/* SessionHUD launch page.
 *
 * Every color, space and radius comes from tokens.css. Nothing here invents one — the
 * depicted HUD panels in particular draw only from the --hud-* tokens, because
 * the product's promise is that its output is brand-neutral on every surface. The brand
 * gradient is page chrome and stays outside the panels.
 *
 * The block below is the one exception, and it is layout rather than color: the app's
 * spacing tokens top out at 32 px because they space a HUD, and a page needs section rhythm
 * and a reading column the HUD never has. They are declared once, here, and named for the
 * page so nobody mistakes them for a mirror of TokenValues.
 */

:root {
  --page-max: 1120px;
  --page-gutter: clamp(20px, 4vw, 40px);
  --section-space: clamp(3.5rem, 8vw, 6.5rem);
  --measure: 40rem;
  --doc-nav-width: 11rem;
  --rule: 1px solid rgb(var(--brand-paper-rgb) / 0.09);
  --text-quiet: rgb(var(--brand-paper-rgb) / 0.72);
  --text-faint: rgb(var(--brand-paper-rgb) / 0.58);
  color-scheme: dark;
  scrollbar-color: rgb(var(--brand-paper-rgb) / 0.22) var(--brand-ink);
}

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

html { -webkit-text-size-adjust: 100%; scroll-padding-top: var(--space-xl); }

body {
  margin: 0;
  background: var(--brand-ink);
  color: var(--brand-paper);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  caret-color: var(--brand-cyan);
}

/* The hero's glow reaches past the right edge on purpose. Clipping it here, at a full-width
   element, keeps it from widening a phone's layout viewport; `clip` rather than `hidden`
   because a scroll container would break the docs' sticky contents. */
main { overflow-x: clip; }

::selection { background: rgb(var(--brand-violet-rgb) / 0.55); color: var(--brand-paper); }

h1, h2, h3 {
  line-height: 1.12; letter-spacing: -0.022em; margin: 0 0 var(--space-md);
  text-wrap: balance;
}
h1 { font-size: clamp(2.4rem, 5vw, 3.5rem); letter-spacing: -0.03em; }
h2 { font-size: clamp(1.7rem, 3.2vw, 2.4rem); }
h3 { font-size: 1.125rem; line-height: 1.3; letter-spacing: -0.01em; }
p { margin: 0 0 var(--space-md); max-width: 62ch; text-wrap: pretty; }
strong { font-weight: 650; }

a {
  color: inherit;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
  text-decoration-color: rgb(var(--brand-paper-rgb) / 0.4);
  transition: text-decoration-color 150ms ease-out, opacity 150ms ease-out;
}
a:hover { text-decoration-color: var(--brand-cyan); }
a:focus-visible, .button:focus-visible {
  outline: 2px solid var(--brand-cyan);
  outline-offset: 3px;
  border-radius: var(--radius-small);
}
/* A code block or table that scrolls sideways is a tab stop (`tabindex="0"` in the markup), or a
   keyboard cannot reach what is past its edge — WCAG 2.1.1. The ring sits inside, because these
   boxes run to the column's edge and an outer ring is cut by `main { overflow-x: clip }`. */
pre[tabindex]:focus-visible, .table-scroll:focus-visible {
  outline: 2px solid var(--brand-cyan);
  outline-offset: -2px;
}

code, kbd {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.86em;
  padding: 0.1em 0.38em;
  border-radius: var(--radius-small);
  background: rgb(var(--brand-paper-rgb) / 0.07);
}
kbd { border: 1px solid rgb(var(--brand-paper-rgb) / 0.18); background: none; }

.skip {
  position: absolute; left: var(--space-md); top: -4rem; z-index: 10;
  background: var(--brand-paper); color: var(--brand-ink);
  padding: var(--space-sm) var(--space-md); border-radius: var(--radius-small);
  text-decoration: none; transition: top 120ms ease;
}
.skip:focus { top: var(--space-md); }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

/* ---------- chrome ---------- */

.site-header {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-md) var(--space-lg);
  max-width: var(--page-max); margin: 0 auto;
  padding: var(--space-lg) var(--page-gutter);
  flex-wrap: wrap;
}
.lockup { border-radius: var(--radius-small); }
.lockup img { display: block; width: 168px; height: auto; }
.site-header nav { display: flex; align-items: center; gap: var(--space-lg); }
.site-header nav a:not(.button) {
  text-decoration: none; color: var(--text-quiet); font-size: 0.9375rem; white-space: nowrap;
}
.site-header nav a:not(.button):hover,
.site-header nav a[aria-current="page"] { color: var(--brand-paper); }

/* A phone gets one row of links and the button beside them, not three stacked rows before
   the headline. */
@media (max-width: 559px) {
  .site-header { padding-top: var(--space-md); }
  .lockup img { width: 148px; }
  .site-header nav { width: 100%; gap: var(--space-sm) var(--space-md); flex-wrap: wrap; }
  .site-header nav .button { margin-left: auto; padding: 0.45rem 0.8rem; font-size: 0.875rem; }
  .site-header nav a:not(.button) { font-size: 0.875rem; }
}
/* With Features in the row, four links and the button no longer fit a 375-point phone, and the
   button dropped to a third row. Account goes first: a returning customer finds it in the footer,
   and a first-time visitor has none. */
@media (max-width: 429px) {
  .site-header nav a[href="/account"] { display: none; }
}

