/*
  Design tokens: every value in docs/design/tokens.md as a CSS variable on :root, light first and the
  dark column under prefers-color-scheme. Components read these and nothing else; a new value goes in
  tokens.md first and here second.
*/
:root {
  color-scheme: light dark;

  /* Color */
  --canvas: #f3f2ee;
  --surface: #ffffff;
  --ink: #15171a;
  --ink-on-primary: #ffffff;
  --muted: #60656c;
  --tertiary: #a3a6ab;
  --line: #e4e3de;
  --field-edge: #84878c;
  --accent: #2457d6;
  --accent-soft: #e8eefc;
  --tint-identity: #e7dff5;
  --tint-confirm: #dde8e0;
  --status-overdue: #b24b40;
  --status-overdue-soft: #fbeae7;
  --status-attention: #916213;
  --status-attention-soft: #fbf1dc;
  --status-good: #26765d;
  --status-good-soft: #e3f0e8;
  --scrim: rgba(21, 23, 26, 0.32);

  /* Type: the web console's five sizes, 12 / 14 / 17 / 22 / 28 (tokens.md, decided 2026-10-25): 13 and 15 are not used. */
  --font-sans: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", Inter, system-ui, sans-serif;
  --font-serif: "Fraunces", ui-serif, "New York", Georgia, serif;
  --type-display: 28px;
  --type-display-max: 28px;
  --type-title: 22px;
  --type-section: 14px;
  --type-eyebrow: 12px;
  --type-body: 17px;
  --type-secondary: 14px;
  --type-footnote: 14px;
  --leading-display: 34px;
  --leading-title: 28px;
  --leading-section: 20px;
  --leading-eyebrow: 16px;
  --leading-body: 22px;
  --leading-secondary: 20px;
  --leading-footnote: 20px;
  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --tracking-display: -0.02em;
  --tracking-eyebrow: 0.08em;

  /* Shape and space: the 4pt grid. */
  --radius-card: 16px;
  --radius-control: 12px;
  --radius-pill: 999px;
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --tap-min: 44px;
  --tap-capture: 64px;
  --tap-camera: 88px;
  --bar-primary: 56px;
  --shadow: none;
  --border-card: 1px solid var(--line);

  /* Kit metrics that tokens.md fixes in words. */
  --thumb-size: 56px;
  --thumb-radius: 12px;
  --row-height: 56px;
  --banner-min-height: 36px;
  --sidebar-width: 232px;
  --topbar-height: 44px;
  --panel-width: 480px;

  /* Motion: 150 to 250ms ease-out on sheets and list changes only. */
  --motion-fast: 150ms;
  --motion-slow: 250ms;
  --ease-out: cubic-bezier(0, 0, 0.2, 1);
}

@media (prefers-color-scheme: dark) {
  :root {
    --canvas: #121212;
    --surface: #1c1c1e;
    --ink: #f2f2f2;
    --ink-on-primary: #121212;
    --muted: #a1a1aa;
    --tertiary: #6e7075;
    --line: #2c2c2e;
    --field-edge: #76787d;
    --accent: #7aa2ff;
    --accent-soft: #1b2a4a;
    --tint-identity: #2a2438;
    --tint-confirm: #1f2a22;
    --status-overdue: #ff8a7a;
    --status-overdue-soft: #3a1f1b;
    --status-attention: #f2c06b;
    --status-attention-soft: #3a2e12;
    --status-good: #7fd1ae;
    --status-good-soft: #15302a;
  }
}

/*
  The marketing site (docs/specs/site.md). The built stylesheet is the console's tokens.css followed by this file and
  motion.css (apps/site/build.mjs), so every value here is a token. The values the console does not have, the site's
  Hero, Headline, Row title and Figure sizes, are tokens.md's marketing rows and live here because only the site uses
  them. The layout follows the founder's reference, Figma's web-development page: large regular headlines, 120px
  between sections, text beside its picture, hairlines for structure. A name in double braces is an asset the build
  renames with its hash.
*/
@font-face {
  font-family: "Fraunces";
  font-weight: 500;
  font-style: normal;
  font-display: swap;
  src: url("fraunces-500.7975c1ef7c.woff2") format("woff2");
}
@font-face {
  font-family: "Fraunces";
  font-weight: 600;
  font-style: normal;
  font-display: swap;
  src: url("fraunces-600.3a1de7711d.woff2") format("woff2");
}

/* tokens.md, marketing rows: phone first, then 768 and 1024 wide. */
:root {
  --type-hero: 36px;
  --leading-hero: 40px;
  --type-headline: 28px;
  --leading-headline: 34px;
  --type-row: 22px;
  --leading-row: 28px;
  --type-figure: 64px;
  --leading-figure: 64px;
  --gutter: var(--space-4);
  --band: 64px;
  --gap: var(--space-6);
  /* The mat around a screenshot: padding and the 1px edge. */
  --mat: calc(var(--space-4) + 1px);
}
@media (min-width: 600px) {
  :root {
    --gutter: var(--space-5);
  }
}
@media (min-width: 768px) {
  :root {
    --type-hero: 48px;
    --leading-hero: 52px;
    --type-headline: 36px;
    --leading-headline: 40px;
    --type-figure: 96px;
    --leading-figure: 96px;
    --band: 96px;
    --gap: 48px;
  }
}
@media (min-width: 1024px) {
  :root {
    --type-hero: 64px;
    --leading-hero: 68px;
    --type-headline: 48px;
    --leading-headline: 52px;
    --type-row: 28px;
    --leading-row: 34px;
    --type-figure: 128px;
    --leading-figure: 128px;
    --band: 120px;
    --gap: 64px;
  }
}

