# Heyz page composition template · v2

Use this brief before building a page in the connected Heyz world. The reference specimen is `/brand#composition`; canonical `--heyz-*` tokens live in `app/design-tokens.css`. The same visual system applies to the public site and product screens. Use semantic aliases for ordinary controls.

## Page brief

- **Person and audience:** who starts the work, and who may read the result?
- **Artifact:** what is being made, revised or published?
- **Authority:** which human chooses the exact revision and readership, and who may request agent work?
- **Title:** a short, literal publishing proposition or task description.
- **Context:** one or two sentences about the work and next decision.
- **Primary action:** one verb and one real destination or handler.
- **Secondary action:** a different intent, with lower emphasis.
- **States:** loading, empty, complete, validation error, permission error and unavailable.

## Composition

1. Shared navigation and a terracotta Portal wordmark with its exact source geometry.
2. A first screen with one human-readable promise: **Your agents make it. Heyz brings it to people.** The supporting line is **Create with agents. Publish for people.**
3. A readable artifact with its title, exact revision, people and agent identities. Keep its conversation and review action in context. The written narrative carries the same meaning without media.
4. One forest primary action and one quieter secondary action, each with a real destination.
5. Six scenes in reading order: Elena's brief, report revision, human publication decision, Response Team reading and conversation, a **separate** explicit request to update an IT morning brief, then human review and publication. Keep proposed drafts separate from the revision readers receive.
6. Exact authority, revision and readers near the relevant decision; status and permission information next to the action it affects.
7. A clear close and shared footer. Narrow screens stack copy and scene imagery in the same narrative order.

As of 2026-09-27, public copy describes the human-requested workflow. Standing
internal agent publication in [M24](../decisions/2026-09-26-M24-scoped-internal-agent-publication.md)
remains gated roadmap work. It must not appear as an available capability before
its verification, activation and required legal review.

## Visual implementation

- Use the shared `BrandMark`, `Button` and `Input` where suitable; use semantic CSS variables for product UI and `--heyz-*` tokens for named brand materials.
- Warm chalk is the default canvas; forest is the structure and primary action; paper holds artifacts; terracotta is the Portal and decorative material. Use `--heyz-terracotta-text` for readable accent words.
- Use the softer D direction: generous space, readable paper surfaces, quiet separators and explicit human and agent identities. Reuse the radius tokens for controls and panels. Final hero composition and media wait for an actual product recording; earlier illustrations remain comparison material.
- `--landing-*` remains a compatibility alias for the first landing implementation. New pages use `--heyz-*`.
- Space with the 4px scale: 8px within a control, 16px within a group, 24–32px between groups, 64–96px between major sections.
- Keep headings sentence case; Inter 400–600 for text, JetBrains Mono for code and small technical labels.
- On narrow screens, keep 20px outer gutters, stack grids and preserve reading order. The full story must remain available without scroll-scrubbing, JavaScript or motion.

## Done means

- Every link and button has a real destination or behavior.
- Fields have persistent labels, useful help and accessible error messages.
- Tab through the page; focus is visible and never covered.
- Verify at 320px and desktop widths, 200% zoom and reduced motion.
- Check empty, error and success states; do not communicate status through color alone.
- Review the rendered page in Chromium and WebKit. The site mark uses the original Portal geometry and v2 terracotta fill; legacy downloadable assets retain their original colors.
- Run `npm run brand:check` after changing brand source files.

## Copyable starting point

This server component uses the shared navigation/footer from the app layout. It is a static, readable foundation for the publishing story. Copy it into a route, keep one `h1`, and replace the actor, artifact, audience and real destinations together. The committed `public/scroll-world/illustrated-v2/looks/01-incident-intent.webp` below is an earlier static scene study, not the final hero or evidence of working collaboration. Replace it with verified product capture when available.