.button {
  display: inline-block; text-decoration: none; white-space: nowrap;
  padding: 0.6rem 1.1rem; border-radius: var(--radius-medium);
  border: 1px solid rgb(var(--brand-paper-rgb) / 0.24);
  font-weight: 600; font-size: 0.9375rem; line-height: 1.3;
  transition: border-color 150ms ease-out, filter 150ms ease-out, transform 150ms ease-out;
}
.button:hover { border-color: rgb(var(--brand-paper-rgb) / 0.55); }
.button:active { transform: translateY(1px); }

/* Ink on the gradient's violet end is 4.37:1, under the 4.5:1 normal text needs, and the
   gradient only clears it once its first stop is nearly half indigo. So the gradient stays the
   brand's and the label is large text instead: 19 px bold needs 3:1. */
.button-primary {
  background: var(--brand-gradient);
  color: var(--brand-ink);
  border: 0;
  padding: 0.75rem 1.4rem;
  font-size: 1.1875rem;
  font-weight: 700;
}
.button-primary:hover { filter: brightness(1.08); }

.quiet-link { font-size: 0.9375rem; color: var(--text-quiet); }
.quiet-link:hover { color: var(--brand-paper); }

.actions {
  display: flex; align-items: center; gap: var(--space-md) var(--space-xl);
  flex-wrap: wrap; max-width: none; margin: var(--space-xl) 0 var(--space-md);
}

.price {
  font-size: 0.9375rem;
  color: var(--text-quiet);
  margin: var(--space-lg) 0 0;
  max-width: 54ch;
}
.price strong { color: var(--brand-paper); }
/* The standard price, struck, beside the launch price: the discount is read as a comparison the
   visitor makes, not a claim the page makes. Faint so the price that is charged stays the loud one. */
.price-was, .plan-was {
  color: var(--text-faint); text-decoration-thickness: 1.5px;
  font-variant-numeric: tabular-nums;
}
.price .price-launch { color: var(--brand-cyan); }

/* ---------- layout ---------- */

.hero, .band {
  max-width: var(--page-max); margin: 0 auto;
  padding: var(--section-space) var(--page-gutter);
}
.band { border-top: var(--rule); }

.hero {
  display: grid; gap: clamp(2.5rem, 6vw, 5rem);
  grid-template-columns: minmax(0, 1fr);
  align-items: center;
  padding-top: clamp(2.5rem, 6vw, 5rem);
}
@media (min-width: 900px) {
  .hero { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); }
}
.hero h1 { margin-bottom: var(--space-lg); }
.hero-copy > p:not(.lede):not(.price):not(.fine):not(.actions) { color: var(--text-quiet); }

.lede { font-size: 1.25rem; line-height: 1.5; color: rgb(var(--brand-paper-rgb) / 0.92); }
/* 52ch, not the body's 62ch: a ch is a zero, wider than the average letter, so 62ch at this
   size ran about 90 characters a line. */
.section-lede {
  font-size: 1.125rem; color: var(--text-quiet); max-width: 52ch;
  margin-bottom: clamp(2rem, 4vw, 3rem);
}
.section-lede:has(+ .section-lede) { margin-bottom: 1em; }

/* A band whose content is prose: the heading holds the left column and the text reads in the
   right one, instead of one narrow column leaving half of a wide screen empty. */
@media (min-width: 900px) {
  .band-split {
    display: grid; align-items: start;
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    column-gap: clamp(2.5rem, 6vw, 5rem);
  }
  .band-split .section-lede { margin-bottom: 0; }
}

/* ---------- cards, facts ---------- */

.facts { padding: 0; }
.facts { list-style: none; margin: 0; }

/* One output per row, picture and words side by side and alternating, so each picture is big
   enough to read the take number in. */
/* Four outputs, one moment: a 2 × 2 grid from tablet width, so all four are on screen together and
   visibly agree. Every card is a 16:10 picture over its copy, so the four pictures share one size
   and the copy lines up across each row. */