/* The backdrop's inks (tokens.md: paper, printInk, tape): a print keeps its paper in dark, not the page's canvas, and its
   ink sits a step off the canvas so the print keeps its edge where the photo is dark. */
:root {
  --paper: #EAE8E2;
  --print-ink: #15171A;
  --tape: #E6DCC3;
  --tape-opacity: .9;
}
@media (prefers-color-scheme: dark) {
  :root {
    /* The site's dark canvas is superlogical.com's (the founder, 2026-10-28), a step greener than the console's #121212. */
    --canvas: #10120F;
    --paper: #7C7E82;
    --print-ink: #202024;
    --tape-opacity: .5;
  }
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--canvas);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: var(--type-body);
  line-height: var(--leading-body);
  font-weight: var(--weight-regular);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, p, ol, figure {
  margin: 0;
}
/* Headings wrap in even lines, so a heading never ends on a one-word stub; running text avoids a lone last word. */
h1, h2, h3 {
  text-wrap: balance;
}
p {
  text-wrap: pretty;
}

ol {
  padding: 0;
  list-style: none;
}

img {
  display: block;
  max-width: 100%;
  height: auto;
}

/* Read by a screen reader, not shown. */
.hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* The console's focus ring (apps/console/src/styles/base.css). */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
:focus:not(:focus-visible) {
  outline: none;
}

/* One column of up to 1280px between the gutters. */
.wrap {
  width: 100%;
  max-width: 1328px;
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* A hairline across the whole width marks the top of the page, as on the reference. */
.masthead {
  border-bottom: 1px solid var(--line);
}
.masthead .wrap {
  padding-block: var(--space-5);
}

/* A wordmark, not a heading and not a link: the page is the whole site. */
.wordmark {
  font-family: var(--font-serif);
  font-weight: var(--weight-semibold);
  font-size: var(--type-title);
  line-height: var(--leading-title);
}

/* The hero: one sentence ending in a wheel of what jobs wait on (the founder, 2026-10-28: line A of Penpot page 13,
   after superlogical.com). Set in the page's sans at the Headline sizes, on one line from 768 wide with the drum at its
   end; below 768 the sentence wraps and the drum sits under it. The grid under it is the page's hairline at its own
   faintness; hero.js redraws it on a canvas and bends it under the pointer. Without the script, or with reduced
   motion, this is a still sentence over the flat grid. */
main {
  --wheel-h: 401px;
}
@media (min-width: 768px) {
  main {
    --wheel-h: 441px;
  }
}
.wheel-hero {
  --wheel-cell: 48px;
  --wheel-grid-opacity: .55;
  position: relative;
  border-bottom: 1px solid var(--line);
}
.wheel-stage {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 400px;
  overflow: hidden;
  background-image: linear-gradient(color-mix(in srgb, var(--line) calc(var(--wheel-grid-opacity) * 100%), transparent) 1px, transparent 1px), linear-gradient(90deg, color-mix(in srgb, var(--line) calc(var(--wheel-grid-opacity) * 100%), transparent) 1px, transparent 1px);
  background-size: var(--wheel-cell) var(--wheel-cell);
  background-position: calc(max((100% - 1264px) / 2, 0px) + var(--gutter)) 56px;
}
.wheel-grid {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: none;
  pointer-events: none;
}
.wheel-stage > .wrap {
  position: relative;
}
.wheel-sentence {
  font-family: var(--font-sans);
  font-weight: var(--weight-regular);
  font-size: var(--type-headline);
  line-height: var(--leading-headline);
  letter-spacing: var(--tracking-display);
}
.wheel-slot {
  position: relative;
  display: block;
  margin-top: var(--space-1);
}
.wheel-still {
  color: var(--accent);
}
.wheel-drum {
  position: absolute;
  left: 0;
  top: 50%;
  width: 24ch;
  height: 0;
  perspective: 900px;
  display: none;
}
.wheel-drum span {
  position: absolute;
  left: 0;
  top: 0;
  white-space: nowrap;
  line-height: var(--leading-headline);
  transform-origin: 0 50%;
  backface-visibility: hidden;
  color: var(--muted);
}
.wheel-drum span.on {
  color: var(--accent);
}
.wheel-hint {
  position: absolute;
  right: var(--gutter);
  /* above the fold on arrival, while the masthead still pushes the stage down */
  bottom: 96px;
  margin: 0;
  font-size: var(--type-secondary);
  line-height: var(--leading-secondary);
  color: var(--muted);
  display: none;
}
@media (min-width: 768px) {
  .wheel-hero {
    --wheel-cell: 64px;
  }
  .wheel-stage {
    min-height: 440px;
  }
  .wheel-sentence {
    white-space: nowrap;
  }
  .wheel-slot {
    display: inline-block;
    margin-top: 0;
    vertical-align: bottom;
    min-width: 9ch;
  }
}
@media (min-width: 768px) and (max-width: 1279px) {
  .wheel-sentence {
    font-size: var(--type-row);
    line-height: var(--leading-row);
  }
  .wheel-drum span {
    line-height: var(--leading-row);
  }
}
@media (prefers-color-scheme: dark) {
  .wheel-hero {
    --wheel-grid-opacity: .3;
  }
}
/* With the script: the drum replaces the still word and the canvas the flat grid. Nothing pins: the drum loops as the
   page scrolls, and the mouse wheel turns it while the cursor is on the words (hero.js). */
.wheel-live .wheel-stage {
  background-image: none;
}
.wheel-live .wheel-grid,
.wheel-live .wheel-drum,
.wheel-live .wheel-hint {
  display: block;
}
.wheel-live .wheel-still {
  color: transparent;
}

.hero {
  /* right under the wheel, so the sentence, the lede and the form share the first screen */
  padding-top: var(--space-6);
}

/* The page's one serif sentence (principles rule 1), tracked tight like every display line (rule 17). */
.hero-title {
  max-width: 1000px;
  font-family: var(--font-serif);
  font-weight: var(--weight-medium);
  font-size: var(--type-hero);
  line-height: var(--leading-hero);
  letter-spacing: var(--tracking-display);
}

.lede {
  max-width: 680px;
  margin-top: var(--space-5);
  color: var(--muted);
}
@media (min-width: 768px) {
  .lede {
    font-size: var(--type-title);
    line-height: var(--leading-title);
  }
}

.action {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-3);
  margin-top: var(--space-6);
}