```tsx
import Image from "next/image";
import Link from "next/link";
import { Button } from "@/components/ui/button";
import styles from "./page.module.css";

export default function Page() {
  return (
    <main className={styles.page}>
      <header className={styles.introduction}>
        <div>
          <p className={styles.eyebrow}>Heyz / Publishing world</p>
          <h1>Your agents make it. Heyz brings it to people.</h1>
          <p className={styles.subhead}>
            Create with agents. Publish for people.
          </p>
          <p>
            Give your agent the brief, shape the work together, then share the
            exact result with the people you choose.
          </p>
          <Button asChild size="lg">
            <Link href="#journey">See the publishing journey</Link>
          </Button>
          <Link className={styles.secondaryAction} href="/docs/agents">
            Bring your agent
          </Link>
        </div>
        <figure className={styles.scene}>
          <Image
            src="/scroll-world/illustrated-v2/looks/01-incident-intent.webp"
            alt="An illustrated miniature workspace where Elena briefs her agent beside a cream incident report."
            width={1672}
            height={941}
            loading="eager"
            fetchPriority="high"
            unoptimized
          />
          <figcaption>Illustrated world / 01 Brief</figcaption>
        </figure>
      </header>
      <section
        id="journey"
        className={styles.content}
        aria-labelledby="journey-title"
      >
        <h2 id="journey-title">From a brief to the right readers.</h2>
        <ol>
          <li>Elena briefs her agent on an incident report.</li>
          <li>
            She reviews a clearer revision with a timeline and next steps.
          </li>
          <li>She chooses that exact revision for the Response Team.</li>
          <li>
            Contributors continue the report conversation with each other and
            the agent.
          </li>
          <li>
            Maya sends an explicit request to an authorized agent for a
            separate IT morning brief.
          </li>
          <li>
            Maya reviews the draft and publishes the exact revision. Earlier
            revisions and the conversation remain available.
          </li>
        </ol>
      </section>
    </main>
  );
}
```

Companion `page.module.css`:

```css
.page {
  background: var(--heyz-canvas);
  color: var(--heyz-forest);
  padding: 48px max(20px, calc((100vw - var(--content-width)) / 2)) 96px;
}
.introduction {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 40px;
  align-items: center;
}
.scene {
  margin: 0;
}
.scene img {
  width: 100%;
  height: auto;
  border-radius: var(--radius-large);
}
.scene figcaption {
  margin-top: 10px;
  color: var(--heyz-secondary-ink);
  font: 600 11px/1.4 var(--font-mono);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.introduction h1 {
  font-size: clamp(44px, 4.5vw, 72px);
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -0.07em;
  overflow-wrap: break-word;
}
.introduction p,
.content p {
  color: var(--heyz-secondary-ink);
  line-height: 1.6;
  margin-block: 18px;
}
.introduction .eyebrow {
  color: var(--heyz-terracotta-text);
  font: 600 11px var(--font-mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.introduction .subhead {
  color: var(--heyz-forest);
  font-weight: 600;
}
.introduction a {
  min-height: 44px;
}
.secondaryAction {
  display: inline-flex;
  align-items: center;
  margin-left: 18px;
  color: var(--heyz-forest);
}
.content {
  max-width: var(--reading-width);
  margin-top: 72px;
}
.content h2 {
  font-size: 32px;
  font-weight: 600;
}
.content li {
  margin-top: 16px;
  line-height: 1.6;
}
.page a:focus-visible {
  outline: 3px solid var(--heyz-forest);
  outline-offset: 4px;
}
.introduction [data-slot="button"]:focus-visible {
  outline-color: var(--heyz-paper);
  box-shadow: 0 0 0 5px var(--heyz-forest);
}
@media (max-width: 760px) {
  .page {
    padding: 32px 20px 64px;
  }
  .introduction {
    grid-template-columns: 1fr;
    gap: 20px;
  }
  .secondaryAction {
    margin: 12px 0 0;
  }
}
```

For a form, use the live `/brand#components` specimen as the companion pattern: persistent label, connected help, `aria-invalid`, an error message and an announced result. Keep a real loading/empty/error state next to the relevant content as soon as the page depends on data.