.output-grid {
  display: grid; gap: clamp(2.5rem, 5vw, 3.5rem) clamp(1.5rem, 3vw, 2.5rem);
  margin-top: clamp(1.5rem, 3vw, 2.5rem);
}
@media (min-width: 760px) {
  .output-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.output-media { position: relative; aspect-ratio: 16 / 10; margin: 0; }
.output-media > img { display: block; width: 100%; height: 100%; }
/* A captured window carries its own rounded corners and edge; it only needs lifting off the page.
   Contained, so no part of the window is cut off. */
.output-window {
  object-fit: contain;
  filter: drop-shadow(0 18px 30px rgb(var(--hud-background-rgb) / 0.55));
}
/* The booth photograph is 16:9 and fills its box; the trim is a few percent off each side, clear of
   both the actor and the HUD. */
.output-photo { object-fit: cover; border-radius: var(--radius-medium); }
/* Below the booth monitor's stand, which hangs under its box, and the same on every card so the
   copy lines up across a row. */
.output-copy { margin-top: calc(var(--space-lg) + var(--space-md) + 4px); }
.output-copy h3 { font-size: 1.375rem; margin-bottom: var(--space-sm); }
.output-copy p { margin: 0; color: var(--text-quiet); max-width: 42ch; }
.output-copy .output-note { margin-top: var(--space-md); font-size: 0.8125rem; color: var(--text-faint); }
.output-copy .output-more { margin-top: var(--space-md); font-size: 0.9375rem; }
.output-copy .output-more a { color: var(--brand-paper); }

.facts li {
  max-width: 62ch; color: var(--text-quiet);
  padding: var(--space-lg) 0; border-top: var(--rule);
}
.facts li:first-child { border-top: 0; padding-top: 0; }
.facts li strong { display: block; color: var(--brand-paper); margin-bottom: var(--space-xs); }

/* A window capture: the window's own rounded corners are transparent in the PNG, so it takes a
   shadow rather than a border, like .output-window. */
.shot { margin: 0 0 clamp(2.5rem, 5vw, 4rem); }
.shot picture { display: block; }
@media (max-width: 559px) { .shot-wide { display: none; } }
.shot img {
  display: block; width: 100%; height: auto;
  filter: drop-shadow(0 24px 40px rgb(var(--hud-background-rgb) / 0.6));
}
.shot figcaption { margin-top: var(--space-lg); font-size: 0.875rem; color: var(--text-faint); max-width: 62ch; }

/* ---------- the HUD in motion ----------

   Each animation is a vertical strip of real HUDView renders (MarketingImageTests), stepped
   through with `step-end`, because the HUD itself never tweens: a take number, a transport
   word and an elapsed second change between one frame and the next. A strip of N frames is
   drawn at `100% N00%`, and frame i sits at `i / (N - 1)` of the way down. Reduced motion
   parks each on a recording frame rather than hiding it. */

.hud-preset-hero {
  margin: 0; border-radius: var(--radius-panel); overflow: hidden;
  border: 1px solid rgb(var(--hud-foreground-rgb) / 0.14);
}

/* 13 s, ten frames: no take yet, every field a dash (2 s), take 01 recording 0:00–0:07 (1 s
   each), take 01 kept after stop (3 s). */
.hero-take {
  aspect-ratio: 760 / 640;
  background: var(--hud-background) url(/assets/screenshots/hero-sprite.png) 0 0 / 100% 1000% no-repeat;
  animation: hero-take 13s step-end infinite;
  /* Open one second into the dash, so the first thing anyone sees is the claim beside it
     happening: a dash, then the take number arriving with REC as its file appears. The whole
     two seconds of a parked panel was too long to wait for the product to do something. */
  animation-delay: -1s;
}
@keyframes hero-take {
  0%      { background-position: 0 0; }
  15.385% { background-position: 0 11.111%; }
  23.077% { background-position: 0 22.222%; }
  30.769% { background-position: 0 33.333%; }
  38.462% { background-position: 0 44.444%; }
  46.154% { background-position: 0 55.556%; }
  53.846% { background-position: 0 66.667%; }
  61.538% { background-position: 0 77.778%; }
  69.231% { background-position: 0 88.889%; }
  76.923%, 100% { background-position: 0 100%; }
}

/* 10 s, ten frames: take 12 recording at 12:55–13:04, one per second, so the minute carries. */
.elapsed-body { display: grid; gap: clamp(2rem, 4vw, 2.75rem); }
.elapsed-figure { max-width: 30rem; }
.elapsed-clock {
  aspect-ratio: 920 / 560;
  background: url(/assets/screenshots/elapsed-sprite.png) 0 0 / 100% 1000% no-repeat;
  animation: elapsed-count 10s step-end infinite;
}
@keyframes elapsed-count {
  0%  { background-position: 0 0; }
  10% { background-position: 0 11.111%; }
  20% { background-position: 0 22.222%; }
  30% { background-position: 0 33.333%; }
  40% { background-position: 0 44.444%; }
  50% { background-position: 0 55.556%; }
  60% { background-position: 0 66.667%; }
  70% { background-position: 0 77.778%; }
  80% { background-position: 0 88.889%; }
  90%, 100% { background-position: 0 100%; }
}

/* The desktop and booth screens: one render each of the moment the browser and call captures
   show. Not animated: the four agree in a grid, and two of them changing would be two disagreeing. */
.screen {
  border-radius: var(--radius-medium);
  border: 1px solid rgb(var(--brand-paper-rgb) / 0.14);
  background: var(--hud-background) 0 0 / 100% 100% no-repeat;
}
.screen-desk { background-image: url(/assets/screenshots/screen-desk.jpg); }
.screen-booth {
  background-image: url(/assets/screenshots/screen-booth.png);
  border-width: 4px; border-color: rgb(var(--brand-paper-rgb) / 0.1);
}
/* The booth monitor's stand: chrome, drawn from the same quiet paper as the bezel. */
.screen-booth::after {
  content: ""; position: absolute; left: 50%; top: 100%;
  width: 22%; height: var(--space-md); transform: translateX(-50%);
  margin-top: 4px;
  border-radius: 0 0 var(--radius-small) var(--radius-small);
  background: rgb(var(--brand-paper-rgb) / 0.1);
}

/* Each loop runs for as long as the page is open, so each carries a pause beside it — WCAG 2.2.2;
   reduced motion alone does not satisfy it. The page runs no script (the CSP allows none), so the
   control is a checkbox and `:has` reads it: "Pause animation", checked while paused. The box is
   visually hidden and the icon beside it — bars while playing, a triangle while paused — is
   what is drawn, because a pseudo-element on an `<input>` does not render in every browser. */
.motion-toggle {
  position: relative;
  display: inline-flex; align-items: center; gap: 0.5em;
  margin-top: var(--space-sm); min-height: 1.5rem;
  font-size: 0.8125rem; color: var(--text-quiet); cursor: pointer;
}
.motion-toggle input { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; }
.motion-icon {
  display: grid; place-items: center; flex: none;
  width: 1.5rem; height: 1.5rem; border-radius: 999px;
  border: 1px solid rgb(var(--brand-paper-rgb) / 0.24);
  transition: border-color 150ms ease-out;
}
.motion-icon::before {
  content: ""; box-sizing: border-box; width: 0.5rem; height: 0.5625rem;
  border-inline: 2px solid currentColor;
}
.motion-toggle input:checked + .motion-icon::before {
  width: 0; height: 0; margin-left: 2px;
  border-block: 0.3125rem solid transparent; border-inline: 0.5rem solid currentColor;
  border-right: 0;
}
.motion-toggle:hover { color: var(--brand-paper); }
.motion-toggle:hover .motion-icon { border-color: rgb(var(--brand-paper-rgb) / 0.55); }
.motion-toggle input:focus-visible + .motion-icon { outline: 2px solid var(--brand-cyan); outline-offset: 2px; }
.hero-visual:has(.motion-toggle input:checked) .hero-take,
.elapsed-media:has(.motion-toggle input:checked) .elapsed-clock { animation-play-state: paused; }

@media (prefers-reduced-motion: reduce) {
  .hero-take { animation: none; background-position: 0 77.778%; }
  .elapsed-clock { animation: none; background-position: 0 55.556%; }
  .motion-toggle { display: none; }
}

/* ---------- preset gallery ---------- */

.preset-gallery {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: var(--space-xl) var(--space-lg);
  grid-template-columns: repeat(12, minmax(0, 1fr));
}
.preset { grid-column: span 6; min-width: 0; }
.preset-detailed, .preset-timecode, .preset-banner { grid-column: span 12; }
.preset-tile {
  position: relative;
  aspect-ratio: 4 / 3;
  /* Neutral rather than the HUD's black: the gallery shows light profiles too, and a Paper
     plate letterboxed in black reads as a mistake. */
  background: rgb(var(--brand-paper-rgb) / 0.04);
  border: 1px solid rgb(var(--brand-paper-rgb) / 0.08);
  border-radius: var(--radius-panel);
  overflow: hidden;
}
/* Absolute, because a percentage height does not resolve inside an auto-height row. */
.preset-tile img { position: absolute; inset: var(--space-md); width: calc(100% - 2 * var(--space-md)); height: calc(100% - 2 * var(--space-md)); object-fit: contain; }
/* Detailed and Timecode share a row at one height, so their boxes take their spans' ratio. */
.preset-detailed .preset-tile { aspect-ratio: 1.7; }
.preset-timecode .preset-tile { aspect-ratio: 2.38; }
.preset-banner .preset-tile { aspect-ratio: auto; }
.preset-banner .preset-tile { padding: var(--space-md); }
.preset-banner .preset-tile img { position: static; display: block; width: 100%; height: auto; }
.preset p { margin: var(--space-md) 0 0; font-size: 0.875rem; line-height: 1.5; color: var(--text-quiet); }
.preset p strong { display: block; color: var(--brand-paper); font-size: 0.9375rem; }
.preset-look { display: block; font-size: 0.8125rem; color: var(--text-faint); margin-bottom: var(--space-xs); }
/* Profile and typeface: one line with a dot where the tile is wide enough for the longest pair
   ("Booth Amber profile · Monospaced type"), otherwise one line each. Wrapping it as a sentence
   broke mid-phrase on a two-column phone ("SessionHUD profile ·" over "Neutral type"). A
   container query, because the tile's width is not the viewport's: four tiles across a 760 px
   window are as narrow as two across a phone. */
.preset { container-type: inline-size; }
.preset-look > span { display: block; }
@container (min-width: 17rem) {
  .preset-look > span { display: inline; }
  .preset-look > span + span::before { content: "· "; content: "· " / ""; }
}
@media (min-width: 760px) {
  .preset-simple, .preset-normal, .preset-timer, .preset-talent { grid-column: span 3; }
  .preset-detailed { grid-column: span 5; }
  .preset-timecode { grid-column: span 7; }
}
.gallery-title { margin: clamp(2rem, 4vw, 3rem) 0 var(--space-sm); }
/* The pairings under each tile are examples, not part of the preset. */
.gallery-note { margin: 0 0 var(--space-lg); font-size: 0.875rem; color: var(--text-faint); }

/* ---------- final ---------- */

.final h2 { margin-bottom: var(--space-xl); }

/* The evaluation leads: it is the one step nobody pays for, so it carries the section's only
   filled button. The plans below are a choice between equals and take outlined ones. */
.trial {
  display: grid; gap: var(--space-xl);
  padding-bottom: clamp(2rem, 4vw, 3rem); border-bottom: var(--rule);
}
@media (min-width: 760px) {
  .trial { grid-template-columns: minmax(0, 1fr) auto; align-items: end; column-gap: clamp(2rem, 6vw, 5rem); }
}
.trial-lead { font-size: 1.25rem; line-height: 1.5; color: var(--text-quiet); max-width: 46ch; }
.trial-lead strong { color: var(--brand-paper); }
.trial-actions {
  display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-md);
  margin: 0; max-width: none;
}
.requirements {
  display: flex; flex-wrap: wrap; gap: var(--space-md) var(--space-xl);
  margin: var(--space-lg) 0 0;
}
.requirements dt, .plan-details dt {
  font-size: 0.75rem; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--text-faint);
}
.requirements dd { margin: var(--space-xs) 0 0; font-size: 1.0625rem; line-height: 1.45; }