/* The console's PrimaryActionButton as a link: ink fill, white label, the trailing arrow. */
.primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  height: var(--bar-primary);
  padding-inline: var(--space-5);
  border-radius: var(--radius-control);
  background: var(--ink);
  color: var(--ink-on-primary);
  font-size: var(--type-body);
  line-height: var(--leading-body);
  font-weight: var(--weight-semibold);
  text-decoration: none;
}
/* A press lifts the ink one step toward the surface: a state change, no motion (tokens.md, Press states). */
.primary:active {
  background: color-mix(in srgb, var(--ink) 80%, var(--surface));
}

.arrow {
  flex: none;
}

.note {
  font-size: var(--type-secondary);
  line-height: var(--leading-secondary);
  color: var(--muted);
}

@media (max-width: 599px) {
  .action {
    align-items: stretch;
  }
  .primary {
    width: 100%;
  }
}

/* The waitlist form (the founder, 2026-10-28; layout A of docs/design/mock/site-waitlist.html): one Work email field
   and the page's ink button side by side, stacked on a phone; the console's TextField for the field (label above,
   surface fill, 1px fieldEdge, radius.control). The states come back from the Worker inside the form. */
.join {
  margin-top: var(--space-6);
  max-width: 560px;
}
.join-row {
  display: flex;
  align-items: flex-end;
  gap: var(--space-3);
}
.join-field {
  flex: 1;
  min-width: 0;
}
.join-field label {
  display: block;
  margin-bottom: var(--space-2);
  font-size: var(--type-secondary);
  line-height: var(--leading-secondary);
  font-weight: var(--weight-semibold);
}
.join-field input {
  display: block;
  width: 100%;
  height: var(--bar-primary);
  padding-inline: var(--space-4);
  border: 1px solid var(--field-edge);
  border-radius: var(--radius-control);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: var(--type-body);
}
.join-field input::placeholder {
  color: var(--muted);
}
.join-field input[aria-invalid="true"] {
  border-color: var(--status-overdue);
}
.join button.primary {
  flex: none;
  border: 0;
  font-family: inherit;
  cursor: pointer;
}
.join .note {
  margin-top: var(--space-3);
  text-wrap: pretty;
}
.join .join-error {
  margin: var(--space-3) 0 0;
}
/* The honeypot: off screen for people, there for bots that fill every field. */
.trap {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
}
/* The Worker's answers. An error line names what to do; the sent card is the page's one sage card (tokens.md tintConfirm). */
.join-error {
  display: flex;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
  font-size: var(--type-secondary);
  line-height: var(--leading-secondary);
  color: var(--status-overdue);
}
.join-error a {
  color: inherit;
}
.join-sent {
  padding: var(--space-5);
  border-radius: var(--radius-card);
  background: var(--tint-confirm);
}
.join-sent strong {
  display: block;
  font-size: var(--type-body);
  line-height: var(--leading-body);
}
.join-sent p {
  margin-top: var(--space-1);
  font-size: var(--type-secondary);
  line-height: var(--leading-secondary);
  color: var(--muted);
}
@media (max-width: 599px) {
  .join-row {
    flex-direction: column;
    align-items: stretch;
  }
  .join button.primary {
    width: 100%;
  }
}

/* The bar at the foot of the window once the hero has gone (after superlogical.com's): one line and a link back to the
   form. It appears with the scroll, in CSS only; where a browser has no scroll timelines it never shows, and the
   pilot section's button still leads to the form. */
.joinbar {
  display: none;
}
@supports (animation-timeline: scroll()) {
  .joinbar {
    position: fixed;
    left: 50%;
    bottom: var(--space-4);
    z-index: 10;
    display: flex;
    align-items: center;
    gap: var(--space-5);
    width: max-content;
    max-width: calc(100% - 2 * var(--gutter));
    padding: var(--space-2) var(--space-2) var(--space-2) var(--space-5);
    border: var(--border-card);
    border-radius: var(--radius-pill);
    background: var(--surface);
    font-size: var(--type-secondary);
    line-height: var(--leading-secondary);
    transform: translateX(-50%);
    animation: joinbar-in linear both;
    animation-timeline: scroll(root);
    animation-range: 900px 1000px;
  }
  .joinbar a {
    display: inline-flex;
    align-items: center;
    min-height: var(--tap-min);
    padding-inline: var(--space-4);
    border-radius: var(--radius-pill);
    color: var(--accent);
    font-weight: var(--weight-semibold);
    text-decoration: none;
  }
  .joinbar a:active {
    background: var(--accent-soft);
  }
  @keyframes joinbar-in {
    from {
      opacity: 0;
      visibility: hidden;
    }
    to {
      opacity: 1;
      visibility: visible;
    }
  }
  @media (prefers-reduced-motion: reduce) {
    .joinbar {
      animation-timing-function: steps(1, start);
    }
  }
  @media (max-width: 599px) {
    .joinbar p {
      display: none;
    }
  }
  body {
    padding-bottom: 88px;
  }
}

/*
  A screenshot sits on a surface mat inside the card's edge and radius. The console's canvas inside it then reads as a
  picture of the app, not as the page's own controls (the critic, 2026-10-27).
*/
/* clip, not hidden: hidden would make the mat a scroll container, and the outlines' view timelines would then track
   the mat instead of the window and never finish (motion.css). */
.shot {
  padding: var(--space-4);
  overflow: clip;
  border: var(--border-card);
  border-radius: var(--radius-card);
  background: var(--surface);
}
.shot img {
  width: 100%;
}
/* A cut whose subject is a white surface (the brief's document) sits on a canvas mat instead, so its own edge shows;
   a cut of the canvas (the board, the rows, the wait panel, whose background is the canvas) keeps the surface mat. */
.shot-surface {
  background: var(--canvas);
}
.shot-hero {
  margin-top: var(--gap);
}
/* On a phone a shot shown at nearly its own size reads as live controls, so it sits narrower, as a picture. */
@media (max-width: 599px) {
  .shot {
    width: 100%;
    max-width: 320px;
    margin-inline: auto;
  }
}

/* The close-up: two overdue rows, with what each part of a row tells the manager. */
.closeup {
  margin-top: var(--space-6);
}
.closeup-frame {
  position: relative;
}
.closeup-labels {
  margin-bottom: var(--space-3);
}
.closeup-label {
  font-size: var(--type-section);
  line-height: var(--leading-section);
  font-weight: var(--weight-semibold);
}
/* Below 1200 wide the four labels read as one line of phrases, the middle dot between them silent. */
@media (max-width: 1199px) {
  .closeup-labels ol {
    display: flex;
    flex-wrap: wrap;
    column-gap: var(--space-2);
  }
  .closeup-label + .closeup-label::before {
    content: "·" / "";
    margin-right: var(--space-2);
    color: var(--muted);
  }
  .closeup-mark {
    display: none;
  }
}
/*
  From 1200 wide each label sits over its part of the strip, and a 2px ink outline marks that part. Positions are
  shares of the cut (build.mjs, rows-desktop): the Overdue group header, Waiting on, Follows up, Next check-in.
*/
@media (min-width: 1200px) {
  .closeup-labels {
    position: relative;
    height: var(--leading-section);
  }
  .closeup-label {
    position: absolute;
    top: 0;
    left: calc(var(--mat) + (100% - 2 * var(--mat)) * var(--at));
    white-space: nowrap;
  }
  .closeup-label:nth-child(1) { --at: 0.004; }
  .closeup-label:nth-child(2) { --at: 0.426; }
  .closeup-label:nth-child(3) { --at: 0.646; }
  .closeup-label:nth-child(4) { --at: 0.766; }

  .closeup-mark {
    position: absolute;
    border: 2px solid var(--ink);
    border-radius: var(--radius-control);
  }
  .closeup-mark:nth-of-type(1) { left: 0.4%; top: 4%; width: 8.3%; height: 17%; }
  .closeup-mark:nth-of-type(2) { left: 42.6%; top: 22%; width: 14.6%; height: 74%; }
  .closeup-mark:nth-of-type(3) { left: 64.6%; top: 22%; width: 6.2%; height: 74%; }
  .closeup-mark:nth-of-type(4) { left: 76.6%; top: 22%; width: 21.6%; height: 74%; }
}

/*
  The backdrop (docs/specs/site.md, Backdrop; the App Store strip's material, sample E of
  docs/design/website-backdrop-2026-10-28.md): one taped print and one swash, nothing else, and nothing that moves.
*/
/* The print: the photo in grayscale multiplied onto the paper, the ink laid over it with lighten (the two inks), the
   dot screen multiplied over that (3px: the ads' 7px pitch as it shows on a phone), the tape above all of it. If the
   image fails, the paper and the tape remain as a blank taped sheet. */
.print {
  position: relative;
  background: var(--paper);
  isolation: isolate;
}
.print img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 30%;
  filter: grayscale(1) contrast(1.25) brightness(1.05);
  mix-blend-mode: multiply;
}
.print::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: var(--print-ink);
  mix-blend-mode: lighten;
}
.print::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background-image: radial-gradient(rgba(0, 0, 0, .16) .5px, transparent .9px);
  background-size: 3px 3px;
  mix-blend-mode: multiply;
}
/* Masking tape across the print's top edge, half above it, the strip's torn ends (tools/site/backdrop.mjs) and its
   six-degree turn: with the paint, the only thing on the page that tilts. */
.tape {
  position: absolute;
  z-index: 2;
  top: -24px;
  left: 50%;
  width: 200px;
  height: 48px;
  background: var(--tape);
  opacity: var(--tape-opacity);
  transform: translateX(-50%) rotate(-6deg);
  box-shadow: inset 0 0 0 999px rgba(255, 255, 255, .08);
  clip-path: polygon(1.3px 0.0%, 1.2px 14.3%, 3.4px 28.6%, 3.4px 42.9%, 3.9px 57.1%, 3.3px 71.4%, 2.4px 85.7%, 2.4px 100.0%, calc(100% - 2.9px) 100.0%, calc(100% - 1.1px) 85.7%, calc(100% - 3.6px) 71.4%, calc(100% - 1.1px) 57.1%, calc(100% - 0.8px) 42.9%, calc(100% - 0.3px) 28.6%, calc(100% - 2.9px) 14.3%, calc(100% - 3.9px) 0.0%);
}

/* Below 1024 wide the print is a band under "Any update?": a 4:3 cut of the same photo, 24px under the question (the
   section's gap) and 32px above the prose (its margin and the prose's gap). Its tape is smaller to match. */