.plans-title { margin: clamp(2rem, 4vw, 3rem) 0 var(--space-sm); font-size: 1.375rem; }
.plans-lede { color: var(--text-quiet); max-width: 54ch; margin-bottom: var(--space-md); }
.plans-window { color: var(--text-quiet); max-width: 54ch; margin-bottom: var(--space-xl); }

.plans { display: grid; gap: var(--space-lg); }
/* Three plans. Two columns would leave the third card alone on a row, so they stack until all
   three fit side by side. */
@media (min-width: 900px) {
  .plans { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
.plan {
  display: flex; flex-direction: column;
  padding: clamp(1.25rem, 3vw, 2rem);
  border: 1px solid rgb(var(--brand-paper-rgb) / 0.14);
  border-radius: var(--radius-panel);
  background: rgb(var(--brand-paper-rgb) / 0.03);
}
.plan h4 {
  margin: 0 0 var(--space-md);
  font-size: 0.8125rem; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--text-quiet);
}
.plan .price { margin: 0; max-width: none; font-size: 1rem; }
/* A card on a launch price takes the brand gradient as its edge, the one place on the page a
   card is drawn in colour, so the offer is found before it is read. Two padding-box layers (ink,
   then the card's wash) keep the inside identical to the other cards. */
.plan-launch {
  border-color: transparent;
  background:
    linear-gradient(rgb(var(--brand-paper-rgb) / 0.03), rgb(var(--brand-paper-rgb) / 0.03)) padding-box,
    linear-gradient(var(--brand-ink), var(--brand-ink)) padding-box,
    var(--brand-gradient) border-box;
}
/* Not the primary button's pairing: that one passes as large text, and 12 px is not large. Ink on
   the gradient's violet end is 4.36:1 behind these glyphs, under the 4.5:1 normal text needs, so
   the badge runs from indigo (5.0:1) to cyan and leaves violet to the card's edge around it. */
.plan-badge {
  display: table; margin: 0 0 var(--space-md);
  padding: 0.3em 0.75em; border-radius: 999px;
  background: linear-gradient(75deg, var(--brand-indigo), var(--brand-cyan)); color: var(--brand-ink);
  font-size: 0.75rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
}
.plan-was { font-size: 1.5rem; font-weight: 600; margin-right: 0.15em; }
/* A price is a number someone compares, so it is set the way the HUD sets a take: large,
   tabular, and tight. */
.plan-amount {
  font-size: clamp(2.75rem, 6vw, 3.5rem); font-weight: 700; line-height: 1;
  letter-spacing: -0.035em; font-variant-numeric: tabular-nums; color: var(--brand-paper);
}
.plan-unit { color: var(--brand-paper); font-weight: 500; }
.plan-note {
  display: block; margin-top: var(--space-md);
  font-size: 0.9375rem; line-height: 1.5; color: var(--text-quiet); max-width: 40ch;
}
.plan-points {
  list-style: none; margin: var(--space-lg) 0 var(--space-xl); padding: 0;
  font-size: 0.9375rem; line-height: 1.5; color: var(--text-quiet);
}
.plan-points li { padding: var(--space-md) 0; border-top: var(--rule); }
.plan-points li:last-child { border-bottom: var(--rule); }
.plan-button { margin-top: auto; align-self: stretch; text-align: center; white-space: normal; }

.plan-shared {
  list-style: none; margin: var(--space-xl) 0 0; padding: 0;
  display: grid; gap: var(--space-sm) var(--space-xl);
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  font-size: 0.9375rem; color: var(--text-quiet);
}
.plan-shared li { display: flex; align-items: baseline; gap: var(--space-sm); }
/* The record lamp's colour would claim a state; a quiet cyan dot only marks the item. */
.plan-shared li::before {
  content: ""; flex: none; width: 6px; height: 6px; border-radius: 50%;
  background: var(--brand-cyan); transform: translateY(-2px);
}

.plan-details {
  margin: var(--space-xl) 0; border-top: var(--rule); border-bottom: var(--rule);
}
.plan-details summary {
  display: flex; align-items: center; gap: var(--space-md);
  padding: var(--space-lg) 0; cursor: pointer; list-style: none;
  font-weight: 600; color: var(--brand-paper);
}
.plan-details summary::-webkit-details-marker { display: none; }
.plan-details summary::before {
  content: ""; flex: none; width: 7px; height: 7px;
  border-right: 2px solid var(--text-quiet); border-bottom: 2px solid var(--text-quiet);
  transform: rotate(-45deg); transition: transform 150ms ease-out;
}
.plan-details[open] summary::before { transform: rotate(45deg); }
.plan-details summary:hover::before { border-color: var(--brand-cyan); }
.plan-details summary:focus-visible { outline: 2px solid var(--brand-cyan); outline-offset: -2px; border-radius: var(--radius-small); }
.plan-details dl { margin: 0; padding: 0 0 var(--space-lg); display: grid; gap: var(--space-lg); }
@media (min-width: 760px) {
  .plan-details dl { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-xl); }
}
.plan-details dd { margin: var(--space-sm) 0 0; font-size: 0.9375rem; line-height: 1.5; color: var(--text-quiet); }