.print-hero {
  display: none;
}
.print-band {
  width: 100%;
  max-width: 342px;
  justify-self: start;
  margin-top: var(--space-4);
  margin-bottom: var(--space-4);
}
/* Below 600 the band takes the column's width (the 342 cap was the mock's 24px-gutter phone; the site's gutter is 16). */
@media (max-width: 599px) {
  .print-band {
    max-width: none;
  }
}
.print-band img {
  height: auto;
  aspect-ratio: 342 / 256;
  object-position: 50% 35%;
}
.print-band .tape {
  top: -18px;
  width: 140px;
  height: 36px;
}

/* From 1024 wide the hero is a grid: the words, the print whole in a 300px column beside them with its top on the
   title's and its right edge on the column's, and the board under both, 48px below the taller of the two, so the
   board's reveal never crosses the print and nothing overlaps it (the critic, 2026-10-28). The band print leaves. */
@media (min-width: 1024px) {
  .hero {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 300px;
    column-gap: var(--gap);
    align-items: start;
  }
  .hero-text {
    grid-column: 1;
    grid-row: 1;
  }
  .print-hero {
    display: block;
    grid-column: 2;
    grid-row: 1;
    width: 300px;
    height: 400px;
  }
  .shot-hero {
    grid-column: 1 / -1;
    grid-row: 2;
    margin-top: 48px;
  }
  .closeup {
    grid-column: 1 / -1;
    grid-row: 3;
  }
  .print-band {
    display: none;
  }
}

/* The sage swash under the close-up, from 1024 wide and in light only: the strip's paint() as a static SVG, in a layer
   under the page's content (main is the stacking context, so the layer sits above the canvas), emerging at the left
   gutter and 40 to 80px below the close-up's mat, under nothing. main clips it at the page's left edge (clip, never
   hidden: no scroll container, so the view timelines keep tracking the window). */
main {
  position: relative;
  z-index: 0;
  overflow-x: clip;
}

/* The grid and the wash (the founder, 2026-10-28, from three frames: K3 in docs/design/mock/website-backdrop.html).
   Under the hero, a hairline grid in the line colour at half strength, its lines on the content column's left edge
   (the wrap's margin and gutter), fading out through the board; under that, a soft wash of the surface colour at the
   top right, behind the print. Both are gradients in the page's own colours, so they follow the dark scheme, add no
   asset, and never move. The grid is 48px below 768 wide and 64px from there. */
main::before,
main::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  pointer-events: none;
}
main::before {
  z-index: -2;
  /* It starts under the old hero, below the wheel hero, which draws its own grid (the wheel hero's block above). */
  top: var(--wheel-h);
  height: 900px;
  opacity: .55;
  background-image: linear-gradient(var(--line) 1px, transparent 1px), linear-gradient(90deg, var(--line) 1px, transparent 1px);
  background-size: 48px 48px;
  /* The lines land on the content column's left edge: a background-position percentage resolves against the box less
     one tile, so the wrap's 1328 is written as 1264 (1328 - 64; the critic, 2026-10-28). At 1440 that is 80, so the
     column's right edge, the print's and the board's sit on lines too. The rows start 56px down, on the title's and
     the print's top edge, and so on the board's, clear of the masthead's rule and the note's x-height. */
  background-position: calc(max((100% - 1264px) / 2, 0px) + var(--gutter)) 56px;
  -webkit-mask-image: linear-gradient(#000 50%, transparent 100%);
  mask-image: linear-gradient(#000 50%, transparent 100%);
}
main::after {
  z-index: -3;
  height: 1000px;
  background: radial-gradient(70% 60% at 85% 12%, var(--surface) 0%, transparent 70%);
}
@media (min-width: 768px) {
  main::before {
    height: 1180px;
    background-size: 64px 64px;
  }
}
/* The dark line sits twice as far from its canvas as the light one, so the grid takes half the opacity to stay as faint. */
@media (prefers-color-scheme: dark) {
  main::before {
    opacity: .3;
  }
}
@media (min-width: 1024px) and (prefers-color-scheme: light) {
  .closeup {
    position: relative;
  }
  .closeup::before {
    content: "";
    position: absolute;
    left: -266px;
    top: 64px;
    z-index: -1;
    width: 932px;
    height: 247px;
    background: url("swash.1b826ff2f0.svg") no-repeat;
    pointer-events: none;
  }
}

.band {
  padding-top: var(--band);
}

/* Section titles: large and regular, tracked like display type (tokens.md, Headline). */
.headline {
  font-size: var(--type-headline);
  line-height: var(--leading-headline);
  font-weight: var(--weight-regular);
  letter-spacing: var(--tracking-display);
}

/* From 1024 wide a section sets its title in the left column and its content in the right. */
.split {
  display: grid;
  gap: var(--space-5);
}
@media (min-width: 1024px) {
  .split {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    gap: var(--gap);
  }
}

/* About 70 characters a line at 17px. */
.prose {
  display: grid;
  gap: var(--space-4);
  max-width: 560px;
}

/*
  The one sourced figure, set large in the page's own sans with proportional digits (dataviz, hero figure), inside the
  argument it supports. Not a stat tile: rule 2 governs the working screens.
*/
.fact {
  display: grid;
  gap: var(--space-2);
  margin-top: var(--space-4);
  padding-top: var(--space-6);
  border-top: 1px solid var(--line);
}
.fact-n {
  display: block;
  margin-bottom: var(--space-3);
  font-size: var(--type-figure);
  line-height: var(--leading-figure);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-display);
}
@media (min-width: 768px) {
  .fact-line {
    font-size: var(--type-title);
    line-height: var(--leading-title);
  }
}
.fact-source {
  font-size: var(--type-secondary);
  line-height: var(--leading-secondary);
  color: var(--muted);
}

.intro .lede {
  margin-top: var(--space-4);
}

.rows {
  display: grid;
  gap: var(--band);
  margin-top: var(--gap);
}

/* A feature row: the words beside their picture from 1024 wide, above it below that. */
.row {
  display: grid;
  gap: var(--space-5);
}
/* A row's shot is a cut of the screen, never shown larger than its own size: centred under the words below 1024 wide,
   against the right edge beside them from 1024, as on the reference. */
.row:nth-child(1) .shot { --shot-width: 559px; }
.row:nth-child(2) .shot { --shot-width: 760px; }
@media (min-width: 600px) {
  .row .shot {
    justify-self: center;
    width: 100%;
    max-width: calc(var(--shot-width) + 2 * var(--mat));
  }
}
@media (min-width: 1024px) {
  .row {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    align-items: center;
    gap: var(--gap);
  }
  .row .shot {
    justify-self: end;
  }
}

.row-title {
  font-size: var(--type-row);
  line-height: var(--leading-row);
  font-weight: var(--weight-regular);
}

.row-text p {
  max-width: 480px;
  margin-top: var(--space-3);
}

/* Answers as a list with hairlines between them. */
.qa {
  padding-block: var(--space-5);
  border-top: 1px solid var(--line);
}
.qa:last-child {
  border-bottom: 1px solid var(--line);
}
.qa h3 {
  font-size: var(--type-body);
  line-height: var(--leading-body);
  font-weight: var(--weight-semibold);
}
.qa p {
  max-width: 560px;
  margin-top: var(--space-2);
}

/*
  The pilot is a note from a person: the page's one tinted card, the identity lavender (rule 15), beside its title,
  with the founder named the way the console's IdentityCard names someone.
*/
.pilot {
  display: grid;
  gap: var(--space-5);
  padding: var(--space-6);
  border-radius: var(--radius-card);
  background: var(--tint-identity);
}
.pilot p {
  max-width: 560px;
}
.person {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}
.initials {
  flex: none;
  display: grid;
  place-items: center;
  width: var(--tap-min);
  height: var(--tap-min);
  border-radius: 50%;
  background: var(--surface);
  color: var(--ink);
  font-size: var(--type-secondary);
  font-weight: var(--weight-semibold);
}
.person-text {
  display: flex;
  flex-direction: column;
}
.person-name {
  font-weight: var(--weight-semibold);
}
.person-role {
  font-size: var(--type-secondary);
  line-height: var(--leading-secondary);
  color: var(--muted);
}
.pilot .action {
  margin-top: 0;
}

.footer {
  margin-top: var(--band);
  border-top: 1px solid var(--line);
}
.footer-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding-block: var(--space-5);
}