.fine { font-size: 0.875rem; color: var(--text-faint); }
.fine a { text-decoration-color: rgb(var(--brand-paper-rgb) / 0.3); }
.fine a:hover { color: var(--brand-paper); }

.site-footer {
  max-width: var(--page-max); margin: 0 auto;
  padding: var(--space-xl) var(--page-gutter) clamp(2.5rem, 6vw, 4rem);
  border-top: var(--rule);
  font-size: 0.9375rem;
}
.site-footer p { margin: 0 0 var(--space-sm); color: var(--text-quiet); max-width: none; }
.site-footer p strong { color: var(--brand-paper); }
.site-footer .fine { color: var(--text-faint); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

/* ---------- inner pages ---------- */

/* Every inner page reads from the same left edge as the logo above it, so the support page,
   the legal pages and the docs line up instead of each floating at its own offset. */
.doc > * { max-width: var(--measure); }
.doc h1 {
  font-size: clamp(2rem, 4vw, 2.75rem);
  margin-bottom: var(--space-md);
}
.doc .lede { margin-bottom: clamp(2rem, 4vw, 2.75rem); color: var(--text-quiet); }
.doc h2 {
  font-size: 1.5rem; letter-spacing: -0.015em;
  margin: clamp(2.5rem, 5vw, 3.25rem) 0 var(--space-md);
}
.doc h2 + h3 { margin-top: var(--space-lg); }
/* A question needs air above it, or an answer and the next question read as one block. */
.doc h3 { margin: 2.25rem 0 var(--space-sm); }
.doc ul, .doc ol { max-width: 62ch; padding-left: 1.2em; margin: 0 0 var(--space-lg); }
.doc li { margin-bottom: 0.5em; padding-left: 0.2em; }
.doc li::marker { color: var(--brand-cyan); }
.doc p, .doc li { text-wrap: pretty; }
.doc .updated {
  font-size: 0.8125rem; color: var(--text-faint);
  margin-top: clamp(2.5rem, 5vw, 3.5rem); padding-top: var(--space-lg); border-top: var(--rule);
}
.doc .actions { margin-top: var(--space-lg); }
/* A step a reader must not skip, set apart from the paragraph around it. A left rule in the
   brand cyan rather than a filled box: it is an instruction, not an alarm. */
.doc .callout {
  margin: 0 0 var(--space-lg);
  padding: var(--space-sm) 0 var(--space-sm) var(--space-md);
  border-left: 2px solid var(--brand-cyan);
}

/* Reference material: the API page's requests, payloads and field tables. Plain monospace with no
   highlighting — the CSP allows no script to colour it, and a payload a reader copies should look
   like what curl prints. Both scroll inside themselves rather than widening the page on a phone,
   and both take a wider column than prose, because a JSON line or a four-column table broken to
   the reading measure is harder to read, not easier. */
.doc pre {
  margin: 0 0 var(--space-lg);
  padding: var(--space-md) var(--space-lg);
  overflow-x: auto;
  border-radius: var(--radius-small);
  border: 1px solid rgb(var(--brand-paper-rgb) / 0.1);
  background: rgb(var(--brand-paper-rgb) / 0.04);
  font-size: 0.875rem; line-height: 1.55;
}
.doc pre code { padding: 0; background: none; font-size: inherit; white-space: pre; }
.doc-article > pre, .doc-article > .table-scroll { max-width: 52rem; }
.doc .table-scroll { overflow-x: auto; margin: 0 0 var(--space-lg); }
.doc table { width: 100%; border-collapse: collapse; font-size: 0.9375rem; }
.doc th, .doc td {
  text-align: left; vertical-align: top;
  padding: 0.55em 1em 0.55em 0;
  border-bottom: 1px solid rgb(var(--brand-paper-rgb) / 0.12);
}
.doc th {
  font-size: 0.75rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--text-faint);
}
.doc td:first-child { white-space: nowrap; }
.doc td { color: var(--text-quiet); }
.doc td code { overflow-wrap: anywhere; }
.doc h2 code, .doc h3 code { font-size: 0.82em; }

/* Marks a capability a license unlocks. The evaluation runs every output, so a page that
   describes the designer the same way tells a reader they can have it for nothing.
   Deliberately quiet: an outline, not a fill, because this is a footnote about which half of
   the product it is, not a badge shouting about a paywall. */
.paid {
  font-size: 0.6875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  vertical-align: middle;
  margin-left: 0.5em;
  padding: var(--space-xs) var(--space-sm);
  border: 1px solid rgb(var(--brand-paper-rgb) / 0.28);
  border-radius: var(--radius-small);
  opacity: 0.7;
  white-space: nowrap;
}

/* Docs guide: contents beside the article on a wide viewport, stacked above it otherwise. */
.doc-with-nav { display: grid; gap: var(--space-xl); }
.doc-with-nav > * { max-width: none; }
.doc-nav { font-size: 0.9375rem; }
.doc-nav h2 {
  font-size: 0.75rem; font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin: 0 0 var(--space-md);
}
.doc-nav ol {
  list-style: none;
  padding: 0;
  margin: 0;
  max-width: none;
}
.doc-nav li { margin: 0; padding: 0; }
.doc-nav a {
  display: block;
  padding: 0.3em 0 0.3em var(--space-md);
  margin-left: -1px;
  border-left: 1px solid rgb(var(--brand-paper-rgb) / 0.12);
  text-decoration: none;
  color: var(--text-quiet);
}
.doc-nav a:hover { color: var(--brand-paper); border-left-color: rgb(var(--brand-paper-rgb) / 0.4); }
.doc-nav a[aria-current="page"] {
  color: var(--brand-paper);
  border-left-color: var(--brand-cyan);
}
/* The current page's sections, indented under it on the same rail. Top-level headings only: a
   page's subsections would bury the four page links. Plain links with no current-section mark,
   because the CSP allows no script to track the scroll. Scripts/check_docs.py fails if this list
   and the page's <h2 id>s disagree. */
.doc-nav .doc-toc { display: block; margin: var(--space-xs) 0 var(--space-sm); }
.doc-nav .doc-toc a {
  padding-left: calc(var(--space-md) * 2);
  font-size: 0.875rem; color: var(--text-faint);
}
.doc-nav .doc-toc a:hover { color: var(--brand-paper); }
.doc-article { min-width: 0; }
.doc-article > * { max-width: var(--measure); }