/* A plain link at the full tap height; pressed, it darkens toward the ink (tokens.md, Press states). */
.mail {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap-min);
  color: var(--accent);
  text-decoration: none;
}
.mail:hover {
  text-decoration: underline;
}
.mail:active {
  color: color-mix(in srgb, var(--accent) 70%, var(--ink));
}

/*
  The walk-through (docs/specs/site-demo.md): six real screens a visitor clicks through, with no script. One radio per
  step, read but not seen; the step whose radio is checked shows; every hotspot and every title in the step row is a
  label for a step's radio, so a click changes the step with no scroll and no history entry. The radios are the
  section's first children, before .demo-scenes, so `:checked ~` reaches the steps.
*/
.demo {
  position: relative;
  margin-top: var(--gap);
}
/* Fixed inside the window: a click on a label focuses its radio, and a radio above the window made the browser scroll
   the page to it (450px on the live page, 2026-10-28). Fixed, it is always in view, so focus never scrolls. */
.demo > input {
  position: fixed;
  top: 50%;
  left: 0;
  width: 1px;
  height: 1px;
  margin: 0;
  overflow: hidden;
  clip-path: inset(50%);
}
/* While a step radio has the keyboard, the picture carries the focus ring. */
.demo > input:focus-visible ~ .demo-scenes .shot {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
}

/* The step row: every step's title as a tab on a hairline, the current one in ink with a 2px rule under it (Apple's
   tabs, this page's hairlines); it is also the way back. 44px tall. */
.demo-nav {
  display: flex;
  flex-wrap: wrap;
  column-gap: var(--space-5);
  border-bottom: 1px solid var(--line);
  font-size: var(--type-secondary);
  line-height: var(--leading-secondary);
  color: var(--muted);
}
.demo-nav label {
  padding-block: var(--space-3);
  cursor: pointer;
}
.demo-nav label:hover {
  color: var(--ink);
}
.demo-nav label:active {
  color: var(--ink);
  text-decoration: underline;
}
#d1:checked ~ .demo-scenes .demo-nav [for="d1"],
#d2:checked ~ .demo-scenes .demo-nav [for="d2"],
#d3:checked ~ .demo-scenes .demo-nav [for="d3"],
#d4:checked ~ .demo-scenes .demo-nav [for="d4"],
#d5:checked ~ .demo-scenes .demo-nav [for="d5"],
#d6:checked ~ .demo-scenes .demo-nav [for="d6"] {
  color: var(--ink);
  font-weight: var(--weight-medium);
  box-shadow: inset 0 -2px var(--ink);
}