/* An annotated screenshot of the app. A window is wider than a paragraph and its labels are small,
   so a figure takes the article's whole column rather than the reading measure.
   The marks are SVG in the image's own pixel space (its viewBox is the capture's size), because the
   CSP allows no inline style to position HTML over it: so a box or a pin lands on the same control at
   every width. Strokes do not scale (vector-effect), the pins do, sized so they stay readable at the
   article's width; on a phone the capture itself is too small to read and the numbered key carries
   it. Cyan is the page's accent that is not a button, and nothing in the app's chrome is cyan, so a
   mark never reads as part of the window. */
.doc-article > .shot { max-width: 60rem; }
/* A small window (Settings) at its own size, not stretched to the column. Mid and small are crops
   of a few panels and a popover, each capped at its own width for the same reason. */
.doc-article > .shot-narrow { max-width: 600px; }
.doc-article > .shot-mid { max-width: 810px; }
.doc-article > .shot-small { max-width: 412px; }
/* Shown near 1:1, so its pins are drawn smaller in its own pixels to match the others on screen. */
.shot-narrow .shot-marks .pin text,
.shot-mid .shot-marks .pin text,
.shot-small .shot-marks .pin text { font-size: 17px; }
.shot { margin: var(--space-xl) 0 clamp(2rem, 4vw, 2.75rem); }
.shot-frame {
  position: relative; border-radius: 10px; overflow: hidden;
  border: 1px solid rgb(var(--brand-paper-rgb) / 0.14);
  background: rgb(var(--brand-paper-rgb) / 0.03);
}
.shot-frame img { display: block; width: 100%; height: auto; }
.shot-marks { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.shot-marks .box {
  fill: rgb(var(--brand-cyan-rgb) / 0.08); stroke: var(--brand-cyan); stroke-width: 2.5;
  vector-effect: non-scaling-stroke;
}
.shot-marks .arrow {
  fill: none; stroke: var(--brand-cyan); stroke-width: 3; stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}
.shot-marks .head { fill: var(--brand-cyan); }
.shot-marks .pin circle { fill: var(--brand-cyan); stroke: var(--brand-ink); stroke-width: 3; }
.shot-marks .pin text {
  fill: var(--brand-ink); font: 700 26px/1 -apple-system, BlinkMacSystemFont, "Helvetica Neue", sans-serif;
  text-anchor: middle; dominant-baseline: central;
}
.shot figcaption { margin-top: var(--space-md); font-size: 0.9375rem; color: var(--text-quiet); max-width: var(--measure); }
.shot-key { list-style: none; padding: 0; margin: var(--space-md) 0 0; counter-reset: key; }
.shot-key li {
  counter-increment: key; position: relative;
  padding-left: 2.25rem; margin: 0 0 var(--space-sm);
}
.shot-key li::before {
  content: counter(key);
  position: absolute; left: 0; top: 0.1em;
  width: 1.5rem; height: 1.5rem; border-radius: 50%;
  background: var(--brand-cyan); color: var(--brand-ink);
  font-size: 0.8125rem; font-weight: 700; line-height: 1.5rem; text-align: center;
}
.shot-key strong { color: var(--brand-paper); }
.doc-article > h1:first-child { margin-top: 0; }
@media (max-width: 831px) {
  .doc-nav ol { display: flex; flex-wrap: wrap; gap: var(--space-xs) var(--space-lg); }
  /* Above the article on a phone, eight more links is a screen to scroll past first. */
  .doc-nav .doc-toc { display: none; }
  .doc-nav a { border-left: 0; padding-left: 0; margin-left: 0; }
  .doc-nav a[aria-current="page"] { color: var(--brand-cyan); }
}
@media (min-width: 832px) {
  .doc-with-nav {
    grid-template-columns: var(--doc-nav-width) minmax(0, 1fr);
    column-gap: clamp(2.5rem, 5vw, 4rem);
    align-items: start;
  }
  .doc-nav {
    position: sticky;
    top: var(--space-xl);
  }
}

/* ---------- features page ----------

   The deeper look behind the homepage: the same bands, with a label over each heading so a
   reader scrolling a long page knows which output they are in. Pictures are the app's own
   renders and take the homepage's treatments; nothing here is a new colour. */

.features-hero { grid-template-columns: minmax(0, 1fr); padding-bottom: clamp(2.5rem, 5vw, 4rem); }
.features-hero h1 { max-width: 20ch; }
.features-hero .lede { max-width: 48ch; }
.feature-jump {
  list-style: none; margin: var(--space-xl) 0 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: var(--space-sm) var(--space-lg);
  font-size: 0.9375rem;
}
.feature-jump a { color: var(--text-quiet); text-decoration: none; white-space: nowrap; }
.feature-jump a:hover { color: var(--brand-paper); }

.eyebrow {
  margin: 0 0 var(--space-sm);
  font-size: 0.8125rem; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--brand-cyan);
}

.feature-shot { margin: 0 0 clamp(2rem, 4vw, 3rem); }
.feature-shot img {
  display: block; width: 100%; height: auto; border-radius: var(--radius-medium);
  border: 1px solid rgb(var(--brand-paper-rgb) / 0.1);
}
.feature-shot figcaption { margin-top: var(--space-md); font-size: 0.875rem; color: var(--text-faint); max-width: 62ch; }
.feature-shot figcaption strong { color: var(--brand-paper); }
/* The tally pair is two panels on a transparent ground: no frame around it. */
.feature-shot-narrow { max-width: 40rem; margin-top: clamp(2.5rem, 5vw, 3.5rem); }
.feature-shot-narrow img { border: 0; border-radius: 0; }

/* Three frames a call can see, side by side from tablet width. */
.feature-trio, .take-states, .profile-strip { list-style: none; margin: 0; padding: 0; display: grid; }
.feature-trio { gap: var(--space-xl) var(--space-lg); margin-bottom: clamp(2rem, 4vw, 3rem); }
@media (min-width: 760px) { .feature-trio { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.feature-trio img {
  display: block; width: 100%; height: auto; border-radius: var(--radius-medium);
  border: 1px solid rgb(var(--brand-paper-rgb) / 0.12);
}
.feature-trio p, .take-states p { margin: var(--space-md) 0 0; font-size: 0.9375rem; line-height: 1.5; color: var(--text-quiet); }
.feature-trio p strong, .take-states p strong { display: block; color: var(--brand-paper); }

.take-states { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-md) clamp(0.75rem, 2.5vw, 1.5rem); margin-bottom: clamp(2rem, 4vw, 3rem); max-width: 54rem; }
.take-states img { display: block; width: 100%; height: auto; }
@media (max-width: 559px) { .take-states p { font-size: 0.8125rem; } }

.profile-strip { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-md); }
@media (min-width: 760px) { .profile-strip { grid-template-columns: repeat(6, minmax(0, 1fr)); } }
.profile-strip img { display: block; width: 100%; height: auto; }
.profile-strip + .gallery-note { margin-top: var(--space-md); margin-bottom: clamp(2rem, 4vw, 3rem); max-width: 62ch; }

/* Two drawn iPads, record and playback, side by side; the shadow lifts the transparent device off
   the page the way .output-window lifts a captured window. */
.feature-pair {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(1rem, 3vw, 2.5rem);
}
.feature-pair img {
  display: block; width: 100%; height: auto;
  filter: drop-shadow(0 18px 30px rgb(var(--hud-background-rgb) / 0.55));
}
.feature-pair-note { margin-top: var(--space-lg); margin-bottom: clamp(2.5rem, 5vw, 4rem); max-width: 62ch; }

/* Facts in two columns once there is room, so a band of six reads as a grid, not a scroll. */
@media (min-width: 760px) {
  .feature-facts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: clamp(2rem, 5vw, 4rem); }
  .feature-facts li:nth-child(2) { border-top: 0; padding-top: 0; }
}
@media (min-width: 1000px) {
  .feature-facts-wide { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .feature-facts-wide li:nth-child(3) { border-top: 0; padding-top: 0; }
}
/* A restriction is a footnote on the item, not a badge on its name: the page says what the trial
   leaves out rather than what a purchase adds. */
.facts .trial-note { display: block; margin-top: var(--space-xs); font-size: 0.875rem; color: var(--text-faint); }

/* A picture beside its facts on a wide screen, above them on a narrow one. */
.feature-split { display: grid; gap: clamp(2rem, 4vw, 3rem); align-items: start; }
@media (min-width: 900px) {
  .feature-split { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); column-gap: clamp(2.5rem, 5vw, 4rem); }
}
.feature-split .screen-booth { margin-bottom: calc(var(--space-md) + 4px); }

.feature-code {
  margin: clamp(2rem, 4vw, 2.75rem) 0 var(--space-lg); max-width: 52rem;
  padding: var(--space-md) var(--space-lg); overflow-x: auto;
  border-radius: var(--radius-small);
  border: 1px solid rgb(var(--brand-paper-rgb) / 0.1);
  background: rgb(var(--brand-paper-rgb) / 0.04);
  font-size: 0.875rem; line-height: 1.55;
}
.feature-code code { padding: 0; background: none; font-size: inherit; white-space: pre; }

.feature-more { margin: var(--space-xl) 0 0; font-size: 0.9375rem; color: var(--text-quiet); }
.feature-more a { color: var(--brand-paper); }

.features-final { text-align: left; }
.features-final h2 { margin-bottom: var(--space-md); }
.features-final .actions { margin-top: 0; }

/* ---------- phones ---------- */

/* The take card is the proof, so on one column it comes straight after the lede rather than after
   the button and the terms. Only the image moves; its one control, the animation's pause, is
   reached after the buttons rather than before them, which costs nothing a reader needs. */
@media (max-width: 899px) {
  .hero { gap: 0; }
  .hero-copy { display: contents; }
  .hero-copy > * { order: 4; }
  .hero h1 { order: 1; }
  .hero .lede { order: 2; }
  .hero-visual { order: 3; margin: var(--space-sm) 0 var(--space-xl); }
}

/* A phone or tablet cannot run a Mac app. Said under each Download button, never instead of it:
   the visitor may be choosing on the sofa and installing at the desk. */
.mac-note { display: none; }
@media (hover: none) and (pointer: coarse) {
  .mac-note { display: block; margin: var(--space-sm) 0 0; font-size: 0.875rem; color: var(--text-faint); max-width: 40ch; }
}
.trial-actions .mac-note { margin: 0; }

/* Pre-launch. Only in a `deploy_site.sh production --prelaunch` upload, which turns the buy and
   download buttons into labels and adds the banner (Scripts/site_channel.py); the committed pages
   never carry either class. A label is quiet text on a dashed edge, so nothing reads as pressable. */
.prelaunch-banner {
  margin: 0; max-width: none; padding: var(--space-sm) var(--page-gutter);
  text-align: center; font-size: 0.9375rem;
  background: rgb(var(--brand-paper-rgb) / 0.06); border-bottom: var(--rule);
}
.button.is-soon,
.button.is-soon:hover {
  cursor: default; background: transparent; color: var(--text-quiet); filter: none;
  border: 1px dashed rgb(var(--brand-paper-rgb) / 0.32);
}
.button.is-soon:active { transform: none; }