/*
  The six steps share one grid cell, every one laid out, so every picture loads with the section and a click never
  shows an empty mat (the founder, 2026-10-28: a step went black for a moment before the next one appeared). The step
  shown is on top and fades in over the one before, which stays whole underneath until the fade ends and is then
  hidden; its caption hides at once, so two captions never overlap. The ring settles in last. Hidden steps are
  visibility: hidden, so their labels can't be clicked, focused or read. Under reduced motion it all changes at once.
*/
.demo-scenes {
  display: grid;
}
.demo-step {
  grid-area: 2 / 1;
  z-index: 0;
  visibility: hidden;
  opacity: 0;
  transition: opacity 0s 240ms, visibility 0s 240ms;
}
.demo-step .demo-caption {
  opacity: 0;
}
.demo-step .demo-mark {
  opacity: 0;
  transform: scale(1.03);
}
#d1:checked ~ .demo-scenes .demo-step-1,
#d2:checked ~ .demo-scenes .demo-step-2,
#d3:checked ~ .demo-scenes .demo-step-3,
#d4:checked ~ .demo-scenes .demo-step-4,
#d5:checked ~ .demo-scenes .demo-step-5,
#d6:checked ~ .demo-scenes .demo-step-6 {
  z-index: 1;
  visibility: visible;
  opacity: 1;
  transition: opacity 240ms cubic-bezier(0.2, 0.7, 0.2, 1), visibility 0s;
}
#d1:checked ~ .demo-scenes .demo-step-1 :is(.demo-caption, .demo-mark),
#d2:checked ~ .demo-scenes .demo-step-2 :is(.demo-caption, .demo-mark),
#d3:checked ~ .demo-scenes .demo-step-3 :is(.demo-caption, .demo-mark),
#d4:checked ~ .demo-scenes .demo-step-4 :is(.demo-caption, .demo-mark),
#d5:checked ~ .demo-scenes .demo-step-5 :is(.demo-caption, .demo-mark),
#d6:checked ~ .demo-scenes .demo-step-6 :is(.demo-caption, .demo-mark) {
  opacity: 1;
  transform: none;
}
#d1:checked ~ .demo-scenes .demo-step-1 .demo-caption,
#d2:checked ~ .demo-scenes .demo-step-2 .demo-caption,
#d3:checked ~ .demo-scenes .demo-step-3 .demo-caption,
#d4:checked ~ .demo-scenes .demo-step-4 .demo-caption,
#d5:checked ~ .demo-scenes .demo-step-5 .demo-caption,
#d6:checked ~ .demo-scenes .demo-step-6 .demo-caption {
  transition: opacity 200ms ease-out 60ms;
}
#d1:checked ~ .demo-scenes .demo-step-1 .demo-mark,
#d2:checked ~ .demo-scenes .demo-step-2 .demo-mark,
#d3:checked ~ .demo-scenes .demo-step-3 .demo-mark,
#d4:checked ~ .demo-scenes .demo-step-4 .demo-mark,
#d5:checked ~ .demo-scenes .demo-step-5 .demo-mark,
#d6:checked ~ .demo-scenes .demo-step-6 .demo-mark {
  transition: opacity 200ms ease-out 180ms, transform 220ms cubic-bezier(0.2, 0.7, 0.2, 1) 180ms;
}
.demo-nav label {
  transition: color 150ms ease-out, box-shadow 150ms ease-out;
}
@media (prefers-reduced-motion: reduce) {
  .demo-step,
  .demo-step .demo-caption,
  .demo-step .demo-mark,
  .demo-nav label {
    /* !important: the shown step's transition rules are more specific. */
    transition: none !important;
  }
}

/* The caption comes before the picture, so the instruction and the control are on screen together; two lines tall
   at least (three on a phone, where captions 4 and 6 run to three), so the mat never moves between steps. */
.demo-caption {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2) var(--space-4);
  min-height: var(--tap-min);
  max-width: 560px;
  margin-top: var(--space-4);
  margin-bottom: var(--space-4);
}
.demo-caption p {
  text-wrap: balance;
}
/* Caption 4 ends differently on a phone, where the ring is on the panel's Close and the brief is in the menu (the
   founder, 2026-10-28, decision 7 of docs/specs/site-demo.md). The hidden ending is display: none, so a screen reader
   hears one ending. */
.demo-narrow {
  display: none;
}
@media (max-width: 599px) {
  .demo-wide {
    display: none;
  }
  .demo-narrow {
    display: inline;
  }
}
.demo-again {
  color: var(--accent);
  cursor: pointer;
}
.demo-again:hover {
  text-decoration: underline;
}
.demo-again:active {
  color: color-mix(in srgb, var(--accent) 70%, var(--ink));
}

/* The walk-through's picture keeps the wrap's width on a phone: its hotspots need the room. */
@media (max-width: 599px) {
  .demo .shot {
    max-width: none;
  }
  .demo-caption {
    min-height: 76px;
  }
}
.demo-frame {
  position: relative;
}
/*
  The control a manager would click, as a share of the picture (--mx, --my, --mw, --mh, set per step below, one set
  for the desktop render and one for the phone's). The ring sits 8px outside it, its radius the control's plus that
  air. The label is the hit area: the ring's box, or the larger area the console itself accepts the click on where a
  step sets one (--hx, --hy, --hw, --hh: step 2's whole row), and 44px at least, centred on it.
*/
.demo-hot {
  position: absolute;
  left: calc(var(--hx, var(--mx)) + var(--hw, var(--mw)) / 2);
  top: calc(var(--hy, var(--my)) + var(--hh, var(--mh)) / 2);
  width: max(calc(var(--hw, var(--mw)) + 16px), var(--tap-min));
  height: max(calc(var(--hh, var(--mh)) + 16px), var(--tap-min));
  transform: translate(-50%, -50%);
  cursor: pointer;
}
.demo-mark {
  position: absolute;
  left: calc(var(--mx) - 8px);
  top: calc(var(--my) - 8px);
  width: calc(var(--mw) + 16px);
  height: calc(var(--mh) + 16px);
  border: 2px solid var(--ink);
  border-radius: var(--r, 20px);
  pointer-events: none;
}
/* Hover tints the ring's inside; a press thickens it: a state change, no motion. */
.demo-hot:hover + .demo-mark {
  background: color-mix(in srgb, var(--ink) 6%, transparent);
}
.demo-hot:active + .demo-mark {
  border-width: 3px;
}

/*
  Where each control sits, measured in the running console (the renders are the viewport): the desktop render, 1440
  by 900, then the phone's, 390 by 844. Step 1: Review in the sidebar; step 2: the row's Review link, with the whole
  row as the hit area, as in the console (on the phone the row has no Review word, so the ring runs from Alex's line
  to the row's chevron); step 3: Accept; step 4: Weekly brief in the sidebar; step 5: Copy. On the phone the sidebar
  is behind the Menu button and a panel covers the screen, so step 1 marks Menu's glyph and step 4 the panel's Close,
  the first tap of each move; the caption names where it lands.
*/
.demo-step-1 .demo-frame { --mx: 0.83%; --my: 12.89%; --mw: 14.37%; --mh: 4.89%; --r: 20px; }
.demo-step-2 .demo-frame { --mx: 94.44%; --my: 35.89%; --mw: 3.33%; --mh: 2.22%; --r: 12px; --hx: 17.5%; --hy: 34.33%; --hw: 81.11%; --hh: 18%; }
.demo-step-3 .demo-frame { --mx: 54.6%; --my: 93.39%; --mw: 9.05%; --mh: 5.33%; --r: 20px; }
.demo-step-4 .demo-frame { --mx: 0.83%; --my: 18%; --mw: 14.37%; --mh: 4.89%; --r: 20px; }
.demo-step-5 .demo-frame { --mx: 45%; --my: 10%; --mw: 7.46%; --mh: 4.89%; --r: 20px; }
@media (max-width: 599px) {
  .demo-step-1 .demo-frame { --mx: 2.05%; --my: 0.95%; --mw: 9.2%; --mh: 3.3%; --r: 20px; }
  .demo-step-2 .demo-frame { --mx: 33.85%; --my: 57.23%; --mw: 62.1%; --mh: 13.03%; --r: 20px; --hx: 1.03%; --hy: 55.81%; --hw: 97.95%; --hh: 36.02%; }
  .demo-step-3 .demo-frame { --mx: 4.1%; --my: 85.78%; --mw: 91.79%; --mh: 6.64%; --r: 20px; }
  .demo-step-4 .demo-frame { --mx: 85.64%; --my: 9.95%; --mw: 11.28%; --mh: 5.21%; --r: 30px; }
  .demo-step-5 .demo-frame { --mx: 4.1%; --my: 91.47%; --mw: 91.79%; --mh: 6.64%; --r: 20px; }
}

/*
  The site's scroll motion (CLAUDE.md, "Website": the one exception to the motion rule, after the founder asked for an
  apple.com feel when scrolling down). Every effect runs on a CSS view timeline, so the browser drives it from the
  scroll position with no script and no scroll events, and only transform and opacity move (fixing-motion-performance).
  Where a browser has no view timelines, or the reader asks for reduced motion, none of this applies and the page is
  still. build.mjs appends this file after site.css. tools/site/shoot.mjs checks every block below settles in view;
  keep its MOVED list the same as these selectors.
*/
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    /* Each block fades up over its first 240px in view, whatever its height, so tall blocks never read half faded. */
    @keyframes site-rise {
      from {
        opacity: 0;
        transform: translateY(32px);
      }
      to {
        opacity: 1;
        transform: none;
      }
    }

    /* The board rises and grows into place as the page scrolls toward it, as a product shot does on apple.com. */
    @keyframes site-settle {
      from {
        transform: translateY(48px) scale(0.92);
      }
      to {
        transform: none;
      }
    }

    /* The sourced figure grows from its baseline as it comes into view. */
    @keyframes site-figure {
      from {
        opacity: 0;
        transform: scale(0.8);
      }
      to {
        opacity: 1;
        transform: none;
      }
    }

    /* A close-up label or outline appears where it points. */
    @keyframes site-appear {
      from {
        opacity: 0;
        transform: translateY(8px);
      }
      to {
        opacity: 1;
        transform: none;
      }
    }

    /* Scaled from its top left, the board keeps its left edge on the text's edge while it grows. */
    .shot-hero {
      transform-origin: left top;
      animation: site-settle linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 40%;
    }

    .closeup-shot,
    .split > .headline,
    .split > .prose,
    .split > .answers > .qa,
    .split > .pilot,
    .intro > *,
    .row > * {
      animation: site-rise var(--ease-out) both;
      animation-timeline: view();
      animation-range: entry 0% entry 240px;
    }

    .fact-n {
      transform-origin: left bottom;
      animation: site-figure var(--ease-out) both;
      animation-timeline: view();
      animation-range: entry 0% cover 40%;
    }

    /* Below 1200 the labels are one line of phrases and rise together. */
    @media (max-width: 1199px) {
      .closeup-labels {
        animation: site-rise var(--ease-out) both;
        animation-timeline: view();
        animation-range: entry 0% entry 240px;
      }
    }

    /* From 1200 each label and its outline appear in turn, 60px of scroll apart, left to right. */
    @media (min-width: 1200px) {
      .closeup-label,
      .closeup-mark {
        animation: site-appear var(--ease-out) both;
        animation-timeline: view();
      }
      .closeup-label:nth-child(1), .closeup-mark:nth-of-type(1) { animation-range: entry 0% entry 160px; }
      .closeup-label:nth-child(2), .closeup-mark:nth-of-type(2) { animation-range: entry 60px entry 220px; }
      .closeup-label:nth-child(3), .closeup-mark:nth-of-type(3) { animation-range: entry 120px entry 280px; }
      .closeup-label:nth-child(4), .closeup-mark:nth-of-type(4) { animation-range: entry 180px entry 340px; }
    }
  }
}
