/* =====================================================================
   P6R BASELINE. PicksYou site.css, the public site and the auth doors.

   design/tokens.css is copied byte for byte to public/css/site.css. There
   is no build step: what is written here is what a browser reads.

   THIS FILE WAS REWRITTEN FROM SCRATCH FOR PHASE 6R, THE OPINLY-GRADE SKIN
   (owner order 2026-09-05: "design wise it should be the same clean as
   Opinly has, just different colors and positioning of items, but fonts,
   sizes and etc same"). The binding ruling is design/rules/phase6r-skin.md
   and the design source is design/mockups/phase6r/site-landing.html and
   site-login.html: every size, radius, height and shadow below is lifted
   from those two files through the tokens.

   WHAT WENT WITH THE n4 SHEET: Figtree and Red Hat Mono, the 17px body and
   its 15px floor, the 48px controls, the 60px bar, the three shadow depths
   and the 72px section rhythm. WHAT STAYED: the palette, every class name
   the shipped views ask for, and the laws (raspberry is never a button,
   counts never a share, tabular figures only on figures).

   WHAT THIS BASELINE OWNS: the two vendored faces, the token block, base
   elements, the type scale, buttons, form fields, links, the slim top bar,
   the footer, the marketing and legal page shell, and the shared card,
   table, chip, hatch, segment, dialog and popover vocabulary.

   THE THREE PAGE SECTIONS BELOW IT (P6R-2 the landing and the receipt,
   P6R-3 the marketing, legal and notice pages, P6R-4 the doors) are the
   old P5O-T2 to T4 regions folded into this rewrite: same surfaces, same
   class names, redrawn on the new scale. They are sections of one
   baseline, not append-only regions, and each carries a banner so a page
   can still be found by name.

   THE CLASS CONTRACT IS THE SHIPPED ONE. Class names that survived the
   skin change are restyled in place under the same names (.wrap,
   .section, .btn, .field, .input, .card, .table, .article, .topbar,
   .foot and the rest), so every view that was not touched this phase
   inherits the skin rather than losing its styling. Token NAMES are the
   shipped ones too, with the new values, because design/app.css and
   design/admin.css read them.
   ===================================================================== */

/* ------------------------------------------------------------------ font */

/* GEIST, everything spoken, and GEIST MONO, everything measured (counts,
   timestamps, verbatim answers, money, ids). Both are OFL (Vercel with
   basement.studio, licence in public/fonts/OFL-geist.txt), both are
   variable across the whole 100 to 900 range, and both are served from our
   own origin: no Google Fonts link is ever in a production page, so a
   reader on a train gets the same page as a reader in an office and no
   third party sees their address.

   ONE FILE EACH, NOT TWO. Figtree and Red Hat Mono were vendored as the
   latin and latin-ext pair Google's css2 output splits on. The Geist
   package (npm geist 1.7.2) ships one variable woff2 per family covering
   the whole set, so there is nothing to split and no second request to
   make; the file is 68 KB for the spoken face and 70 KB for the measured
   one.

   font-display: swap with a real fallback stack, so the first paint is the
   system face and never nothing. */
@font-face {
  font-family: "Geist";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/fonts/geist-variable.woff2") format("woff2");
}

@font-face {
  font-family: "Geist Mono";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/fonts/geistmono-variable.woff2") format("woff2");
}

/* SATOSHI, EVERYTHING SPOKEN ON A PUBLIC PAGE (T2.12, the Public reference
   sheet design/mockups/phase6r/s7/PUBLIC-SHEET.md section 1). The owner's
   brief was "same fonts, sizes and etc" as the reference, and the reference's
   public site is set in Satoshi at 16/24; the workspace keeps Geist. Two
   sheets, not one skin: --font is the app and admin face, --font-pub is the
   public one, and neither reaches into the other.

   VENDORED FROM FONTSHARE, UNCHANGED, WITH ITS LICENCE BESIDE IT. The two
   files are the official variable web fonts from the family download
   (api.fontshare.com/v2/fonts/download/satoshi, Fonts/WEB/fonts), copied byte
   for byte: the ITF Free Font License forbids subsetting, format conversion
   and any other alteration, so nothing is stripped. The licence text ships as
   public/fonts/LICENSE-satoshi.txt. It grants free personal and commercial
   use, self hosting on our own origin with no page view limit, no separate
   web licence and no attribution required; it forbids reselling, passing the
   files to a third party and derivative fonts. We do none of those.

   THE ITALIC IS DECLARED BUT NEVER FETCHED unless a page actually sets an
   italic, which is how a browser treats a second @font-face. Only the normal
   file is preloaded.

   font-display: swap with a real fallback stack, as above. */
@font-face {
  font-family: "Satoshi";
  font-style: normal;
  font-weight: 300 900;
  font-display: swap;
  src: url("/fonts/satoshi-variable.woff2") format("woff2");
}

@font-face {
  font-family: "Satoshi";
  font-style: italic;
  font-weight: 300 900;
  font-display: swap;
  src: url("/fonts/satoshi-variable-italic.woff2") format("woff2");
}

/* ---------------------------------------------------------------- tokens */

:root {
  color-scheme: light;

  /* COLOUR (phase6r-skin.md section 3, unchanged from n4).

     Three grounds: paper is the page, panel is the quiet band and the
     footer, card is white. One ink and one secondary. One hairline.

     ONE ACCENT, AND IT IS NEVER A BUTTON. Raspberry is spent on links, the
     active tab underline, the named pill, the marked name, the current
     week column, the interval band and the callout dots. Buttons are
     filled ink with a white label; a quiet button is card on hairline.

     MEASURED on paper (#fafcfe): ink 14.6:1, secondary 6.2:1, accent
     6.0:1, ok 6.4:1, warn 5.8:1, bad 6.4:1. --muted is the same value as
     --ink-2 on purpose: this palette has one secondary, and the shipped
     sheet had two names for it, so both names point at the one colour
     rather than inventing a paler grey that would fail on the panel. */
  --ink: #1c2630;
  --ink-2: #52606e;
  --muted: #52606e;
  --bg: #fafcfe;           /* paper: the page */
  --band: #f1f5f9;         /* panel: quiet bands, the footer, an inset box */
  --surface: #ffffff;      /* card */
  --line: #dbe2ea;         /* the hairline: every rule, card and control */
  --line-2: #7c8998;       /* a heavier edge, kept for the two panel sheets */
  --line-3: #66717f;       /* the same edge, one step darker, on hover */
  --accent: #c2255c;       /* raspberry: links, marks, the accent dot */
  --accent-soft: rgba(194, 37, 92, 0.10);
  --accent-bg: #f9e6ec;    /* the solid twin of the soft fill, for tints */
  --button: #1c2630;       /* a filled button is ink */
  --button-2: #0f161d;     /* and one step darker on hover (the mockup) */
  --button-ink: #ffffff;
  /* THE PLACEHOLDER IS 4.5:1 NOW (T2.12, the owner's review "fix the input
     boundary regression", and both reference sheets). #8b97a3 measured 3.0:1
     on the white field, which is a hint a reader has to lean in to read;
     #6b7885 is 4.5:1 and nothing else about the control moves. This is a
     BASELINE change and not a public one on purpose: the workspace and the
     operator panel read the same token and had the same defect. */
  --placeholder: #6b7885;
  --ok: #1a6b3f;
  --ok-bg: #e6f3ea;
  --warn: #8a5a08;
  --warn-bg: #fbeed2;
  --bad: #b3261e;
  --bad-bg: #fbe4e1;
  --zebra: rgba(241, 245, 249, 0.5);   /* a table row on the panel at half */
  /* The marked business name inside an answer: the soft accent fill with a
     2px accent rule under it. */
  --mark: var(--accent-soft);
  --mark-ink: inherit;

  /* SHADOW, AND THERE IS ONE (phase6r-skin.md section 2: "Shadows only on
     popovers, modals and toasts"). The landing's browser frame and a
     floating bar are the two objects the mockups add to that list, because
     both of them float over the page.

     --shadow-1 is not a depth, it is the 1px seat under a white pill on
     the panel ground; --shadow-2 and --shadow-3 are the one shadow, kept
     as two names because design/app.css and design/admin.css ask for
     both. */
  --shadow-ink: 28, 38, 48;
  --shadow-1: 0 1px 2px rgba(var(--shadow-ink), 0.04);
  --shadow-2: 0 8px 24px rgba(var(--shadow-ink), 0.08);
  --shadow-3: 0 8px 24px rgba(var(--shadow-ink), 0.08);
  --chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cpath d='M4 6l4 4 4-4' fill='none' stroke='%2352606e' stroke-width='2'/%3E%3C/svg%3E");

  /* TYPE (phase6r-skin.md section 1, the table). Geist for everything
     spoken, Geist Mono for everything measured. Body 14, description and
     meta 13, mini label 12 and nothing under it, card title 15, page
     title 20, a public page head 24 to 30, the landing display 40 to 56.

     THE FLOOR IS 12 AND THE MINI LABEL SITS ON IT. The ruling's table says
     11 for the uppercase mini label and its own floor says 12; the floor
     wins, which is the reading the mockups shipped. */
  --font: "Geist", ui-sans-serif, system-ui, "Segoe UI", Roboto, sans-serif;
  --font-mono: "Geist Mono", ui-monospace, "SF Mono", Menlo, monospace;
  /* THE PUBLIC FACE (T2.12). Satoshi draws every word on a public page and
     every sentence in the workspace; --font keeps the headings, the nav, the
     buttons and the table heads. The stack falls back in the same order as
     the Geist one, so a first paint is the system face and never nothing. */
  --font-pub: "Satoshi", ui-sans-serif, system-ui, "Segoe UI", Roboto, sans-serif;
  --fs-mini: 12px;                        /* the uppercase mini label */
  --fs-meta: 13px;                        /* description, meta, help */
  --fs-body: 14px;
  --fs-lede: 16px;                        /* the one body size above 14 */
  --fs-h3: 15px;                          /* a card title */
  --fs-h2: 20px;                          /* a section heading */
  --fs-title: 20px;                       /* a page or panel title */
  --fs-page: clamp(24px, 3vw, 30px);      /* the head of a public page */
  --fs-h1: clamp(40px, 5vw, 56px);        /* the landing display, alone */
  --fs-count: 30px;                       /* the receipt sentence's figure */
  --fs-count-big: 40px;                   /* a headline count on its own */
  --lh: 1.55;
  --lh-head: 1.25;
  --lh-display: 1.05;

  /* SPACE, on the 4 and 8 scale, and SHAPE (phase6r-skin.md section 2).
     The grid gap is 20 and the card stack gap 24; a section of a public
     page stands 56 apart and the landing block opens on 72. */
  --s1: 4px;
  --s2: 8px;
  --s3: 12px;
  --s4: 16px;
  --s5: 24px;
  --s6: 32px;
  --s7: 48px;
  --s8: 64px;
  --s9: 96px;
  --s10: 128px;
  --gap: 20px;             /* the grid gap between cards */
  --section: 56px;         /* 40 on a phone */
  --hero: 72px;            /* 40 on a phone */
  --radius: 10px;          /* cards */
  --radius-l: 12px;        /* popovers, modals and the browser frame */
  --radius-s: 8px;         /* every button, input and inset box */
  --radius-xs: 6px;        /* menu rows, the cell inside a segment */
  --radius-tile: 8px;
  --radius-pill: 999px;
  --container: 1280px;     /* the frame caps here and centres */
  --gutter: 20px;          /* 24 from 1200, 16 under 640 */
  --header: 46px;          /* the slim bar */
  --row: 36px;             /* a table row */
  --control-xs: 26px;
  --control-s: 30px;       /* the bar button */
  --control: 34px;         /* every control on the page */
  --control-l: 40px;       /* the landing's own hero controls */

  /* The admin panel's own numbers live here as well as in admin.css, so
     the customer panel can reach the same values (admin-ui.md 2.12). */
  --adm-bar: 46px;
  --adm-rail: 174px;
  --adm-main: 1280px;
  --z-bar: 10;
  --z-menu: 20;

  /* MOTION (phase6r-skin.md section 5). 150ms on a control, 160ms on a
     card that entered after a state change, and nothing loops. The ease is
     the design skills' own cubic bezier; there is no ease-in anywhere. */
  --ease: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-enter: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in: cubic-bezier(0.23, 1, 0.32, 1);
  --dur-1: 150ms;
  --dur-2: 160ms;
  --dur-3: 250ms;
  --t-in: 160ms;
  --t-out: 160ms;

  /* THE PUBLIC SHEET'S OWN VALUES (T2.12, PUBLIC-SHEET.md). They are
     declared here, beside the rest, so design/app.css can read --edge and
     --font-pub without a second source of truth; the sizes are only ever
     read inside the P6R-S2A region at the foot of this file.

     THE INPUT BOUNDARY IS A TOKEN NOW. --edge is --line-2 under the name the
     two reference sheets use for it: 3.6:1 on a white field and 3.5:1 on
     paper, which is what WCAG 1.4.11 asks of a control a reader has to find
     BEFORE they focus it. --edge-hover is --line-3. */
  --edge: var(--line-2);
  --edge-hover: var(--line-3);
  --pub-shadow: 0 4px 6px -2px rgba(16, 24, 40, 0.03), 0 12px 16px -4px rgba(16, 24, 40, 0.06);
  --closing-ink: #dde1e9;   /* the sentence on the dark closing block, 11.6:1 */

  /* THE PUBLIC TYPE SCALE, per template (PUBLIC-SHEET.md section 2). The
     hero and the one big block are 72/92; a narrative section head is 36/45;
     pricing and comparison heads 56/70; an index 60/75; an article 48/60; a
     compact head 36/40; a docs-like page 28/42; legal 30/40. The responsive
     steps are in the region, not here, because they differ per role. */
  --fs-pub-body: 16px;
  --fs-pub-blurb: 14px;
  --fs-pub-lede: 20px;
  --fs-pub-h3: 20px;
  --fs-pub-h2: 36px;
  --fs-pub-hero: 72px;
  --fs-pub-compare: 56px;
  --fs-pub-index: 60px;
  --fs-pub-article: 48px;
  --fs-pub-compact: 36px;
  --fs-pub-docs: 28px;
  --fs-pub-legal: 30px;
  --fs-pub-cta: 18px;
  --fs-pub-input: 18px;
  --radius-pub: 12px;      /* every public control and input corner */
}

@media (min-width: 1200px) {
  :root { --gutter: 24px; }
}

@media (max-width: 767px) {
  :root { --section: 40px; --hero: 40px; }
}

@media (max-width: 639px) {
  :root { --gutter: 16px; }
}

/* ------------------------------------------------------------------ base */

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

/* Components set their own display, so the hidden attribute needs this. */
[hidden] { display: none !important; }

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  font-size: var(--fs-body);
  line-height: var(--lh);
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  text-wrap: pretty;
  -webkit-font-smoothing: antialiased;
}

main { flex: 1 0 auto; }

/* Links are raspberry, and they underline on hover rather than at rest
   (the mockup). Inside a paragraph of prose the underline is on at rest,
   because a link a reader has to hover to find is not a link; the prose
   rule sits in the marketing shell section below. */
a {
  color: var(--accent);
  text-decoration: none;
  text-decoration-thickness: 1.5px;
  text-underline-offset: 3px;
}

@media (hover: hover) and (pointer: fine) {
  a:hover { text-decoration: underline; }
}

/* FOCUS VISIBLE IS INK, NOT RASPBERRY (phase6r-skin.md section 3). The
   accent's whole budget is links, the active tab underline, the named
   pill, the marked name, the current week column, the interval band and
   the callout dots. A ring around a control is none of those, and an ink
   ring holds 14.6:1 on paper. It never transitions, so it lands in the
   same frame as the focus. */
a:focus-visible, button:focus-visible, input:focus-visible,
select:focus-visible, textarea:focus-visible, summary:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
  border-radius: 3px;
  transition: none;
}

/* A tap is a tap, not a double tap zoom, and it leaves no grey flash. */
a, button, input, select, textarea, summary, label, .btn {
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

h1, h2, h3 { margin: 0 0 var(--s3); overflow-wrap: anywhere; text-wrap: balance; }
h1 { font-size: var(--fs-h1); font-weight: 700; letter-spacing: -0.02em; line-height: var(--lh-display); }
h2 { font-size: var(--fs-h2); font-weight: 600; letter-spacing: -0.01em; line-height: var(--lh-head); }
h3 { font-size: var(--fs-h3); font-weight: 600; letter-spacing: 0; line-height: 1.35; }

p { margin: 0 0 var(--s4); text-wrap: pretty; }
p:last-child { margin-bottom: 0; }

ul, ol { margin: 0 0 var(--s4); padding-left: 1.2em; }
li { margin: 0 0 var(--s2); text-wrap: pretty; }

hr { height: 1px; border: 0; background: var(--line); margin: var(--s5) 0; }

.muted { color: var(--muted); }
.meta { font-size: var(--fs-meta); line-height: 1.5; color: var(--muted); }

/* THE MINI LABEL: the smallest thing on the site, at the floor, in the
   measured face, uppercase and tracked. AMOUNT, CHARGED ON, IMPORTANT, a
   footer column head. */
.mini {
  font-family: var(--font-mono);
  font-size: var(--fs-mini);
  font-weight: 500;
  line-height: 1.2;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-2);
}

/* TABULAR FIGURES ARE FOR MEASURED THINGS ONLY (the tnum punctuation
   lesson). .num is the marker a table cell or a count carries; it is never
   put on prose, where tabular punctuation reads wrong. .mono is the
   measured face itself: counts, timestamps, verbatim answers, money, and
   its zero is slashed, which is what the measured face is for. */
.num { font-variant-numeric: tabular-nums; }
.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-feature-settings: "zero" 1; }

/* GEIST MONO'S SPACE IS WIDE (mockup note 3): 0.6em against Geist's 0.25,
   so "27 of 90" set inside a sentence reads as double spaced. A figure
   that stands inside a line of prose closes the gap; a verbatim answer
   keeps its natural spacing, because that is the vendor's own text. */
.mono { word-spacing: -0.28em; }
.a-body, .obj-body, .answer .excerpt, .answer .rest p { word-spacing: normal; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* The skip link is the first thing in the tab order and has to be visible
   the moment it is focused, or it is a link only a screen reader finds. */
a.sr-only:focus-visible {
  position: fixed;
  top: var(--s3);
  left: var(--s3);
  z-index: 30;
  width: auto;
  height: auto;
  margin: 0;
  padding: var(--s3) var(--s4);
  clip: auto;
  overflow: visible;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  box-shadow: var(--shadow-2);
  color: var(--ink);
  font-weight: 600;
  text-decoration: none;
}

/* THE MARKED NAME: the soft accent fill with a 2px accent rule under it,
   the ink left alone. It is the one place the accent touches text inside a
   quoted answer, and the answer itself is never edited. */
mark {
  background: var(--accent-soft);
  color: inherit;
  box-shadow: inset 0 -2px 0 var(--accent);
  padding: 1px 2px;
  border-radius: 2px;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

/* A match a person is still checking: underlined, never filled. An
   uncertain match is never drawn as a hit. */
mark.possible {
  background: transparent;
  box-shadow: none;
  padding: 0;
  border-radius: 0;
  border-bottom: 2px dashed var(--warn);
}

/* The gutter, or the phone's own safe area when that is wider: on a
   notched handset held sideways the inset is the larger of the two. */
.wrap {
  width: 100%;
  max-width: var(--container);
  margin: 0 auto;
  padding-left: max(var(--gutter), env(safe-area-inset-left));
  padding-right: max(var(--gutter), env(safe-area-inset-right));
}

/* A reading column: the wrap with the measure taken down to one column of
   prose, used by the notice pages and the doors. */
.wrap.narrow { max-width: calc(680px + 2 * var(--gutter)); }

/* The panel ground. Put it on a section, or on main for a notice page. */
.band { background: var(--band); }

/* --------------------------------------------------------------- sections */

.section { padding: var(--section) 0; }
.section.tight { padding: var(--s7) 0; }
.section.hairline { border-top: 1px solid var(--line); }

/* A section head: the heading with its explaining sentence UNDER it, never
   floated beside it. The pair is the ruling's 15 over 13, and the block
   stands 30 above the cards it opens.

   THE MEASURE IS ON THE HEAD, NOT ON ITS SENTENCE (the 1920 law, and the
   shape .price-head and .article already ship). A cap on the paragraph
   leaves the paragraph short inside a full width parent, which is the
   defect the harness measures; the cap belongs to the block that owns the
   reading column, and its children then fill it. Nothing moves on screen
   and the head keeps the page's one left edge. */
.section-head { margin-bottom: var(--s5); max-width: 70ch; }
.section-head h2 { margin: 0; }
.section-head .lede, .section-head p { max-width: none; }
.section-sub { margin: var(--s2) 0 0; font-size: var(--fs-meta); color: var(--ink-2); }
.section-sub.meta { color: var(--muted); }
.section.tight .section-head { margin-bottom: var(--s4); }

.eyebrow {
  font-family: var(--font-mono);
  font-size: var(--fs-mini);
  font-weight: 500;
  line-height: 1.2;
  color: var(--ink-2);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin: 0 0 var(--s2);
}

.lede {
  font-size: var(--fs-lede);
  line-height: 1.5;
  color: var(--ink-2);
  margin: 0 0 var(--s5);
  max-width: 62ch;
}

/* The fine print under a form or a call: the description size, secondary,
   no bottom margin of its own so the block that holds it decides the air. */
.fine { font-size: var(--fs-meta); line-height: 1.5; color: var(--muted); margin: 0; }

/* --------------------------------------------------------------- buttons */

/* FOUR KINDS AND NO MORE (phase6r-skin.md section 3). Filled ink with a
   white 13px label is the action a page wants taken, and there is one of
   them per screen; quiet is card on hairline; ghost is the label alone;
   destructive is filled red. Raspberry is never a button. Every kind is
   34 tall and takes the 8px control radius. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: var(--control);
  padding: 0 var(--s3);
  border: 1px solid var(--button);
  border-radius: var(--radius-s);
  background: var(--button);
  color: var(--button-ink);
  font-family: inherit;
  font-size: var(--fs-meta);
  font-weight: 500;
  line-height: 1;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--dur-1) var(--ease), border-color var(--dur-1) var(--ease), color var(--dur-1) var(--ease), transform var(--dur-1) var(--ease);
}

@media (hover: hover) and (pointer: fine) {
  .btn:hover { background: var(--button-2); border-color: var(--button-2); text-decoration: none; }
}

.btn:active { transform: scale(0.98); }

/* The quiet button: the card ground on the hairline, ink label. It is the
   second action of a pair, and the bar's own control on a page that
   already carries a filled button of its own. */
.btn.outline, .btn.quiet {
  background: var(--surface);
  border-color: var(--line);
  color: var(--ink);
}

@media (hover: hover) and (pointer: fine) {
  .btn.outline:hover, .btn.quiet:hover { background: var(--bg); border-color: var(--line); }
}

/* The ghost button: the label and nothing else, for the help door in a
   header trio. */
.btn.ghost {
  background: transparent;
  border-color: transparent;
  color: var(--ink-2);
}

@media (hover: hover) and (pointer: fine) {
  .btn.ghost:hover { background: var(--band); color: var(--ink); }
}

.btn.small { min-height: var(--control-s); padding: 0 10px; }
.btn.big { min-height: var(--control-l); padding: 0 var(--s4); }
.btn.wide { width: 100%; }

.btn[disabled], .btn[aria-disabled="true"] { opacity: 0.5; cursor: not-allowed; }

/* A destructive action is filled in the failing colour; the word is what
   warns first, the paint second. The bordered kind is the quiet twin. */
.btn.danger { background: var(--bad); border-color: var(--bad); }
@media (hover: hover) and (pointer: fine) {
  .btn.danger:hover { background: #8f1e18; border-color: #8f1e18; }
}
.btn.outline.danger { background: var(--surface); border-color: var(--bad); color: var(--bad); }
@media (hover: hover) and (pointer: fine) {
  .btn.outline.danger:hover { background: var(--bad-bg); border-color: var(--bad); }
}

/* A button that is really a link inside a row of text or a table cell. */
.btn-link {
  display: inline-flex;
  align-items: center;
  gap: var(--s1);
  min-height: 26px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--accent);
  font: inherit;
  font-weight: 500;
  cursor: pointer;
}

@media (hover: hover) and (pointer: fine) {
  .btn-link:hover { text-decoration: underline; }
}

/* A row of actions: the primary first, then whatever stands beside it. */
.actions { display: flex; flex-wrap: wrap; gap: var(--s2); align-items: center; }
.actions form { margin: 0; }

/* THE BUTTON COMPONENT'S LAYERS (components/site/button.blade.php). It
   emits an .edge, a .front and a .label because the Warm craft button was a
   3D press: a black edge with the label riding three pixels above it. This
   button is flat, so the edge draws nothing and the front is simply the
   row the label sits in. The component's markup is not changed here: it is
   the one place every filled button on the site comes through, and one
   sheet is a cheaper place to hold this than nine views. */
.btn .edge { display: none; }
.btn .front, .btn .label { display: inline-flex; align-items: center; justify-content: center; gap: 6px; }

/* The pending state a submitting form puts on its own button: the label
   swaps to the waiting one, the spinner appears, and the control stops
   taking presses. Both labels are rendered by the component and the class
   picks one, so no script ever writes text into a button. */
.btn .spinner { display: none; flex: none; }
.btn.is-pending .spinner { display: block; animation: spin 900ms linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
.btn .when-pending { display: none; }
.btn.is-pending .when-idle { display: none; }
.btn.is-pending .when-pending { display: inline; }
.btn.is-pending { pointer-events: none; opacity: 0.72; }

/* ------------------------------------------------------------------ form */

.form { display: grid; gap: var(--s4); }
.form fieldset { border: 0; padding: 0; margin: 0; min-width: 0; display: grid; gap: var(--s4); }
.form legend { padding: 0; margin: 0 0 var(--s2); font-weight: 600; font-size: var(--fs-h3); }
.form .h3 { font-size: var(--fs-h3); font-weight: 600; margin: 0 0 var(--s2); }

.field { min-width: 0; }
.field label { display: block; font-weight: 500; font-size: var(--fs-meta); line-height: 1.4; margin-bottom: 6px; }
.field .hint { display: block; font-weight: 400; font-size: var(--fs-meta); color: var(--muted); margin: 0 0 6px; }
.field .optional { font-weight: 400; color: var(--muted); }

/* THE LABEL LINE (the login mockup): the label at the left with its one
   link at the right end of the same line, so "I forgot my password" is
   read where it is needed and not under the button. */
.field .label-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s3);
  margin-bottom: 6px;
}
.field .label-row label { margin-bottom: 0; }
.field .label-row .label-link { font-size: var(--fs-meta); font-weight: 400; }

/* INPUTS: 34 tall, 8px radius, ITS OWN BOUNDARY, the focused edge in ink.

   THE EDGE IS --edge AGAIN, AND THAT IS A CORRECTION (T2.12; the owner's
   review of 2026-09-05, "fix the input boundary regression"). The 6R rewrite
   put every border on the one hairline and leaned on the focus ring; a focus
   ring helps after focus and does nothing to help a reader FIND an unfocused
   field on a near white page, and the shipped hairline measured about 1.3:1
   against it. A decorative card border and an input boundary are two
   different jobs: cards keep --line, an input takes --edge (#7c8998, 3.6:1
   on the white field, 3.5:1 on paper, WCAG 1.4.11), hover steps to
   --edge-hover, and focus keeps the 2px ink ring it already had.

   THIS IS A BASELINE CHANGE, NOT A PUBLIC ONE, on purpose: the workspace
   and the operator panel read this same rule and had the same defect, and
   the review names both sheets. Both reference sheets say the same thing
   (PUBLIC-SHEET.md section 4, APP-SHEET.md section 3). T0.6 decision 4,
   "every border is the one hairline", is overturned for inputs and stands
   for everything else. */
.input, select.input, textarea.input {
  display: block;
  width: 100%;
  min-height: var(--control);
  padding: 0 10px;
  background: var(--surface);
  border: 1px solid var(--edge);
  border-radius: var(--radius-s);
  color: var(--ink);
  font-family: inherit;
  font-size: var(--fs-body);
  line-height: 1.3;
  transition: border-color var(--dur-1) var(--ease);
}

textarea.input { min-height: 120px; padding: 8px 10px; line-height: var(--lh); resize: vertical; }
.input[type="file"] { padding-top: 7px; }
.input::placeholder { color: var(--placeholder); opacity: 1; }

@media (hover: hover) and (pointer: fine) {
  .input:hover { border-color: var(--edge-hover); }
}

.input:focus { border-color: var(--ink); }
.input:focus-visible { outline: 2px solid var(--ink); outline-offset: 0; border-color: var(--ink); }

select.input {
  appearance: none;
  -webkit-appearance: none;
  padding-right: var(--s6);
  background-image: var(--chevron);
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 16px;
}

/* A DISABLED FIELD DROPS BACK TO THE HAIRLINE (both sheets, "Disabled:
   panel ground, secondary ink, the hairline"): a control nobody can type in
   does not need to be found. */
.input[disabled], select.input[disabled], textarea.input[disabled] {
  background: var(--band);
  border-color: var(--line);
  color: var(--ink-2);
  cursor: not-allowed;
}

.field.error .input { border-color: var(--bad); border-width: 2px; }
.field .error-text { color: var(--bad); font-size: var(--fs-meta); font-weight: 500; margin: var(--s1) 0 0; }
.field > .not-saved { display: block; margin-top: var(--s1); font-size: var(--fs-meta); font-weight: 500; color: var(--bad); }

/* Two short fields on one row, and only when both are short. */
.field-grid { display: grid; gap: var(--s4) var(--gap); }
@media (min-width: 640px) {
  .field-grid.two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* A checkbox or radio with its sentence beside it, and the explaining line
   under the sentence. The control is 16px with an ink tick, never the
   accent: the accent is for marks and links. The column stays 20 wide, so
   a row keeps a 20px target and the two shipped radio groups keep the grid
   they were built on. */
.checkline {
  display: grid;
  grid-template-columns: 20px minmax(0, 1fr);
  gap: 10px;
  align-items: start;
  margin: 0;
  font-size: var(--fs-body);
  font-weight: 400;
  cursor: pointer;
}
.checkline input { width: 16px; height: 16px; margin: 3px 0 0 2px; accent-color: var(--ink); }
.checkline .meta { display: block; }
.radioline { display: grid; gap: var(--s3); }
.radioline .checkline input { border-radius: 50%; }
.field .radioline .checkline { font-weight: 400; }

/* The Cloudflare widget slot: the real widget is 300 by 65. */
.cf-slot { min-height: 65px; }

/* ------------------------------------------------------- cards and rules */

/* A card is the white surface on a hairline at the 10px card radius. On
   the panel ground it keeps the hairline: this skin has one shadow and it
   is for things that float, so a card never lifts. */
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--s5);
  min-width: 0;
}
.card > :last-child { margin-bottom: 0; }
.band .card, .card.raised { border-color: var(--line); }

.card-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--s2) var(--s4);
  margin: 0 0 var(--s4);
}
.card-title { flex: 0 1 auto; min-width: 0; display: grid; gap: 2px; align-content: start; }
.card-title h1, .card-title h2, .card-title h3 { font-size: var(--fs-h3); font-weight: 600; letter-spacing: 0; line-height: 1.35; margin: 0; text-wrap: balance; }
.card-title .sub { font-size: var(--fs-meta); line-height: 1.5; color: var(--muted); margin: 0; }
.card-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); margin-left: auto; min-width: 0; }
.card-body { display: grid; gap: var(--s3); }
.card-body > p { margin: 0; }

/* The foot of a card: one hairline, then the fact and its door. SHARED
   with the workspace sheet, which draws the same object. */
.card-foot {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--s3);
  margin: var(--s4) calc(-1 * var(--s5)) calc(-1 * var(--s5));
  padding: var(--s3) var(--s5);
  border-top: 1px solid var(--line);
  font-size: var(--fs-meta);
  color: var(--ink-2);
}

/* A notice page's one object: the card that carries a whole short page
   (an error, a confirmation, a door). It is a modal in everything but
   name, so it takes the modal radius and the one shadow. */
.notice-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-l);
  box-shadow: var(--shadow-2);
  padding: var(--s5);
  max-width: 520px;
  margin: 0 auto;
}
@media (max-width: 639px) { .notice-card { padding: var(--s5) var(--s4); } }
.notice-card h1 { font-size: 24px; font-weight: 600; letter-spacing: -0.01em; line-height: 1.2; margin-bottom: var(--s2); }
.notice-card .lede { margin-bottom: var(--s5); font-size: var(--fs-meta); }
.notice-card form { display: grid; gap: var(--s4); }
.notice-card .actions { margin-top: var(--s5); }
.notice-card h2 { font-size: var(--fs-h3); font-weight: 600; margin: var(--s5) 0 var(--s3); }
.notice-card .body { color: var(--ink-2); }

/* A flash: the one sentence a redirect brings with it. The kind is said in
   words as well as in the tint, so it does not depend on colour alone. */
.flash {
  border: 1px solid var(--line);
  border-left: 3px solid var(--ink);
  border-radius: var(--radius-s);
  background: var(--band);
  padding: var(--s3) var(--s4);
  margin: 0 0 var(--s5);
  font-size: var(--fs-body);
}
.flash p { margin: var(--s1) 0 var(--s3); color: var(--ink-2); }
.flash p:last-child { margin-bottom: 0; }
.flash ul { margin: var(--s2) 0 0; }
.flash .actions { margin-top: var(--s3); }
.flash[tabindex="-1"]:focus { outline: none; }
.flash.ok { background: var(--ok-bg); border-left-color: var(--ok); }
.flash.warn { background: var(--warn-bg); border-left-color: var(--warn); }
.flash.bad { background: var(--bad-bg); border-left-color: var(--bad); }

/* A pill says a state in one word. The tint is the marker, the word is the
   meaning; a named pill is the one that takes the accent, and it is not a
   button, so it never takes a border or a press. */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-mini);
  font-weight: 500;
  color: var(--ink-2);
  white-space: nowrap;
}
.pill.named { color: var(--accent); }
.pill.named::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  flex: none;
}

/* A chip: the state as a 20px round label with a dot, in the four kinds
   the ruling names, plus the quiet one a source tag wears. Never red caps,
   never a whole row painted. */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 20px;
  padding: 0 var(--s2);
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--band);
  font-size: var(--fs-mini);
  font-weight: 500;
  line-height: 1;
  color: var(--ink-2);
  white-space: nowrap;
}
.chip::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }
.chip.ok, .chip.fine { color: var(--ok); background: var(--ok-bg); }
.chip.warn { color: var(--warn); background: var(--warn-bg); }
.chip.bad, .chip.fail { color: var(--bad); background: var(--bad-bg); }
.chip.named { color: var(--accent); background: var(--accent-soft); }
.chip.quiet, .chip.pending { color: var(--muted); background: var(--band); }
.chip.quiet::before, .chip.pending::before { background: var(--line); }
/* A source tag names where a reading came from; it is a label, not a
   state, so it carries no dot. */
.chip.src::before { display: none; }

/* A ledger: a label at the left, its figure at the right, hairline rows.
   The figure is measured, so it is the mono face and it is tabular; the
   label is prose, so it is neither. */
.tally { list-style: none; margin: 0; padding: 0; font-size: var(--fs-body); }
.tally li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s3);
  margin: 0;
  padding: var(--s2) 0;
  border-bottom: 1px solid var(--line);
}
.tally li > span:last-child { font-family: var(--font-mono); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* AND A VALUE THAT IS NOT A FIGURE SAYS SO (V1 finding 5, 2026-09-03).
   The measured face is for measured things: counts, timestamps, verbatim
   answers, money. A ledger row's value is not always one of those. "kept
   forever" and "in the mail" on /how-it-works are sentences, and a
   sentence in the measured face with tabular figures is the tnum lesson
   broken; worse, nowrap drops a sentence that will not fit onto a line of
   its own under its label, which breaks the aligned pairs the ledger
   exists to draw.

   THE MARK IS ON THE VALUE, because most ledgers are mixed: the imprint's
   rows are prose beside a VAT number, the queue notice names a business
   and a UTC time, the daily cap page prints "3 of 3" beside "always free,
   does not count". A list whose every value is prose may carry .prose
   once, on the list. */
.tally.prose li > span:last-child, .tally li > span.prose:last-child {
  font-family: var(--font);
  font-variant-numeric: normal;
  white-space: normal;
  text-align: right;
  margin-left: auto;
}

/* AND THE PAIR HOLDS. A ledger row is a wrapping flex line, and flexbox
   decides where to wrap on the items' content widths before it shrinks
   anything, so a long label plus a sentence dropped the sentence onto a
   line of its own and left it hanging at the left margin. Where a value
   has declared itself prose, the label gives up its content width and
   wraps inside its own column instead, so label and value stay a pair. It
   is opt-in twice over, by :has and by the mark, so no ledger that has not
   asked for it changes; the margin above right aligns the value on the
   rare line it still has to itself, which is what a browser with no :has
   gets.

   The basis is 0 and not auto on purpose: flexbox breaks a line on the
   items' CONTENT widths, so a label that keeps its content width as its
   basis still pushes the value off the line however much it could have
   shrunk afterwards. AND THE LABEL KEEPS ITS min-width: auto, the floor at
   its longest word: written with min-width 0 the label could be squeezed
   past its own text, and on /imprint at 390 "Operator" was crushed to a
   few pixels while its own words painted over the company name beside
   it. */
.tally li:has(> span.prose:last-child) > span:first-child,
.tally.prose li > span:first-child { flex: 1 1 0; }

.tally li.total { border-bottom: 0; border-top: 2px solid var(--ink); font-weight: 600; }

/* A table: 36px rows, the head at the mini size in the spoken face, one
   hairline under every row, figures right and tabular. A wide table
   scrolls in its own box, never the page. */
.table { width: 100%; border-collapse: collapse; border-top: 1px solid var(--line); font-size: var(--fs-body); }
.table th, .table td { padding: 9px var(--s2); border-bottom: 1px solid var(--line); text-align: left; vertical-align: top; }
.table th:first-child, .table td:first-child { padding-left: 0; }
.table th:last-child, .table td:last-child { padding-right: 0; }
.table th { font-size: var(--fs-mini); font-weight: 500; line-height: 1.4; color: var(--ink-2); white-space: nowrap; }
.table td { color: var(--ink-2); }
.table td:first-child { color: var(--ink); }
.table td .meta { display: block; }
.table .num { text-align: right; white-space: nowrap; font-family: var(--font-mono); font-size: var(--fs-meta); font-variant-numeric: tabular-nums; font-feature-settings: "zero" 1; }
.table tr.now td, .table tr.you td { color: var(--ink); font-weight: 500; }
.table tr.total td { border-top: 2px solid var(--ink); border-bottom: 0; font-weight: 600; color: var(--ink); }
.table tbody tr.zebra td { background: var(--zebra); }
.table.dense td { font-size: var(--fs-meta); padding-top: 6px; padding-bottom: 6px; }
.table .status-word { font-weight: 500; }
.table .status-word.ok { color: var(--ok); }
.table .status-word.warn { color: var(--warn); }
.table .status-word.bad { color: var(--bad); }
.table .btn-link { min-height: 22px; font-size: var(--fs-meta); }

.scroll { overflow-x: auto; }
.scroll .table { min-width: 560px; }
.scroll .table td:first-child, .scroll .table th:first-child { white-space: nowrap; }

/* THE HATCHED EMPTY STATE (phase6r-skin.md section 4): a sentence, a mono
   hint line under it and one door, on a hatched panel. It is the one place
   the site draws a dashed edge, and it says "nothing here yet" without a
   picture and without an apology. */
.hatch {
  padding: 28px var(--gap);
  text-align: center;
  border: 1px dashed var(--line);
  border-radius: var(--radius-s);
  background: repeating-linear-gradient(45deg, rgba(28, 38, 48, 0.06) 0 1px, transparent 1px 8px);
}
.hatch h2, .hatch h3 { font-size: 18px; font-weight: 600; line-height: 1.3; margin: 0; }
.hatch p { margin: var(--s2) 0 0; color: var(--ink-2); }
.hatch .hint { margin: var(--s1) 0 0; font-family: var(--font-mono); font-size: var(--fs-mini); line-height: 1.5; color: var(--ink-2); }
.hatch .btn { margin-top: var(--s4); }

/* THE SEGMENTED CONTROL: one 34px box, a 28px cell each, the active cell
   filled ink. It is a switch between views of the same thing, never a set
   of buttons, so the filled cell does not count against the one filled
   button a screen is allowed. */
.seg {
  display: inline-flex;
  align-items: center;
  height: var(--control);
  padding: 2px;
  gap: 2px;
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  background: var(--surface);
}
.seg a, .seg button {
  display: inline-flex;
  align-items: center;
  height: 28px;
  padding: 0 10px;
  border: 0;
  border-radius: var(--radius-xs);
  background: transparent;
  color: var(--ink-2);
  font-family: inherit;
  font-size: var(--fs-meta);
  font-weight: 500;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
}
@media (hover: hover) and (pointer: fine) {
  .seg a:hover, .seg button:hover { color: var(--ink); text-decoration: none; }
}
.seg .on, .seg [aria-current="page"], .seg [aria-pressed="true"] { background: var(--ink); color: var(--button-ink); }

/* THE CONFIRM DIALOG AND ITS FROSTED SCRIM (phase6r-skin.md section 4):
   the question as the title, what goes, what stays, what happens next,
   Cancel as text and one filled verb. White frosted rather than a black
   wash, because the page under it is paper and a black wash on paper reads
   as an error. The native element and the class both take it, so a
   <dialog> and a hand built panel look the same. */
.scrim, dialog.dialog::backdrop {
  position: fixed;
  inset: 0;
  z-index: 40;
  background: rgba(255, 255, 255, 0.72);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
}

.dialog {
  width: min(440px, calc(100vw - 2 * var(--s4)));
  padding: var(--s5);
  border: 1px solid var(--line);
  border-radius: var(--radius-l);
  background: var(--surface);
  box-shadow: var(--shadow-2);
  color: var(--ink);
}
dialog.dialog { margin: auto; }
.dialog h2 { font-size: 24px; font-weight: 600; line-height: 1.2; margin: 0 0 var(--s2); letter-spacing: -0.01em; }
.dialog p { margin: 0 0 var(--s3); color: var(--ink-2); }
.dialog ul { margin: 0 0 var(--s3); padding-left: 1.1em; color: var(--ink-2); }
.dialog .dialog-actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--s3); margin-top: var(--s5); }

/* A POPOVER: 312 wide, 40px rows, the modal radius and the one shadow. It
   is the panel a quiet control opens, and every row in it is a real link
   or a real button. */
.pop {
  position: absolute;
  z-index: var(--z-menu);
  min-width: 312px;
  padding: var(--s1);
  border: 1px solid var(--line);
  border-radius: var(--radius-l);
  background: var(--surface);
  box-shadow: var(--shadow-2);
}
.pop ul { list-style: none; margin: 0; padding: 0; }
.pop li { margin: 0; }
.pop a, .pop button {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  width: 100%;
  min-height: 40px;
  padding: 0 var(--s3);
  border: 0;
  border-radius: var(--radius-xs);
  background: none;
  color: var(--ink);
  font-family: inherit;
  font-size: var(--fs-body);
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}
@media (hover: hover) and (pointer: fine) {
  .pop a:hover, .pop button:hover { background: var(--band); text-decoration: none; }
}
.pop a:focus-visible, .pop button:focus-visible { background: var(--band); }
.pop .pop-foot { margin: var(--s1) 0 0; padding: var(--s2) var(--s3); border-top: 1px solid var(--line); font-size: var(--fs-meta); color: var(--ink-2); }

/* THE TWO MONTH CALENDAR, inside a popover, under a quiet "Pick dates"
   beside the preset segments. Two grids side by side from 560, one under
   the other on a phone; a day is a 30px cell, the chosen range is the soft
   accent fill and its two ends are ink. */
.cal { display: grid; gap: var(--s5); padding: var(--s3); }
@media (min-width: 560px) { .cal { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.cal-month { min-width: 0; }
.cal-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); margin-bottom: var(--s2); font-size: var(--fs-meta); font-weight: 500; }
.cal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 2px; }
.cal-grid .dow { font-family: var(--font-mono); font-size: var(--fs-mini); font-weight: 500; text-transform: uppercase; letter-spacing: 0.08em; color: var(--ink-2); text-align: center; padding-bottom: var(--s1); }
.cal-day {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 30px;
  border: 0;
  border-radius: var(--radius-xs);
  background: none;
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: var(--fs-meta);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "zero" 1;
  cursor: pointer;
}
@media (hover: hover) and (pointer: fine) {
  .cal-day:hover { background: var(--band); }
}
.cal-day[disabled] { color: var(--line-2); cursor: not-allowed; }
.cal-day.in { background: var(--accent-soft); border-radius: 0; }
.cal-day.end { background: var(--ink); color: var(--button-ink); border-radius: var(--radius-xs); }

/* ---------------------------------------------------------------- header */

/* THE SLIM TOP BAR (phase6r-skin.md section 2): 46 tall, white, closed by
   one hairline, the mark at the left and the nav at the right. It does not
   stick: these are short pages and a bar that follows the reader is a bar
   that covers the thing they came for. */
.topbar {
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}

/* An anchor still lands clear of the bar on a page that links into
   itself. #keep keeps its own line because it is the receipt's jump from
   the keep strip down to the band that holds the address form, and the
   test that pins that jump names the rule. */
#check, #proof, #how, #count { scroll-margin-top: calc(var(--header) + var(--s4)); }
#keep { scroll-margin-top: calc(var(--header) + var(--s4)); }

.topbar .wrap {
  display: flex;
  align-items: center;
  gap: var(--s4);
  min-height: var(--header);
}

/* THE MARK, AS THE OWNER DREW IT (2026-08-30, kept through this skin
   change). One picture carrying his mesh mark and the wordmark; the name
   is inside the drawing, so the anchor carries it again as sr-only text
   and the picture is decoration. The font properties dress that sr-only
   text and cost nothing on screen. */
.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  font-weight: 700;
  font-size: 16px;
  letter-spacing: -0.01em;
  color: var(--ink);
  text-decoration: none;
  white-space: nowrap;
}

@media (hover: hover) and (pointer: fine) {
  .brand:hover { text-decoration: none; }
}

.brand .logo { display: block; height: 28px; width: auto; flex: none; }

.topbar nav {
  display: flex;
  align-items: center;
  gap: 18px;
  margin-left: auto;
  font-size: var(--fs-body);
}

.topbar nav > a:not(.btn) {
  color: var(--ink);
  font-weight: 500;
  text-decoration: none;
  white-space: nowrap;
}

/* The page being read is underlined in the accent, 2px, 6px under the
   baseline: the one mark of place in the bar. Hover takes the same
   underline to ink, so hovering and standing differ in colour and in
   nothing else.

   THE PUBLIC BAR ONLY. The signed in panel carries its own nav in this
   element and marks its own place, so without :not(.app-nav) a panel page
   would show the mark twice. */
.topbar nav:not(.app-nav) > a[aria-current="page"]:not(.btn) {
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-decoration-color: var(--accent);
  text-underline-offset: 6px;
}

@media (hover: hover) and (pointer: fine) {
  .topbar nav:not(.app-nav) > a[aria-current="page"]:not(.btn):hover { text-decoration-color: var(--ink); }
  .topbar nav:not(.app-nav) > a:not(.btn):hover {
    text-decoration: underline;
    text-decoration-thickness: 2px;
    text-decoration-color: var(--ink);
    text-underline-offset: 6px;
  }
}

/* THE COMPACT MENU (site-chrome.md 1.4): native details, a square summary
   carrying two bars that meet as a cross when it opens, and a panel of
   real links. It exists under 1024 only, where the stylesheet has folded
   the text links into it. */
.site-menu { position: relative; display: none; }
.site-menu > summary {
  list-style: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  margin-right: -10px;
  border-radius: var(--radius-s);
  color: var(--ink);
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  transition: background-color var(--dur-1) var(--ease);
}
.site-menu > summary::-webkit-details-marker { display: none; }
@media (hover: hover) and (pointer: fine) {
  .site-menu > summary:hover { background: var(--band); }
}
.site-menu > summary svg { width: 20px; height: 20px; display: block; overflow: visible; }
.site-menu > summary svg line {
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  transform-origin: 50% 50%;
  transform-box: fill-box;
  transition: transform var(--dur-2) var(--ease);
}
.site-menu[open] > summary .b1 { transform: translateY(4px) rotate(45deg); }
.site-menu[open] > summary .b2 { transform: translateY(-4px) rotate(-45deg); }

.site-menu > ul {
  position: absolute;
  top: calc(100% + var(--s2));
  right: -4px;
  z-index: var(--z-menu);
  margin: 0;
  padding: var(--s1);
  list-style: none;
  min-width: 248px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-l);
  box-shadow: var(--shadow-2);
}
.site-menu li { margin: 0; }
.site-menu li.sep { margin-top: var(--s1); padding-top: var(--s1); border-top: 1px solid var(--line); }
.site-menu > ul a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  min-height: 40px;
  padding: 0 var(--s3);
  border-radius: var(--radius-xs);
  color: var(--ink);
  font-size: var(--fs-body);
  font-weight: 400;
  text-decoration: none;
  white-space: nowrap;
}
@media (hover: hover) and (pointer: fine) {
  .site-menu > ul a:hover { background: var(--band); text-decoration: none; }
}
.site-menu > ul a:focus-visible { background: var(--band); }
.site-menu > ul a[aria-current="page"]::after {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  flex: none;
}

/* The panel arrives 4px down and in, once, on open. Closing is instant; a
   panel that is going away has nothing to say. */
.js .site-menu[open] > ul { animation: menu-in var(--dur-2) var(--ease) both; }
@keyframes menu-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }

/* The bar's button carries a short label on a phone. */
.topbar .btn .short { display: none; }

@media (max-width: 767px) {
  .topbar .btn .long { display: none; }
  .topbar .btn .short { display: inline; }
}

/* The compact bar: the mark, the one control, the menu. The line is 1024
   and not 768, because with Pricing in the row the full bar needs its
   whole width and 768 does not give it. */
@media (max-width: 1023px) {
  .topbar .wrap { gap: var(--s3); }
  .topbar nav { gap: var(--s3); }
  .topbar nav > a:not(.btn) { display: none; }
  .site-menu { display: block; }
}

@media (max-width: 479px) {
  .topbar .wrap, .topbar nav { gap: var(--s2); }
  .topbar .btn.small { min-width: 0; padding: 0 var(--s2); }
}

/* Under 400 the drawing steps down, which is what makes 360 and 375 fit
   without the row scrolling sideways. */
@media (max-width: 399px) {
  .topbar .brand .logo { height: 24px; }
}

/* --------------------------------------------- marketing and legal pages */

/* THE READING PAGE: one column of prose at the ruling's measure, with the
   contents rail beside it from 1100 so the measure cap never leaves a hole
   at the right of a wide screen. */
.article-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s6);
  align-items: start;
}

@media (min-width: 1100px) {
  .article-grid { grid-template-columns: minmax(0, 1fr) 224px; gap: var(--s8); }
  .article-grid .article { margin: 0; }
}

.article { width: 100%; max-width: 68ch; margin: 0 auto; min-width: 0; }
.article h1 { font-size: var(--fs-page); font-weight: 700; letter-spacing: -0.02em; line-height: 1.15; margin-bottom: var(--s4); }
.article h2 { margin: var(--s7) 0 var(--s3); scroll-margin-top: calc(var(--header) + var(--s4)); }
.article h3 { margin: var(--s5) 0 var(--s2); }
.article p, .article li { color: var(--ink-2); }
.article strong { color: var(--ink); }
.article .lede { margin-bottom: var(--s5); max-width: none; }
.article > .eyebrow { color: var(--accent); }

/* In prose a link is underlined at rest: a link a reader has to hover to
   find is not a link. */
.article p a, .article li a, .article dd a { text-decoration: underline; }

/* A quoted or worked example: the panel ground, no border, the figures
   inside it in the measured face. */
.article .example {
  background: var(--band);
  border-radius: var(--radius-s);
  padding: var(--s3) var(--s4);
  margin: 0 0 var(--s5);
}
.article .example p:first-child { color: var(--ink); font-weight: 500; }
.article .example p:last-child { margin-bottom: 0; }
.article .example .mono { font-size: var(--fs-meta); }

.article .scroll { margin: 0 0 var(--s5); }
.article .table th { white-space: normal; }
.article .table td { vertical-align: top; }

.article-foot {
  margin-top: var(--s7);
  padding-top: var(--s5);
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-size: var(--fs-meta);
}
.article-foot .actions { margin-bottom: var(--s4); }

/* A definition list on a legal or method page. */
.defs { margin: 0 0 var(--s5); }
.defs dt { color: var(--ink); font-weight: 600; margin-top: var(--s4); }
.defs dt:first-child { margin-top: 0; }
.defs dd { color: var(--ink-2); margin: var(--s1) 0 0; padding: 0; }

/* The contents rail: real content beside the measure, which is the answer
   this codebase gives to "what is beside the capped text". Under 1100 it
   is not printed at all rather than stacked as a second navigation. */
.toc { display: none; }
@media (min-width: 1100px) {
  .toc { display: block; position: sticky; top: var(--s5); }
}
.toc .eyebrow { color: var(--ink-2); margin-bottom: var(--s3); }
.toc ol { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s1); font-size: var(--fs-meta); }
.toc li { margin: 0; }
.toc a { color: var(--ink-2); text-decoration: none; display: block; padding: var(--s1) 0; }
@media (hover: hover) and (pointer: fine) {
  .toc a:hover { color: var(--ink); text-decoration: none; }
}
.toc a:focus-visible { color: var(--ink); }

/* A list of questions that open, on the FAQ and anywhere else a page owes
   short answers. Native details, one hairline per row, no card. */
.faq-list { max-width: 880px; border-top: 1px solid var(--line); }
.faq-item { border-bottom: 1px solid var(--line); }
/* A linked question lands clear of the bar, on its own line so the rule is
   greppable by the test that pins the anchor law. */
.faq-item { scroll-margin-top: calc(var(--header) + var(--s4)); }
.faq-item summary {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s4);
  padding: var(--s3) 0;
  list-style: none;
  cursor: pointer;
  font-size: var(--fs-body);
  font-weight: 500;
  color: var(--ink);
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary .chevron { flex: none; width: 16px; height: 16px; color: var(--ink-2); transition: transform var(--dur-2) var(--ease); }
.faq-item[open] summary .chevron { transform: rotate(180deg); }
@media (hover: hover) and (pointer: fine) {
  .faq-item summary:hover { color: var(--accent); }
}
.faq-item .rest p { margin: 0 0 var(--s3); color: var(--ink-2); max-width: 70ch; }
.faq-item .rest p:last-child { margin-bottom: var(--s4); }
.faq-item .rest a { text-decoration: underline; }

/* ---------------------------------------------------------------- footer */

/* THE DOORMAT (the landing mockup): the panel ground under a hairline
   rule, the brand cell with its two quiet lines, then the link columns
   under mono uppercase heads, then the legal row. The mockup draws four
   cells; the shipped footer has five, because Learn and Company are real
   pages this site owes a reader, and the grid is written for however many
   the layout prints. */
.foot {
  margin-top: var(--s8);
  background: var(--band);
  border-top: 1px solid var(--line);
  padding: var(--s6) 0 var(--s5);
  font-size: var(--fs-body);
}

/* On a results page the private note is its own line above the columns,
   so the brand cell is the same on every page. */
.foot p.foot-note {
  margin: 0 0 var(--s5);
  max-width: none;
  color: var(--ink-2);
  font-size: var(--fs-meta);
}

.foot-cols { display: grid; gap: var(--s5); align-items: start; }

@media (min-width: 560px) {
  .foot-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s5) var(--s6); }
  .foot-brand { grid-column: 1 / -1; }
}

@media (min-width: 1024px) {
  .foot-cols { grid-template-columns: minmax(0, 1.4fr) repeat(4, minmax(0, 1fr)); gap: var(--s6); }
  .foot-brand { grid-column: auto; }
}

.foot .brand { margin-bottom: var(--s2); font-size: 16px; }
.foot .brand .mark { height: 22px; width: auto; }
.foot .brand .logo { height: 24px; width: auto; }
.foot .foot-line { margin: 0 0 var(--s1); max-width: 36ch; color: var(--ink-2); font-size: var(--fs-meta); text-wrap: pretty; }

.foot h2 {
  font-family: var(--font-mono);
  font-size: var(--fs-mini);
  font-weight: 500;
  line-height: 1.2;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-2);
  margin: 0 0 10px;
}

.foot ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }
.foot li { margin: 0; }
.foot a {
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  color: var(--ink);
  text-decoration: none;
}

@media (min-width: 1024px) {
  .foot ul { gap: 6px; }
  .foot a { min-height: 0; }
}

@media (hover: hover) and (pointer: fine) {
  .foot a:hover { color: var(--accent); text-decoration: underline; }
}

.foot-legal {
  margin-top: var(--s5);
  padding-top: var(--s4);
  border-top: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s3) var(--s5);
  color: var(--ink-2);
  font-size: var(--fs-meta);
}
.foot-legal p { margin: 0; max-width: none; color: var(--ink-2); }
.foot-legal nav { display: flex; flex-wrap: wrap; gap: 0 var(--s5); }
.foot-legal nav a { min-height: 36px; font-size: var(--fs-meta); }
@media (min-width: 1024px) { .foot-legal nav a { min-height: 0; } }

/* ---------------------------------------------------------------- motion */

/* THE WHOLE BUDGET (phase6r-skin.md section 5): 150ms colour and transform
   on a control, one 160ms fade and rise on a card that entered after a
   state change, and nothing loops. The reduced motion block switches off
   every transition and animation this sheet declares, including the ones
   inside pointer gates. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* =====================================================================
   ==== P6R-2 THE LANDING, THE FRAME AND THE RECEIPT ====

   The old P5O-T2 region, folded into this baseline and redrawn on the 6R
   scale. It owns three surfaces and nothing else:

     1. checker/landing.blade.php: the centred text block, the form object
        and the one dominant browser frame with its callouts;
     2. checker/show.blade.php: the whole free receipt, every state,
        including the answer table;
     3. the two receipt components those two pages share with the panel,
        x-receipt.blocker-card and x-receipt.checked-ledger.

   THE VALUES ARE THE MOCKUP'S. Every colour, radius, height and size is
   design/mockups/phase6r/site-landing.html, through the baseline's tokens;
   where the mockup has no equivalent (the receipt has no mockup of its
   own) the grammar is the frame's, one step quieter.

   TWELVE IS THE FLOOR. Nothing here sets a size under var(--fs-mini).

   TABULAR FIGURES ONLY ON FIGURES. .mono carries them from the baseline
   and is put on counts, timestamps and money. A quoted answer is set in
   the measured face WITHOUT them (.a-body, .answer .excerpt), because
   tabular punctuation inside a sentence is the tnum lesson.

   THE NAMES ARE SITE SCOPED, ON PURPOSE (the six-collision lesson of 5g).
   An admin page loads site.css AND admin.css, so an unscoped name written
   here lands on the operator panel as well: .frame is .workframe (admin
   support draws a .frame), .legend is .callout-legend (admin costs draws a
   .legend), .strip is .dotstrip (admin dashboard draws .tiles.strip) and
   .door is .site-door (.door is the admin staff door's own body class).
   ===================================================================== */

/* ------------------------------------------------- landing: the block */

/* ONE CENTRED COLUMN. What stands under this block is the product frame,
   at the full width of the wrap, so there is no hole beside anything. */
.hero.hero-v3 {
  padding: var(--hero) 0 var(--s6);
  text-align: center;
}

.hero-v3 .hero-grid { display: block; }

.hero-v3 .hero-copy {
  max-width: 760px;
  margin: 0 auto;
  min-width: 0;
}

.hero-v3 h1 { margin: 0; }

.hero-v3 .lede {
  margin: var(--s4) auto 0;
  max-width: 62ch;
}

.hero-v3 .flash { margin: var(--s5) auto 0; text-align: left; max-width: 560px; }

/* ---------------------------------------------- landing: the object */

/* THE FORM IS THE SHIPPED OBJECT, RE-SET (checker-form.md, kept by
   contract). Three cells on one centred row, the disclosure and the one
   ink button on the row under them, and the three settings cells drawn
   between the two when the disclosure is open.

   THE CELLS ARE SET LEFT INSIDE A CENTRED ROW. A label centred over its
   own control reads as decoration; the row is centred, the cell is not.

   AND THE HERO'S CONTROLS ARE 40, NOT 34 (mockup note 7). A 34px control
   under a 56px headline reads as a filter rather than the page's one
   action. It is the only place on the site that steps up. */
.check { margin: var(--s5) 0 0; }

.check-box.check-v3 {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: flex-end;
  gap: var(--s2);
  text-align: left;
}

.check-v3 .cell { flex: 0 1 224px; min-width: 0; }
.check-v3 .cell.kind { flex: 0 1 248px; }

.check-v3 .cell label {
  display: block;
  font-size: var(--fs-meta);
  font-weight: 500;
  color: var(--ink);
  margin: 0 0 6px;
}

.check-v3 .cell .optional { font-weight: 400; color: var(--muted); }

.check-v3 .cell-input,
.check-v3 .cell-select {
  display: block;
  width: 100%;
  min-height: var(--control-l);
  padding: 0 var(--s3);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  color: var(--ink);
  font-family: inherit;
  font-size: var(--fs-body);
  font-weight: 400;
  line-height: 1.3;
  transition: border-color var(--dur-1) var(--ease);
}

.check-v3 .cell-input::placeholder { color: var(--placeholder); opacity: 1; }

@media (hover: hover) and (pointer: fine) {
  .check-v3 .cell-input:hover, .check-v3 .cell-select:hover { border-color: var(--line-3); }
}

.check-v3 .cell-input:focus, .check-v3 .cell-select:focus { border-color: var(--ink); }

.check-v3 .cell-select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: var(--s6);
  background-image: var(--chevron);
  background-repeat: no-repeat;
  background-position: right var(--s3) center;
  background-size: 16px;
}

/* The one required question starts unanswered and reads in placeholder
   grey until it is answered. */
.check-v3 .cell-select:required:invalid { color: var(--placeholder); }

.check-v3 .cell.error .cell-input,
.check-v3 .cell.error .cell-select { border-color: var(--bad); border-width: 2px; }

/* THE THREE SETTINGS CELLS ARE DRAWN BY THE DISCLOSURE (:has), so nothing
   about them depends on script. A browser with no :has support simply
   shows them, and no field is ever unreachable. */
.check-v3 .cell.website,
.check-v3 .cell.country,
.check-v3 .cell.language { display: none; }

.check-box.check-v3:has(.check-more[open]) .cell.website,
.check-box.check-v3:has(.check-more[open]) .cell.country,
.check-box.check-v3:has(.check-more[open]) .cell.language { display: block; }

@supports not selector(:has(*)) {
  .check-v3 .cell.website, .check-v3 .cell.country, .check-v3 .cell.language { display: block; }
}

/* The entrance the rows take when a READER opens the row. A page load is
   not something a reader did, so the server-open state skips it. */
@media (prefers-reduced-motion: no-preference) {
  .check-box.check-v3:has(.check-more[open]:not(.served-open)) .cell.website,
  .check-box.check-v3:has(.check-more[open]:not(.served-open)) .cell.country,
  .check-box.check-v3:has(.check-more[open]:not(.served-open)) .cell.language {
    animation: cell-in var(--dur-3) var(--ease-enter) both;
  }
  @keyframes cell-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
}

.check-v3 .cell-more { flex: 1 0 100%; display: grid; gap: var(--s2); }
.check-v3 .cell-more .cell { flex: none; max-width: 320px; }
.cell-more-note { margin: 0; font-size: var(--fs-meta); color: var(--muted); max-width: 62ch; }

/* The object's lower edge: the disclosure and the one ink button, on a
   centred row of their own under the cells. */
.check-v3 .check-foot {
  flex: 1 0 100%;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--s3);
  margin-top: var(--s2);
}

.check-more { min-width: 0; }
.check-more > .more-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: var(--control-l);
  padding: 0 var(--s2);
  list-style: none;
  cursor: pointer;
  color: var(--ink-2);
  font-size: var(--fs-meta);
  font-weight: 500;
}
.check-more > .more-toggle::-webkit-details-marker { display: none; }
.check-more .chevron { width: 16px; height: 16px; transition: transform var(--dur-2) var(--ease); }
.check-more[open] .chevron { transform: rotate(180deg); }
@media (hover: hover) and (pointer: fine) {
  .check-more > .more-toggle:hover { color: var(--ink); }
}

.check-errors { margin: var(--s3) 0 0; display: grid; gap: var(--s1); }
.check-errors p { margin: 0; color: var(--bad); font-size: var(--fs-meta); font-weight: 500; }

.turnstile { margin: var(--s4) 0 0; display: flex; justify-content: center; }
.turnstile:empty { display: none; }

.hero-v3 .hero-meta {
  margin: var(--s3) 0 0;
  font-size: var(--fs-meta);
  color: var(--muted);
}

/* NO PRICE ON THE FRONT PAGE (owner order, 2026-09-03, restated by the
   designer's session ruling of 2026-09-05 on the 6R mockup): the price
   line and the plan roster under the hero are not drawn, and the view does
   not print them. The two rules are kept as empty homes for nothing; the
   classes stay declared so a stray .price in a hero cannot inherit the
   pricing page's own figure size. */
.hero-v3 .price, .hero-v3 .roster {
  margin: var(--s2) auto 0;
  max-width: 62ch;
  font-size: var(--fs-meta);
  color: var(--ink-2);
}

@media (max-width: 639px) {
  .check-v3 .cell, .check-v3 .cell.kind { flex: 1 0 100%; }
  .check-v3 .cell-more .cell { max-width: none; }
  .check-v3 .check-foot { flex-direction: column-reverse; align-items: stretch; }
  .check-v3 .check-foot .btn { width: 100%; }
  .check-more > .more-toggle { justify-content: center; }
}

/* ------------------------------------------------- landing: the frame */

/* THE ONE DOMINANT OBJECT. A browser chrome frame with the workspace
   inside it, rendered in real markup at natural size: never an img, never
   a scaled screenshot, so every word in it is selectable, translated and
   over the floor. It floats, which is what earns it the one shadow. */
.stage { margin: 0 auto; padding: var(--s4) 0 0; }

.workframe {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-l);
  box-shadow: var(--shadow-2);
  overflow: visible;
}

/* ONE ENTRANCE, WITH FILL-MODE BOTH, and nothing else on this page moves
   by itself. Off entirely under reduced motion (the baseline's block
   zeroes the duration; this keeps the end state visible). */
@media (prefers-reduced-motion: no-preference) {
  .workframe { animation: frame-in var(--dur-3) var(--ease-enter) 100ms both; }
  @keyframes frame-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
}

.workframe .chrome {
  display: flex;
  align-items: center;
  gap: 10px;
  height: 38px;
  padding: 0 14px;
  background: var(--band);
  border-bottom: 1px solid var(--line);
  border-radius: var(--radius-l) var(--radius-l) 0 0;
}

.workframe .dots { display: flex; gap: 6px; flex: none; }
.workframe .dots i { width: 9px; height: 9px; border-radius: 50%; background: #c6d0da; }

.workframe .url {
  font-size: var(--fs-mini);
  color: var(--ink-2);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-xs);
  padding: 5px 10px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.fr-app { display: grid; grid-template-columns: 174px minmax(0, 1fr); }

.fr-side {
  background: var(--band);
  border-right: 1px solid var(--line);
  border-radius: 0 0 0 var(--radius-l);
  padding: var(--s3) var(--s2);
  font-size: var(--fs-meta);
  min-width: 0;
}
.fr-side p { margin: 0; }
.fr-brand { font-weight: 700; font-size: var(--fs-body); margin: 0 0 var(--s3) 6px !important; }
.fr-biz { font-weight: 500; line-height: 1.3; padding-left: 6px; }
.fr-city { color: var(--ink-2); padding-left: 6px; }
.fr-nav { list-style: none; padding: 0; margin: var(--s3) 0 0; display: grid; gap: 2px; }
.fr-nav li { margin: 0; display: flex; align-items: center; height: 30px; padding: 0 var(--s2); border-radius: var(--radius-xs); color: var(--ink-2); font-size: var(--fs-body); }
.fr-nav li.on { background: var(--surface); color: var(--ink); font-weight: 500; box-shadow: var(--shadow-1); }
.fr-plan {
  border-top: 1px solid var(--line);
  margin: var(--s3) 6px 0 6px !important;
  padding-top: var(--s2);
  color: var(--ink-2);
  line-height: 1.5;
}

.fr-main { padding: var(--s5) var(--s5) var(--s5); min-width: 0; }
.fr-eyebrow { margin: 0; font-size: var(--fs-meta); color: var(--ink-2); }
.fr-h {
  margin: var(--s1) 0 0;
  font-size: clamp(20px, 2.4vw, 26px);
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.2;
}
.fr-h .mono { font-weight: 600; }
/* The interval line runs the frame's own column: it is one sentence with a
   callout pinned to its end, and nothing stands beside it, so a measure cap
   here would be a hole at the right of the frame at 1920. */
.fr-interval {
  position: relative;
  margin: 6px 0 0;
  font-size: var(--fs-body);
  color: var(--ink-2);
}
.fr-interval .callout { position: static; display: inline-block; transform: none; vertical-align: -3px; margin-left: var(--s2); }

.fr-tbl {
  margin-top: var(--s4);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.fr-thead {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--s3);
  padding: var(--s3) var(--s4) 10px;
  border-bottom: 1px solid var(--line);
  font-size: var(--fs-meta);
  color: var(--ink-2);
}
.fr-thead strong { color: var(--ink); font-size: var(--fs-h3); font-weight: 600; }

/* THE SUBTOTAL ROW that opens a group: the assistant, its own count, and
   the same count drawn as one cell per answer. */
.fr-grp {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  min-height: var(--row);
  padding: 6px var(--s4);
  background: var(--band);
  border-bottom: 1px solid var(--line);
  font-size: var(--fs-meta);
}
.fr-grp .g-name { font-weight: 600; font-size: var(--fs-body); min-width: 0; }
.fr-grp .g-sum { display: inline-flex; align-items: center; gap: 10px; color: var(--ink-2); white-space: nowrap; }

.dotstrip { display: inline-flex; gap: 2px; flex: none; }
.dotstrip i { width: 8px; height: 8px; border-radius: 2px; background: var(--line); }
.dotstrip i.on { background: var(--accent); }

/* THE ROW OPENS INLINE, NATIVELY. No script anywhere in this table. */
.fr-row { border-bottom: 1px solid var(--line); }
.fr-row > summary {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s3);
  min-height: var(--row);
  padding: 6px var(--s4);
  font-size: var(--fs-body);
  cursor: pointer;
  list-style: none;
}
.fr-row > summary::-webkit-details-marker { display: none; }
.fr-row > summary .q { min-width: 0; color: var(--ink); }
@media (hover: hover) and (pointer: fine) {
  .fr-row > summary:hover .q { color: var(--accent); }
}

.fr-answer {
  position: relative;
  margin: 0 var(--s4) var(--s3);
  padding: var(--s3) 34px var(--s3) 14px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
}
.fr-answer .a-head {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--s2);
  margin: 0 0 var(--s2);
  font-size: var(--fs-meta);
  color: var(--ink-2);
}
/* The quoted answer is the measured face and NOT tabular: it is a
   sentence, and tabular punctuation inside prose is the tnum lesson. */
.fr-answer .a-body {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--fs-body);
  line-height: 1.6;
  overflow-wrap: break-word;
}

.fr-more {
  margin: 0;
  padding: 10px var(--s4);
  border-bottom: 1px solid var(--line);
  font-size: var(--fs-meta);
  color: var(--ink-2);
}

/* THE SUM ROW, UNDER THE 2px RULE. It is the frame's headline restated
   nowhere: the headline is read off these same two numbers. */
.fr-sum {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--s3);
  padding: var(--s3) 34px var(--s3) var(--s4);
  border-top: 2px solid var(--ink);
  border-radius: 0 0 var(--radius) var(--radius);
  background: var(--surface);
  font-size: var(--fs-body);
  font-weight: 600;
}
.fr-sum .mono { font-weight: 600; }

/* THE THREE CALLOUTS. A numbered raspberry disc pinned to the object it
   points at, with the words in the legend under the frame. They are
   aria-hidden: a bare "2" read aloud over an answer is noise, and the
   legend rows are the content. Raspberry here is a mark, never a button:
   nothing about a dot is pressable. */
.callout {
  position: absolute;
  top: 50%;
  right: -13px;
  transform: translateY(-50%);
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  font-family: var(--font-mono);
  font-size: var(--fs-meta);
  font-weight: 600;
  line-height: 26px;
  text-align: center;
  box-shadow: 0 0 0 4px var(--bg);
}
.fr-answer .callout { top: 12px; transform: none; }

.stage-cap {
  margin: var(--s3) 0 0;
  text-align: center;
  font-size: var(--fs-meta);
  color: var(--muted);
}

.callout-legend {
  list-style: none;
  margin: var(--s5) auto 0;
  padding: 0;
  max-width: 860px;
  display: grid;
  gap: 10px;
}
.callout-legend li { display: flex; gap: var(--s3); align-items: baseline; margin: 0; }
.callout-legend .n {
  flex: none;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  font-family: var(--font-mono);
  font-size: var(--fs-mini);
  font-weight: 600;
  line-height: 24px;
  text-align: center;
}
.callout-legend p { margin: 0; min-width: 0; color: var(--ink-2); }
.callout-legend strong { color: var(--ink); font-weight: 600; }

/* The door and the one honesty sentence: the whole tail of the page. */
.site-door { text-align: center; padding: var(--s6) 0 var(--s2); }
.site-door .fine { margin: 10px 0 0; }
.honesty {
  max-width: 680px;
  margin: var(--s5) auto var(--s8);
  text-align: center;
  color: var(--ink-2);
  font-size: var(--fs-body);
}
.honesty a { text-decoration: underline; white-space: nowrap; }

/* THE FRAME CROPS ITS OWN SIDEBAR UNDER 760, exactly as a screenshot of a
   narrow window would. */
@media (max-width: 760px) {
  .fr-app { grid-template-columns: minmax(0, 1fr); }
  .fr-side { display: none; }
  .fr-main { padding: var(--s4) var(--s4) var(--s4); }
  .callout { right: -8px; }
  .fr-grp, .fr-row > summary, .fr-sum { flex-wrap: wrap; }
}

/* ------------------------------------------------------- the receipt */

/* ONE COLUMN, TOP TO BOTTOM, ON EVERY STATE (R5.1). Nothing stands beside
   the head: the ask moved under it on the open states and into the band at
   the foot on a finished one, so there is no track with nothing in it. */
.receipt { display: block; }
.receipt-notice { margin: 0 0 var(--s5); }
.receipt-main { min-width: 0; }
.receipt-side, .receipt-ask { margin: var(--s6) 0 0; min-width: 0; }
.receipt-wait, .receipt-tail { margin: var(--s6) 0 0; }
.receipt-main .eyebrow-chip { margin: 0 0 var(--s3); }
.receipt-main h1 { font-size: var(--fs-title); font-weight: 600; letter-spacing: -0.01em; margin-bottom: var(--s2); }
.receipt-main > .meta { margin: 0 0 var(--s4); }
.receipt-main > .note { color: var(--ink-2); font-size: var(--fs-meta); }

/* THE SCOREBOARD: the count on the panel ground, with the usual range
   instrument under it. One column, because the per assistant split is the
   answer table's subtotal rows now and nothing else stands here. */
.scoreboard { margin: 0 0 var(--s5); }

.rcpt-frame {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}
.rcpt-pane { background: var(--band); padding: var(--s5); }

/* THE RECEIPT SENTENCE, the one head this product writes: the words at the
   reading size and the count in the measured face at 30, which is the
   ruling's head sentence exactly. */
.count { margin: 0; }
.count .n { display: block; line-height: 1.2; }
.count .lead, .count .unit { font-size: var(--fs-lede); font-weight: 500; color: var(--ink-2); }
.count .fig {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "zero" 1;
  font-size: var(--fs-count);
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
  margin: 0 6px;
}
/* A queued check has no figure yet, so the lead is the whole sentence and
   takes the figure's own size for exactly as long as the figure is empty. */
.count:has(.fig:empty) .lead { font-size: var(--fs-count); font-weight: 600; color: var(--ink); }
.count .pm { display: block; margin-top: var(--s2); font-size: var(--fs-meta); color: var(--muted); }

/* THE USUAL RANGE INSTRUMENT: N + 1 whole cells, one per possible count,
   the likely band tinted across the cells it covers and this check's own
   count marked on one of them. Grid lines, never a share. */
.ruler { margin: var(--s4) 0 0; }
.ruler-track {
  position: relative;
  display: grid;
  grid-template-columns: repeat(var(--cells), minmax(0, 1fr));
  height: 12px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-xs);
  overflow: hidden;
}
.ruler-band {
  grid-column: var(--band-start) / var(--band-end);
  grid-row: 1;
  background: var(--accent-soft);
}
.ruler-mark {
  grid-column: var(--mark-at) / span 1;
  grid-row: 1;
  background: var(--accent);
}
.ruler-ends {
  display: flex;
  justify-content: space-between;
  gap: var(--s3);
  margin: 6px 0 0;
  font-size: var(--fs-mini);
  color: var(--muted);
}
.ruler-ends .num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-feature-settings: "zero" 1; }

/* THE MEASURE IS NOT CAPPED ON THE RECEIPT'S OWN LINES (the owner's
   layout law read the other way round). .receipt .meta and the caption
   under the named table run the width of the column they are in, because
   nothing stands beside them and a capped line with a hole at its right
   is the defect. */
.pm-line {
  margin: var(--s4) 0 0;
  font-size: var(--fs-meta);
  color: var(--ink-2);
}
.pm-line .info { display: inline-flex; vertical-align: -3px; margin-left: 6px; color: var(--ink-2); }
@media (hover: hover) and (pointer: fine) {
  .pm-line .info:hover { color: var(--accent); }
}

/* THE ASKED FRAME (Phase 5l R1 2.2): a hairline ruled region of the paper
   itself, never a third card grammar between the receipt and the blockers.
   Two cells from 980, the note in the pane's own column, the questions
   filling the rest of the row by construction. */
.asked-frame {
  display: grid;
  gap: var(--s4);
  margin: 0 0 var(--s5);
  padding: var(--s4) 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
@media (min-width: 980px) {
  .asked-frame { grid-template-columns: 340px minmax(0, 1fr); gap: var(--s6); }
}
.af-head .eyebrow { margin-bottom: var(--s2); }
.af-note { margin: 0; font-size: var(--fs-meta); color: var(--ink-2); }
.af-questions { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s3); min-width: 0; }
.af-questions li { margin: 0; }
.af-q-meta { display: block; font-size: var(--fs-mini); color: var(--muted); }
.af-q { margin: 2px 0 0; font-weight: 500; }

/* THE KEEP STRIP: one quiet line saying where this report can live. Not a
   card, no tint, no form, and the claim is the quiet kind so the page's
   one fill is still the band's claim at the foot. */
.keep-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s3) var(--s4);
  margin: 0 0 var(--s5);
  padding: var(--s3) 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.keep-strip p { margin: 0; font-size: var(--fs-meta); color: var(--ink-2); min-width: 0; }
.keep-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s3); margin-left: auto; }

/* The progress block on an open check. The bar says in words what it says
   in pixels, through aria-valuetext. */
.progress { margin: 0 0 var(--s5); }
.progress h2 { font-size: var(--fs-h3); margin-bottom: var(--s2); }
.track {
  height: 8px;
  background: var(--band);
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  overflow: hidden;
}
/* THE FILL IS INK, NOT RASPBERRY (V1 finding 6, ruled 2026-09-03). The
   accent is spent on links, the marked name, the named pill, the current
   week column, the interval band and the callout dots, and on nothing
   else. A progress bar is not on that list, and at full width it was the
   largest block of accent in the product, on the one screen a customer
   watches for two minutes. */
.track .fill {
  height: 100%;
  width: calc(var(--fill) * 100%);
  background: var(--ink);
  transition: width var(--dur-3) var(--ease);
}
.progress .counts { margin: var(--s3) 0 var(--s1); font-weight: 500; }
.progress .meta { margin: 0; }

/* ------------------------------------------------- the answer table */

/* THE RECEIPT'S ANSWER TABLE, the same grammar the landing frame draws,
   one step larger because it is the page's own surface. */
.atable {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  margin: var(--s5) 0 0;
}

.atable-head {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--s3);
  padding: var(--s4) var(--gap) var(--s3);
  border-bottom: 1px solid var(--line);
  font-size: var(--fs-meta);
  color: var(--ink-2);
}
.atable-head strong { color: var(--ink); font-size: var(--fs-h3); font-weight: 600; }

.agrp {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  min-height: var(--row);
  padding: 6px var(--gap);
  background: var(--band);
  border-bottom: 1px solid var(--line);
  font-size: var(--fs-meta);
}
.agrp .g-name { font-weight: 600; font-size: var(--fs-body); min-width: 0; }
.agrp .g-name .note { display: block; font-size: var(--fs-meta); font-weight: 400; color: var(--muted); }
.agrp .g-name .note:empty { display: none; }
.agrp .g-sum { display: inline-flex; align-items: center; gap: 10px; white-space: nowrap; }
.agrp .g-sum .mono { font-weight: 500; }

.arow-waiting {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s3);
  min-height: var(--row);
  padding: 6px var(--gap);
  border-bottom: 1px solid var(--line);
  font-size: var(--fs-meta);
  color: var(--ink-2);
}

.arow { border-bottom: 1px solid var(--line); }
.arow > summary {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s3);
  min-height: var(--row);
  padding: 6px var(--gap);
  list-style: none;
  cursor: pointer;
  font-size: var(--fs-body);
}
.arow > summary::-webkit-details-marker { display: none; }
.arow > summary .q { min-width: 0; color: var(--ink); font-weight: 400; }
@media (hover: hover) and (pointer: fine) {
  .arow > summary:hover { background: var(--zebra); }
  .arow > summary:hover .q { color: var(--accent); }
}
.arow > summary .pill.named, .arow > summary .pill.picked { color: var(--accent); }
.arow > summary .pill.picked::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  flex: none;
}

/* THE SUM ROW UNDER THE 2px RULE, and it is where the count at the head of
   the page comes from. */
.asum {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--s3);
  padding: var(--s3) var(--gap);
  border-top: 2px solid var(--ink);
  border-radius: 0 0 var(--radius) var(--radius);
  background: var(--surface);
  font-size: var(--fs-body);
  font-weight: 600;
}
.asum .s-count { font-weight: 600; }

/* ONE ANSWER, WORD FOR WORD (x-receipt.answer-card, shared with the
   panel). Inside a row it is flat: the row is the box, so the card draws
   no second border. */
.answer { min-width: 0; }
.arow .answer { padding: 0 var(--gap) var(--s4); }
.answer-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s2) var(--s3);
  margin: 0 0 var(--s2);
  font-size: var(--fs-meta);
  color: var(--ink-2);
}
.answer-head .who { display: inline-flex; flex-wrap: wrap; gap: var(--s2); min-width: 0; }
.answer-head .engine { font-weight: 600; color: var(--ink); }
.answer-head .asked { color: var(--muted); font-family: var(--font-mono); }
.answer-head .asked:empty { display: none; }

/* INSIDE A ROW THE VERDICT IS SAID ONCE. The row's own summary carries the
   pill, so the card's chip four lines under it is the same word twice; it
   is taken out of the picture and out of the reading order together. On
   any other surface that shows this card (the panel) the chip is the only
   place the verdict is written, so the rule is scoped to the row. */
.arow .answer-head .chip { display: none; }

.answer-body {
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  padding: var(--s3) var(--s4);
}
/* The quoted answer: the measured face, and NOT tabular, because it is a
   sentence and not a figure. */
.answer .excerpt, .answer .rest p {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--fs-body);
  line-height: 1.6;
  overflow-wrap: break-word;
}
.answer-body > p { margin: 0; font-size: var(--fs-meta); color: var(--ink-2); }

/* The disclosure inside a card OPENS the rest under the excerpt; it never
   swaps it. With no rest to open the control is not drawn at all. */
.answer .more { margin: var(--s2) 0 0; }
.answer .more.auto { display: none; }
.answer .more > summary {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  list-style: none;
  cursor: pointer;
  color: var(--accent);
  font-family: var(--font);
  font-size: var(--fs-meta);
  font-weight: 500;
}
.answer .more > summary::-webkit-details-marker { display: none; }
.answer .more .chevron { transition: transform var(--dur-2) var(--ease); }
.answer .more[open] .chevron { transform: rotate(180deg); }
.answer .more .when-open { display: none; }
.answer .more[open] .when-closed { display: none; }
.answer .more[open] .when-open { display: inline; }
.answer .more .rest { margin: var(--s2) 0 0; }

.answer-foot {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2) var(--s4);
  margin: var(--s2) 0 0;
  font-size: var(--fs-meta);
  color: var(--muted);
}
.answer-foot span:empty { display: none; }

/* --------------------------------------------- blockers and readings */

.blocker {
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 3px solid var(--line-2);
  border-radius: var(--radius);
  padding: var(--s5);
  margin: 0 0 var(--s4);
  min-width: 0;
}
.blocker.bare { border: 0; border-radius: 0; padding: 0; background: none; }
.blocker.fail { border-left-color: var(--bad); }
.blocker.warn { border-left-color: var(--warn); }
.blocker.ok { border-left-color: var(--ok); }
.blocker-head { margin: 0 0 var(--s3); }
.blocker-head h3 { margin: var(--s1) 0 0; }
.status {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-mono);
  font-size: var(--fs-mini);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-2);
}
.status.fail { color: var(--bad); }
.status.warn { color: var(--warn); }
.status.ok { color: var(--ok); }
.status.unknown, .status.waiting { color: var(--muted); }
.blocker dl { margin: 0; display: grid; gap: var(--s3); }
@media (min-width: 900px) {
  .blocker dl { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--gap); }
}
.blocker dl > div { min-width: 0; }
.blocker dt {
  font-family: var(--font-mono);
  font-size: var(--fs-mini);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  margin: 0 0 var(--s1);
}
.blocker dd { margin: 0; color: var(--ink-2); }

.blockers-foot { margin: var(--s4) 0 0; display: grid; gap: var(--s2); }
.blockers-foot .meta { margin: 0; }
.blockers-foot .show-all {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: var(--control);
  list-style: none;
  cursor: pointer;
  color: var(--accent);
  font-size: var(--fs-meta);
  font-weight: 500;
}
.blockers-foot .show-all::-webkit-details-marker { display: none; }
.blockers-foot .chevron { transition: transform var(--dur-2) var(--ease); }
.blockers-foot .more[open] .chevron { transform: rotate(180deg); }
.blockers-foot .more .when-open { display: none; }
.blockers-foot .more[open] .when-closed { display: none; }
.blockers-foot .more[open] .when-open { display: inline; }
.blockers-foot .more .rest { margin: var(--s4) 0 0; }

/* The checks ledger, shared with the panel: what we read, how it went, the
   evidence, and the tag naming where the reading came from. */
.checked { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--line); }
.checked li {
  display: grid;
  gap: var(--s1) var(--s4);
  grid-template-columns: minmax(0, 1fr);
  margin: 0;
  padding: var(--s2) 0;
  border-bottom: 1px solid var(--line);
  font-size: var(--fs-meta);
  color: var(--ink-2);
}
@media (min-width: 900px) {
  .checked li { grid-template-columns: 200px 110px minmax(0, 1fr) 110px; align-items: baseline; }
}
.checked .what { color: var(--ink); font-weight: 500; }
.checked .tag { color: var(--muted); }

.tag-legend {
  display: grid;
  gap: var(--s2) var(--gap);
  margin: var(--s4) 0 0;
  font-size: var(--fs-meta);
}
@media (min-width: 900px) {
  .tag-legend { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
.tag-legend > div { min-width: 0; }
.tag-legend dt { font-weight: 600; color: var(--ink); }
.tag-legend dd { margin: 0; color: var(--muted); }

/* Named beside you: the shipped table, under the answers it was counted
   from. The caption under it is not capped. */
.named-solo h2 { margin-bottom: var(--s3); }
table.ledger { width: 100%; border-collapse: collapse; border-top: 1px solid var(--line); font-size: var(--fs-body); }
table.ledger td {
  padding: 9px var(--s2);
  border-bottom: 1px solid var(--line);
  vertical-align: top;
  color: var(--ink-2);
}
table.ledger td:first-child { padding-left: 0; color: var(--ink); }
table.ledger td:last-child {
  padding-right: 0;
  text-align: right;
  white-space: nowrap;
  font-family: var(--font-mono);
  font-size: var(--fs-meta);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "zero" 1;
}
table.ledger tr.you td { color: var(--ink); font-weight: 500; }
.named-solo > .meta { margin: var(--s3) 0 0; }

/* ------------------------------------------------------ the two asks */

.ask { min-width: 0; }
.ask h2, .ask h3 { font-size: var(--fs-h3); margin-bottom: var(--s2); }
.ask > p { color: var(--ink-2); }
.ask .fine { margin-top: var(--s2); }
.ask form { display: grid; gap: var(--s3); max-width: 420px; }
.ask form .btn { justify-self: start; }
.ask .btn.block { width: 100%; justify-self: stretch; }

/* The wide ask: text beside form, which fills the row by construction and
   leaves no hole at 1400. */
.ask.wide {
  display: grid;
  gap: var(--s4) var(--s6);
  padding: var(--s5);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
@media (min-width: 900px) {
  .ask.wide { grid-template-columns: minmax(0, 1fr) minmax(0, 420px); align-items: start; }
}
.ask.wide .ask-text { min-width: 0; }
.ask.wide form.inline { max-width: none; }

.ask.done {
  padding: var(--s5);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

/* ONE NEXT STEP (R5.6): the claim as the primary half and the mail form as
   the quieter half behind a hairline. Not sticky, by spec. */
.ask.next-step {
  display: grid;
  gap: var(--s5);
  padding: 0;
  background: none;
  border: 0;
}
@media (min-width: 900px) {
  .ask.next-step { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--s7); align-items: start; }
  .next-alt { border-left: 1px solid var(--line); padding-left: var(--s7); }
}
@media (max-width: 899px) {
  .next-alt { border-top: 1px solid var(--line); padding-top: var(--s5); }
}
.next-main, .next-alt { min-width: 0; }
.next-main .btn { margin: var(--s4) 0 0; }
.next-main .fine { margin-top: var(--s3); }
.sample-link { margin: var(--s4) 0 0; font-size: var(--fs-meta); }
.method-note { margin: var(--s6) 0 0; font-size: var(--fs-meta); }

/* The chip a pending strip carries, and the receipt's own eyebrow chip. */
.eyebrow-chip { margin: 0 0 var(--s3); }

/* =====================================================================
   ==== P6R-3 THE MARKETING, LEGAL AND NOTICE PAGES ====

   The old P5O-T3 region, folded into this baseline and redrawn on the 6R
   scale. It owns /how-it-works, /pricing, /faq, /about, /contact, /claim,
   the two /learn pages, the four legal pages, the layout error pages, the
   two checker notices and the mail preference page.

   THE MONEY IS MEASURED, SO THE MONEY IS MONO. A plan's amount, a VAT
   figure, a count in a comparison cell and the roster table's passes are
   all Geist Mono with tabular figures, and the prose beside them is Geist
   with none. On this page that is also what replaced the display figure.

   COLLISIONS: site.css is read by the app and the admin panels as well as
   by the public site, so every rule that could reach another surface is
   scoped by an ancestor this surface owns (.pricing-top, .how-steps,
   .never, .article, .notice-card). The names that are deliberately shared
   with a panel view, because the object is the same object, are marked
   SHARED where they are written.
   ===================================================================== */

/* ---------------------------------------------------- the reading page */

/* The article pages set their own rhythm with .section, so .article-grid
   only has to be the grid. The two grid children each keep their own
   minimum, which is what stops a long unbroken URL in a legal paragraph
   from pushing the rail off the screen. */
.article-grid > .article, .article-grid > .toc { min-width: 0; }

/* A ledger inside the reading column holds FACTS, NOT FIGURES: the
   company's postal address on /imprint is prose and wraps. That is
   answered by the value level .prose mark in the baseline above, and the
   two views carry it; the imprint's VAT number stays measured beside them,
   which is exactly what a scoped exception could not have done. */

/* The closing door at the foot of a learn page: the heading and the fact
   line keep the column's full measure and only the button shrinks to its
   label, so no block in the door stands short of its container. */
.article .learn-door {
  margin-top: var(--s7);
  padding-top: var(--s5);
  border-top: 2px solid var(--ink);
}
.article .learn-door h2 { margin-top: 0; }
.article .learn-door .btn { margin: var(--s4) 0 0; }
.article .learn-door .meta { margin: var(--s3) 0 0; }

/* --------------------------------------------------- the closing door */

/* SHARED with the panel's own sample page, which closes the same way: a
   centred line, a button and one fact, on the page's own ground. */
.section.closing { text-align: center; border-top: 1px solid var(--line); }
.section.closing h2 { margin-bottom: var(--s4); }
.closing-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--s3) var(--s6);
  margin: var(--s4) 0 0;
}
.closing-links a { color: var(--ink); font-weight: 500; }
.section.closing .hero-meta, .section.closing .fine {
  margin: var(--s3) 0 0;
  font-size: var(--fs-meta);
  color: var(--muted);
}

/* ------------------------------------------------------------ /pricing */

/* Everything on this page is scoped by .pricing-top or by a class this
   page alone carries, because .plan, .plans and .price all name something
   else in the app panel. */
.pricing-top .price-head { max-width: 70ch; margin-bottom: var(--s6); }
.pricing-top .price-head h1 { font-size: var(--fs-page); }
.pricing-top .price-head .lede { margin-bottom: var(--s3); max-width: 62ch; }

/* Which assistants each plan asks, and how many passes each one gets. It
   is built from the plan's roster, so every number in it is computed, but
   it is a SENTENCE and not a figure. A line being true is not what decides
   its face; being a figure is. */
.pricing-top .assistants {
  margin: 0 0 var(--s2);
  font-size: var(--fs-meta);
  color: var(--ink-2);
  max-width: 70ch;
}
.pricing-top .assistants:last-child { margin-bottom: 0; }

/* TWO PLAN COLUMNS, HAIRLINE CARDS, NOTHING ORNAMENTAL. They end level by
   construction: everything above the button is one name, one amount and
   one VAT sentence on both cards, so the two buttons share a line at every
   width whatever a language does to a row below them. */
.pricing-top .plans {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--gap);
  margin: 0 0 var(--s6);
}

/* THREE TRACKS FROM 1024, TWO BETWEEN, ONE ON A PHONE (changed by T6.6,
   design/css-requests-phase6r-s6.md). This rule was two tracks and nothing
   else, and T6.2 added the free check as a third card, so the third one
   wrapped onto a row of its own and stood alone with a hole beside it at
   1400 and 1920: the owner's layout law of 2026-08-07 broken by a grid
   rather than by a measure cap. The breakpoint moved from 760 to 600 at the
   same time, so the step from one column to two lands on the Public sheet's
   own phone edge and no width is left with a single card in a wide row. */
@media (min-width: 600px) {
  .pricing-top .plans { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 1024px) {
  .pricing-top .plans { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.pricing-top .plan {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  min-width: 0;
  padding: var(--s5);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.pricing-top .plan h2 {
  margin: 0 0 var(--s2);
  font-size: var(--fs-h3);
  font-weight: 600;
  letter-spacing: 0;
}

/* THE AMOUNT, IN THE MEASURED FACE. Money is measured, so it is Geist Mono
   with tabular figures at the head sentence size; "a month" beside it is
   prose, so it is Geist at reading size on the same baseline and a screen
   reader still hears one line. */
.pricing-top .plan .price {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--s2);
  margin: 0 0 var(--s1);
}
.pricing-top .plan .price .fig {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "zero" 1;
  font-size: var(--fs-count);
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.1;
  color: var(--ink);
}
.pricing-top .plan .price .per { font-size: var(--fs-body); font-weight: 500; color: var(--ink-2); }

/* The VAT sentence sits directly under the amount it belongs to, and its
   own figures are measured too. */
.pricing-top .plan .vat {
  margin: 0 0 var(--s4);
  font-size: var(--fs-meta);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.pricing-top .plan > .btn { align-self: stretch; }

/* One hairline, then the mini label, then the three rows. */
.pricing-top .plan-label {
  margin: var(--s4) 0 var(--s3);
  padding-top: var(--s4);
  border-top: 1px solid var(--line);
  border-bottom: 0;
  font-family: var(--font-mono);
  font-size: var(--fs-mini);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
}
.pricing-top .plan-rows { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s2); }
.pricing-top .plan-rows li {
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr);
  gap: var(--s2);
  align-items: start;
  margin: 0;
  color: var(--ink-2);
  font-size: var(--fs-meta);
}
.pricing-top .plan-rows li + li { border-top: 0; }
.pricing-top .plan-rows b { color: var(--ink); font-weight: 600; }

/* The one check mark this page draws. It is the accent, once per row, and
   it is not a button and not a badge: raspberry marks, it never presses. */
.pricing-top .plan-rows svg, .includes svg {
  width: 18px;
  height: 18px;
  flex: none;
  margin-top: 1px;
  color: var(--accent);
}

/* The comparison table between the cards and the shared facts: the site
   table, with the row heads in ink. It scrolls in its own box, never the
   page.

   THE CELLS ARE PROSE (V1 finding 5). Four of the six rows are sentences
   outright and the other two are counts wearing a qualifier. A cell here
   reads in the text face; the figures inside it are still computed and
   still true. */
.compare-scroll { margin: 0 0 var(--s4); }
.compare-scroll .table { min-width: 640px; }
.pricing-top .compare th[scope="row"] { color: var(--ink); font-weight: 600; white-space: normal; vertical-align: top; }
.pricing-top .compare thead th { color: var(--ink); font-size: var(--fs-meta); }
.pricing-top .compare td { font-size: var(--fs-meta); }

.plans-notes { display: grid; gap: var(--s2); max-width: 76ch; }
.plans-note { margin: 0; font-size: var(--fs-meta); color: var(--muted); }

/* What both plans share, six facts on the panel ground. Two columns from
   760 so the list does not run as one long capped strip beside a hole. */
.includes { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s3); }
.includes li {
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr);
  gap: var(--s2);
  align-items: start;
  margin: 0;
  color: var(--ink-2);
  font-size: var(--fs-body);
}

@media (min-width: 760px) {
  .includes { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s3) var(--s7); }
}

/* ------------------------------------------------------ /how-it-works */

/* THE THREE STEPS, EACH BESIDE THE OBJECT IT PRODUCES. The paragraph is
   capped at a reading measure and the worked object is what stands beside
   it, which is answer 1 of the wide screen law. Under 900 the object
   stacks under its copy and the page is one column. */
.how-steps .step-row { display: grid; gap: var(--s5); align-items: start; }
.how-steps .step-row + .step-row { margin-top: var(--s6); padding-top: var(--s6); border-top: 1px solid var(--line); }

@media (min-width: 900px) {
  .how-steps .step-row { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); gap: var(--s7); }
}

.how-steps .step-copy { min-width: 0; max-width: 62ch; }
.how-steps .step-copy p:not(.step-n) { color: var(--ink-2); }
.how-steps .step-n {
  margin: 0 0 var(--s2);
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "zero" 1;
  font-size: var(--fs-mini);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
}

.how-object { min-width: 0; }
.how-object > .eyebrow { color: var(--ink-2); }

/* Step one's object: the live prompt pack, three rows of it, numbered in
   the measured face. */
.qlist { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s2); }
.qrow {
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr);
  gap: var(--s2);
  align-items: baseline;
  margin: 0;
  font-size: var(--fs-body);
}
.qrow + .qrow { padding-top: var(--s2); border-top: 1px solid var(--line); }
.qn { font-family: var(--font-mono); font-size: var(--fs-meta); font-variant-numeric: tabular-nums; font-feature-settings: "zero" 1; color: var(--muted); }
.qfoot { margin: var(--s3) 0 0; }

/* Step two's object: one answer, word for word, with the name marked. The
   answer is verbatim, so it is set in the measured face. */
.obj-answer .pill { margin: 0 0 var(--s2); }
.obj-body {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--fs-body);
  line-height: 1.6;
  overflow-wrap: break-word;
}
.obj-answer .meta { margin: var(--s3) 0 0; }

/* Step three's object: the count as a sentence in measured figures, with
   the usual range instrument under it. */
.bigcount {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--s2);
  margin: 0;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "zero" 1;
  font-size: var(--fs-count-big);
  font-weight: 700;
  line-height: 1;
}
.bigcount .of {
  font-family: var(--font);
  font-variant-numeric: normal;
  font-size: var(--fs-body);
  font-weight: 500;
  color: var(--ink-2);
}

/* SHARED with the panel's sample page: the sentence that reads the
   instrument out in words, under the scale it belongs to. */
.ruler-key { margin: var(--s3) 0 0; font-size: var(--fs-meta); color: var(--ink-2); }

/* The designed wait, storyboarded: three still frames of the receipt's own
   progress block, at frame scale. Three across from 900, one column under
   it, and each frame is the site card. */
.storyboard { list-style: none; margin: 0 0 var(--s4); padding: 0; display: grid; gap: var(--gap); }
.storyboard > li { margin: 0; min-width: 0; }
.storyboard .progress { margin: 0; }
.storyboard .tally li:last-child { border-bottom: 0; padding-bottom: 0; }

@media (min-width: 900px) {
  .storyboard { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* Who is asked, and how many times: the copy beside the roster table, so
   the capped paragraph has real content next to it. */
.roster-grid { display: grid; gap: var(--s5); align-items: start; }

@media (min-width: 1000px) {
  .roster-grid { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--s7); }
}

.roster-grid > div { min-width: 0; }
.roster-grid .lede { font-size: var(--fs-body); color: var(--ink); font-weight: 500; max-width: 62ch; }
.roster-grid p:not(.lede) { color: var(--ink-2); max-width: 62ch; }
.roster-scroll { overflow-x: auto; }
.roster-scroll .roster-table { min-width: 520px; }
.roster-table caption { text-align: left; font-size: var(--fs-meta); color: var(--muted); padding-bottom: var(--s2); }
.roster-table td.num, .roster-table th.num { text-align: right; }
.roster-table td.none { color: var(--muted); font-family: var(--font); font-variant-numeric: normal; }
.roster-table tfoot td { border-top: 2px solid var(--ink); border-bottom: 0; font-weight: 600; color: var(--ink); }
.roster-table tr.joins td:first-child { box-shadow: inset 2px 0 0 var(--accent); padding-left: var(--s2); }

/* A table that stacks into label and value rows rather than clipping, at
   the width where its columns stop fitting. SHARED: any table that carries
   a data-th on every cell may take it. */
@media (max-width: 639px) {
  .table.stack, .table.stack thead, .table.stack tbody, .table.stack tfoot,
  .table.stack tr, .table.stack th, .table.stack td { display: block; }
  .table.stack thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0, 0, 0, 0); }
  .table.stack tr { padding: var(--s2) 0; border-bottom: 1px solid var(--line); }
  .table.stack td { border: 0; padding: var(--s1) 0; display: flex; justify-content: space-between; gap: var(--s4); text-align: left; }
  .table.stack td::before { content: attr(data-th); color: var(--muted); font-size: var(--fs-meta); }
  .table.stack td:first-child::before { content: none; }
  .table.stack td:first-child { color: var(--ink); font-weight: 600; }
  .table.stack tfoot td { border-top: 0; }
  .table.stack tfoot tr { border-top: 2px solid var(--ink); border-bottom: 0; }
  .roster-scroll .roster-table { min-width: 0; }
}

/* Every Monday: the cadence in words beside the week's ledger card. */
.how-weekly .weekly-grid { display: grid; gap: var(--s5); align-items: start; }
.how-weekly .weekly-grid > div, .how-weekly .weekly-grid > aside { min-width: 0; }
.how-weekly .weekly-grid p { color: var(--ink-2); max-width: 62ch; }

@media (min-width: 900px) {
  .how-weekly .weekly-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 420px); gap: var(--s7); }
}

.how-weekly .card h3 { margin-bottom: var(--s3); }
.how-weekly .card .tally li:last-child { border-bottom: 0; }

/* What a day of this is, and what it is not: two columns of equal weight,
   so neither leaves a void under a short one. SHARED with /admin/costs,
   which splits the same way. */
.split { display: grid; gap: var(--s5); align-items: start; }
.split > * { min-width: 0; }
.split p { color: var(--ink-2); max-width: 62ch; }

@media (min-width: 768px) {
  .split { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s7); }
}

/* What we never do: four facts, each one a standing law of this product. */
.never { display: grid; gap: var(--s5); }
.never .fact { min-width: 0; }
.never .fact h3 { margin-bottom: var(--s2); }
.never .fact p { margin: 0; color: var(--ink-2); }
.never .fact a { text-decoration: underline; }

@media (min-width: 768px) {
  .never { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s5) var(--s7); }
}

/* ------------------------------------------------------ notice pages */

/* A notice page's ground: /claim, the queue notice and the daily cap page
   all put one card in the middle of the panel ground. SHARED with the
   panel's subscribe notice, which is the same object. */
.notice { padding: var(--section) 0; }

/* What a claim card hangs under its form: what claiming gives you, and
   what it does not, under a hairline rather than beside the fields. */
.notice-card .after { margin-top: var(--s5); padding-top: var(--s4); border-top: 1px solid var(--line); }
.notice-card .after h2:first-child { margin-top: 0; }
.notice-card .after ul { margin: 0 0 var(--s4); color: var(--ink-2); }
.notice-card .after ul:last-child { margin-bottom: 0; }

/* A form's action block: the button, whatever quiet button stands beside
   it, and the fine print under both. SHARED with the account forms. */
.submit { display: grid; justify-items: stretch; gap: var(--s3); }
.submit .fine { margin: var(--s1) 0 0; }
.submit .fine a { text-decoration: underline; }

/* --------------------------------------------------- the error pages */

/* THE NUMBER IS THE PAGE'S IDENTITY (owner ruling 2026-08-31,
   design/rules/error-pages.md, which this skin does not overturn). One
   full moment on the panel ground, copy left and the number right from
   960, the number first on a phone because it is the instant identity.

   THE NUMBER NEVER TAKES A SENTENCE'S PLACE. It is aria-hidden, and the
   code is real text twice: in the title and in the line under it. */
.err-stage {
  width: 100%;
  max-width: var(--container);
  margin: 0 auto;
  padding: var(--s7) max(var(--gutter), env(safe-area-inset-right)) var(--s8) max(var(--gutter), env(safe-area-inset-left));
  min-height: calc(100svh - var(--header));
  display: grid;
  gap: var(--s6);
  align-content: center;
}
.err-copy { min-width: 0; }
.err-copy h1 { font-size: var(--fs-page); }
.err-copy p { max-width: 62ch; }
.err-copy .lede { margin-bottom: var(--s4); }
.err-fig { order: -1; text-align: center; justify-self: center; min-width: 0; }

@media (min-width: 960px) {
  .err-stage { grid-template-columns: minmax(0, 7fr) minmax(0, 6fr); gap: var(--s8); align-items: center; }
  .err-copy { grid-column: 1; grid-row: 1; }
  .err-fig { grid-column: 2; grid-row: 1; order: 0; }
}

.err-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2) var(--s5); margin: var(--s5) 0 0; }

.err-code {
  --ex: 0.55;
  --ey: 0.85;
  display: inline-flex;
  font-size: var(--code-fs, clamp(112px, 26vw, 190px));
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.045em;
  color: var(--ink);
  padding: 0.07em 0.1em 0.17em;
  user-select: none;
  -webkit-user-select: none;
  filter: drop-shadow(calc(var(--ex) * 0.03em) 0.035em 0.05em rgba(var(--shadow-ink), 0.12));
  text-shadow:
    calc(var(--ex) * 0.0084em) calc(var(--ey) * 0.0084em) #c6d0da,
    calc(var(--ex) * 0.0168em) calc(var(--ey) * 0.0168em) #c6d0da,
    calc(var(--ex) * 0.0252em) calc(var(--ey) * 0.0252em) #cfd8e1,
    calc(var(--ex) * 0.0336em) calc(var(--ey) * 0.0336em) #cfd8e1,
    calc(var(--ex) * 0.0420em) calc(var(--ey) * 0.0420em) #cfd8e1,
    calc(var(--ex) * 0.0504em) calc(var(--ey) * 0.0504em) #cfd8e1,
    calc(var(--ex) * 0.0588em) calc(var(--ey) * 0.0588em) #cfd8e1,
    calc(var(--ex) * 0.0672em) calc(var(--ey) * 0.0672em) #cfd8e1,
    calc(var(--ex) * 0.0756em) calc(var(--ey) * 0.0756em) #cfd8e1,
    calc(var(--ex) * 0.0840em) calc(var(--ey) * 0.0840em) #cfd8e1,
    calc(var(--ex) * 0.0924em) calc(var(--ey) * 0.0924em) #dbe2ea,
    calc(var(--ex) * 0.1008em) calc(var(--ey) * 0.1008em) #dbe2ea,
    calc(var(--ex) * 0.1092em) calc(var(--ey) * 0.1092em) #dbe2ea,
    calc(var(--ex) * 0.1176em) calc(var(--ey) * 0.1176em) #dbe2ea,
    calc(var(--ex) * 0.1260em) calc(var(--ey) * 0.1260em) #dbe2ea,
    calc(var(--ex) * 0.1344em) calc(var(--ey) * 0.1344em) #dbe2ea;
}

@media (min-width: 960px) { .err-code { --code-fs: clamp(150px, 17vw, 250px); } }

.err-code span { display: inline-block; transform: translateY(var(--dy, 0)) rotate(var(--dr, 0deg)); }

/* A left leaning side must not paint over the digit before it. */
.err-code.rev span { position: relative; }
.err-code.rev span:nth-child(1) { z-index: 3; }
.err-code.rev span:nth-child(2) { z-index: 2; }
.err-code.rev span:nth-child(3) { z-index: 1; }

/* The line under it: the protocol status, verbatim. */
.err-tag {
  margin: var(--s3) 0 0;
  font-family: var(--font-mono);
  font-size: var(--fs-mini);
  font-weight: 500;
  color: var(--muted);
  letter-spacing: 0.04em;
}

/* ------------------------------------------- the mail preference page */

.unsub { display: grid; gap: var(--s5); }
.unsub-text { max-width: 62ch; }
.unsub-text .eyebrow { text-transform: none; letter-spacing: 0; color: var(--muted); }
.unsub-text h2 { margin-bottom: var(--s2); }
.unsub-text p { margin: 0; color: var(--ink-2); }
.unsub form + .meta { margin: var(--s3) 0 var(--s5); }

/* A row of mail switches. SHARED with the account's own notification page,
   which is the same list of the same rows: label, how often, control. */
.toggle-list { list-style: none; margin: 0 0 var(--s5); padding: 0; border-top: 1px solid var(--line); }
.toggle-list > li { margin: 0; border-bottom: 1px solid var(--line); }
.toggle-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--s1) var(--s4);
  padding: var(--s3) 0;
}
.toggle-row label { grid-column: 1; font-weight: 500; cursor: pointer; }
.toggle-row .cadence { grid-column: 1; grid-row: 2; font-size: var(--fs-meta); color: var(--muted); }
/* The control draws at 20 tall inside a 34px row, which is the height
   every other control on the page stands. */
.toggle-row .ctl { grid-column: 2; grid-row: 1 / span 2; display: flex; align-items: center; min-height: var(--control); }

/* The control itself: a native checkbox with role="switch", drawn as a
   track with a knob. Ink when it is on, because the accent is for marks
   and links and never for a control. */
.switch {
  appearance: none;
  -webkit-appearance: none;
  position: relative;
  flex: none;
  width: 36px;
  height: 20px;
  margin: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--band);
  cursor: pointer;
  transition: background-color var(--dur-1) var(--ease), border-color var(--dur-1) var(--ease);
}
.switch::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--surface);
  box-shadow: var(--shadow-1);
  transition: transform var(--dur-2) var(--ease);
}
.switch:checked { background: var(--ink); border-color: var(--ink); }
.switch:checked::after { transform: translateX(16px); }
.switch:disabled { cursor: not-allowed; opacity: 0.55; }

/* -------------------------------------- a check row inside a field (fix) */

/* THE CHECKBOX ROW HAS TO BEAT THE FIELD LABEL (found by the app lane,
   2026-09-03, and it survives the skin change unchanged).

   The baseline draws a field's label with `.field label { display: block }`,
   which is (0,1,1), and the check row with `.checkline`, which is (0,1,0).
   So the moment a checkbox or a radio row landed inside a .field, and the
   API keys card's ability radios are exactly that (design/rules/
   api-keys-ui.md, .field .radioline .checkline), the row lost its grid and
   rendered as a block: the control on one line and its sentence under it,
   with the label's meta size and 500 weight on top.

   The row is named with its element here, so it is (0,2,1) inside a field
   and (0,1,1) on its own, and this section is read after the baseline, so
   it wins in both places. Every declaration the field label would
   otherwise impose is restated, not only the display. SHARED: this reaches
   the panel pages too, which is the point, since site.css is read there as
   well. */
.field label.checkline, label.checkline {
  display: grid;
  grid-template-columns: 20px minmax(0, 1fr);
  gap: 10px;
  align-items: start;
  margin: 0;
  font-size: var(--fs-body);
  font-weight: 400;
  cursor: pointer;
}

/* And the group they sit in keeps its own stack inside a field. */
.field .radioline { display: grid; gap: var(--s3); }

/* THE DOORMAT LEAVES NO STRIPE UNDER A PAGE THAT ENDS ON THE PANEL GROUND.
   The footer holds var(--s8) of paper above itself, which is air under a
   white page and a band of a third colour under an error page, whose stage
   is on the panel ground already: panel, paper, panel, in three stripes. A
   browser without :has keeps the gap, which is the shipped behaviour and
   not a defect anywhere else. */
main:has(> section.band:last-child) + .foot { margin-top: 0; }

/* =====================================================================
   ==== P6R-4 THE DOORS ====

   The old P5O-T4 region, folded into this baseline and redrawn on the 6R
   scale. It owns the six auth views at /login, /register,
   /forgot-password, /reset-password, /verify-email and the two factor
   challenge. The design source is design/mockups/phase6r/site-login.html,
   and every value below is that file's: the 400px column, the 12px radius
   on the card, the 26 by 24 padding, the 24px heading, the 13px lede, the
   8px stack in the method block, the hairline that carries "or with your
   address" in its middle.

   THE NAMES ARE auth-*, AND THAT IS DELIBERATE. The shipped door markup
   was .door-stage, .door-col, .door-main, .door-greet and .door-note.
   Every admin page loads site.css AND admin.css, and admin.css owns .door
   as the staff door's body class and .door-col as its column, so styling
   .door-col here would have painted the staff door from a sheet that is
   not its own. The site lane already renamed the landing's closing door to
   .site-door for the same reason.

   ONE GRAMMAR ON ALL SIX DOORS. The stage is the panel ground, the column
   is measured, the card holds the one thing to do, and anything the page
   owes the reader afterwards is a postscript UNDER the card rather than a
   second half of it. On the sign in door that postscript is the throttle
   sentence, which the mockup also stands outside the card.
   ===================================================================== */

/* The stage and the measured column. The mockup centres its door in the
   viewport because it has no chrome; this stage sits between the slim bar
   and the doormat, so it takes the same air a notice page takes and the
   column carries the measure. */
.auth-stage { padding: var(--section) 0; }
.auth-col { width: 100%; max-width: 400px; margin: 0 auto; }

/* The door itself. Border AND shadow, which is what the mockup draws and
   what .notice-card draws: a door is the one object on its page, so it
   gets an edge as well as the one lift this skin allows. */
.auth-door {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-l);
  box-shadow: var(--shadow-2);
  padding: 26px 24px;
}

@media (max-width: 400px) {
  .auth-door { padding: var(--s5) var(--s4); }
}

.auth-door > :last-child { margin-bottom: 0; }

/* THE HEADING IS A FIXED 24, the ruling's modal title, and not the fluid
   page size. The card is 400 wide at 390 and at 1920 alike, so a heading
   that grew with the viewport would grow inside a box that never does. */
.auth-door h1 {
  font-size: 24px;
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.2;
  margin: 0 0 var(--s1);
}
.auth-door .eyebrow { margin-bottom: var(--s2); }
.auth-door .lede {
  font-size: var(--fs-meta);
  color: var(--ink-2);
  max-width: none;
  margin: 0 0 var(--s5);
}
.auth-door .flash { margin: 0 0 var(--s5); }
.auth-door .hint { color: var(--muted); }

/* WHY THIS PAGE OPENED: the sign in door found no account on the address
   and sent the reader here. A band tint, no motion, no icon, and it is the
   first thing in the card, above the eyebrow. */
.auth-greet {
  background: var(--band);
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  padding: var(--s3) var(--s4);
  margin: 0 0 var(--s5);
  color: var(--ink-2);
  font-size: var(--fs-meta);
}
.auth-greet p { margin: 0; }

/* THE TWO METHODS ABOVE THE HAIRLINE, EQUAL AND QUIET. Both are full
   width, both are card on hairline, and the one filled button on the card
   is the submit: no method is drawn as the right one. With no Google
   client and no WebAuthn the block is empty, draws nothing, and the card
   starts at the fields. */
.auth-door .sso { display: grid; gap: var(--s2); margin: 0; }
.auth-door .sso .btn { width: 100%; }

/* The hairline with the words in its middle. It is printed only when there
   is a button above it to divide from (the view branches, and the passkey
   half is unhidden by public/js/auth.js). */
.auth-door .or {
  display: flex;
  align-items: center;
  gap: var(--s3);
  margin: 18px 0 14px;
  color: var(--ink-2);
  font-size: var(--fs-meta);
}
.auth-door .or::before, .auth-door .or::after {
  content: "";
  flex: 1 1 auto;
  height: 1px;
  background: var(--line);
}
.auth-door .or span { flex: none; }

/* The fields, the label line with the forgot link on it and the check row
   are all the baseline's; the door only says how the stack breathes and
   how wide the action is. */
.auth-door .form { gap: 14px; }
.auth-door .submit { margin: var(--s1) 0 0; }

/* THE POSTSCRIPT, UNDER THE CARD AND IN THE SAME COLUMN. The mockup
   centres its one sentence; four of the six doors hang a heading and a
   list here, and a centred heading over a left aligned list is two edges
   in one column, so the block keeps the card's left edge at every width. */
.auth-note {
  margin: var(--s4) 0 0;
  color: var(--ink-2);
  font-size: var(--fs-meta);
}
.auth-note h2 {
  font-size: var(--fs-h3);
  font-weight: 600;
  color: var(--ink);
  margin: 0 0 var(--s2);
}
.auth-note p, .auth-note ul { margin: 0 0 var(--s3); }
.auth-note ul { padding-left: 1.1em; }
.auth-note li { margin: 0 0 var(--s2); }
.auth-note > :last-child { margin-bottom: 0; }
.auth-note a { text-decoration: underline; }

/* ONE ENTRANCE, FILL BOTH, AND NOTHING ELSE MOVES. The baseline's reduced
   motion block switches it off; this gate keeps it off a browser that
   never starts it. */
@media (prefers-reduced-motion: no-preference) {
  .auth-door { animation: door-in var(--dur-2) var(--ease) both; }

  @keyframes door-in {
    from { opacity: 0; transform: translateY(4px); }
    to { opacity: 1; transform: none; }
  }
}

/* =====================================================================
   ==== P6R-S1 ====

   STAGE 1 ON THE PUBLIC SIDE (T1.8): the zero row card on the results
   page, and the claim card's fork.

   IT IS APPENDED AS ITS OWN REGION and changes nothing in the four
   regions above. Only two objects land here, because only two of stage
   1's screens are public: /check/{token}, which is x-site.layout, and
   /claim/{token}, which is the same shell. Everything else stage 1 built
   is inside the app shell and lives in design/app.css under the same
   banner.

   THE CHOICE CARDS ARE THE SAME RULES IN BOTH SHEETS, ON PURPOSE.
   x-app.choice-cards is one component used on both sides of the product,
   so its grammar is written once in each sheet at the same values rather
   than being reached for across a shell it does not belong to.
   ===================================================================== */

/* ---------------------------------------------------------------------
   S1.1 THE ZERO ROW (x-receipt.zero-row), above the answers table on the
   results page with the claim band directly under it.
   --------------------------------------------------------------------- */

/* THE CARD IS THE HOOK AND THE THING THE HARNESS MEASURES. Its rows carry
   their own hairlines, so the card body gives up the gap it puts between
   grid children: a 12px gap plus a 9px row padding plus a rule is three
   separators for one list. */
.zero-card .card-body { gap: 0; }

/* ONE ROW PER ASSISTANT, IN THE RUN'S ROSTER ORDER. It is a list of names
   and counts and nothing in it is a place in a list: no ordinal column,
   no arrow, no league table. */
.zero {
  display: grid;
  grid-template-columns: 180px minmax(0, 1fr);
  gap: var(--s2) var(--s4);
  align-items: baseline;
  padding: 9px 0;
  border-top: 1px solid var(--line);
  font-size: var(--fs-body);
}

.zero:first-child { border-top: 0; padding-top: 0; }
.zero .who { font-weight: 500; }

/* The answer count under the assistant's name. The size is stated: the
   browser's own `small` is 0.833em, which is 11.7px on 14px body type and
   under the 12px floor. */
.zero .who small {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--fs-mini);
  font-weight: 400;
  line-height: 1.4;
  color: var(--ink-2);
}

.zero ul { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px var(--s3); }
.zero li { white-space: nowrap; }
.zero li .mono { font-size: var(--fs-meta); color: var(--ink-2); }

/* THE READER IS LAST ON EVERY ROW and reads as theirs, never as one of
   the businesses beside them. */
.zero li.you { font-weight: 500; }

/* RASPBERRY MEANS THE RUN NAMED THEM, and it is spent here and nowhere
   else in this card. An unnamed reader stays in the row's own ink,
   because a zero is not an alarm. */
.zero li.you.named,
.zero li.you.named .mono { color: var(--accent); }

/* The fold door sits on the names' baseline rather than starting a line
   of its own, and it is a native details, so it opens with no script. */
.zero li.zero-more { white-space: normal; }
.zero li.zero-more > details > summary { display: inline; list-style: none; cursor: pointer; font-size: var(--fs-meta); color: var(--accent); }
.zero li.zero-more > details > summary::-webkit-details-marker { display: none; }
.zero li.zero-more > details[open] > ul { margin-top: 6px; }

/* THE TOTAL ROW: the sentence the card exists for, under a 2px INK rule
   and not a hairline. The figure keeps a node of its own, because the
   poll rewrites that node while a run is still filling. */
.zero-you {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--s3);
  margin-top: 10px;
  padding-top: var(--s3);
  border-top: 2px solid var(--ink);
  font-weight: 600;
}

.zero-you .zero-line { min-width: 0; }
.zero-you a { font-size: var(--fs-meta); font-weight: 400; margin-left: 10px; }

/* ---------------------------------------------------------------------
   S1.2 x-app.choice-cards on the claim card.
   --------------------------------------------------------------------- */

/* The fieldset is the question, and the legend reads as the claim card's
   own "Create your account" does. `.form fieldset` sets a 16px grid gap
   for a stack of fields; a group of cards wants 8, and this selector ties
   it on specificity and wins on order. */
fieldset.choice-set { display: grid; gap: var(--s2); border: 0; margin: 0; padding: 0; min-width: 0; }
.choice-set > legend { display: block; padding: 0; margin: 0 0 var(--s2); font-size: var(--fs-h3); font-weight: 600; line-height: 1.35; }
.choices { display: grid; gap: 10px; }
.choices.two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.choices.three { grid-template-columns: repeat(3, minmax(0, 1fr)); }

.choice {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: var(--s3) 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  cursor: pointer;
  transition: border-color var(--dur-1) var(--ease), box-shadow var(--dur-1) var(--ease);
}

/* The radio is DRAWN AND NEVER HIDDEN: it stays a real radio, so the
   arrow keys, the focus ring and the required state are the browser's. */
.choice input { width: 16px; height: 16px; margin-top: 2px; flex: none; accent-color: var(--ink); }

/* THE TICKED CARD IS A WEIGHT CHANGE, NOT A COLOUR WASH. */
.choice:has(input:checked) { border-color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink); }
.choice .t { display: block; font-size: var(--fs-body); font-weight: 500; line-height: 1.4; }
.choice .m { display: block; font-size: var(--fs-meta); line-height: 1.5; color: var(--muted); margin-top: 2px; }
.choice-set > .error-text { margin: 0; color: var(--bad); font-size: var(--fs-meta); font-weight: 500; }

/* ---------------------------------------------------------------------
   S1.3 THE PHONE, 390.
   --------------------------------------------------------------------- */
@media (max-width: 640px) {
  /* One column, and the assistant sits over its names: 180px for a name
     and the rest for a wrapping list does not fit 390 without clipping. */
  .zero { grid-template-columns: minmax(0, 1fr); gap: var(--s1); }

  /* Two cards side by side at 390 put four words on four lines. */
  .choices.two,
  .choices.three { grid-template-columns: minmax(0, 1fr); }
}

/* =====================================================================
   ==== P6R-S3 ====

   STAGE 3, THE PROOF LINK (T3.7). /p/{token} and the one dead page it
   answers with when the link is revoked, expired, unknown or closed.
   Both views render inside x-site.layout, so they are drawn here and
   not in the workspace sheet.

   IT IS APPENDED AS ITS OWN REGION, not edited into the four T0.6
   regions or into P6R-S1 above.

   THE PAGE IS A DOCUMENT AND NOT A DASHBOARD. The reader is not our
   customer: they were sent this address by somebody who is. So it is
   one 880px column on the paper ground with symmetrical margins at
   1920, and the only things on it that can be pressed are the two
   controls, which are plain GET links inside a segmented group.

   TWO NAMES ARE TAKEN IN BOTH SHEETS ON PURPOSE, .excerpts and .blk-row.
   The same two objects are drawn on the month page inside the workspace
   and here inside the public shell; no page loads both sheets for them,
   and the S1 region already recorded .qrow as the first of these. One
   object used on both sides of the product is drawn once in each sheet
   rather than reaching across a shell it does not belong to.

   THE DESIGN SOURCE is design/mockups/phase6r/s3/parts/s3.css lines 93
   to 116 and design/css-requests-phase6r-s3.md, section T3.2.
   ===================================================================== */

/* THE DOCUMENT. It is the whole page, so the leftover at 1920 is
   symmetrical margin and never a hole beside a capped column. */
.proof { max-width: 880px; margin: 0 auto; padding: 40px var(--s5) var(--s8); }

/* EVERY FIGURE IN THIS DOCUMENT IS A MEASURED THING. The mockup's `.n`
   is the shipped `.mono` everywhere else in the product; this page was
   written against the mockup's spelling, so the scoped rule is what
   makes its counts read as counts. Word spacing closes the same way
   .mono closes it, because Geist Mono's space is wide inside a
   sentence. */
.proof .n {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "zero" 1;
  word-spacing: -0.28em;
}

/* THE HEAD: who it was prepared for, the business as the title, what
   the page is, then the count sentence the whole document exists for
   with its n, and the usual range under it. */
.proof-brand { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin: 0 0 var(--s4); }
.proof-brand .client { display: flex; align-items: center; gap: 10px; font-size: var(--fs-body); font-weight: 500; }
.proof-brand .meta { margin: 0; }

/* The 28px initials tile, and it stays the initials until a business
   uploads a logo on the brand card. */
.proof-brand .logo-mark {
  width: 28px;
  height: 28px;
  flex: none;
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: var(--radius-xs);
  background: var(--band);
  font-family: var(--font-mono);
  font-size: var(--fs-mini);
  font-weight: 600;
  line-height: 1;
  color: var(--ink-2);
}

/* With a logo stored the tile gives way to the file itself, at the tile's
   own height so the head keeps one baseline whichever it is. */
.proof-brand .client-logo { height: 28px; width: auto; max-width: 200px; flex: none; }

.proof .p-head h1 { font-size: 28px; line-height: 1.2; letter-spacing: -0.01em; margin: 0; }
.proof .p-head .what { margin: 6px 0 0; font-size: var(--fs-lede); line-height: 1.5; color: var(--ink-2); }
.proof .count { margin: 18px 0 0; font-size: 18px; line-height: 1.4; font-weight: 500; }
.proof .count .n { font-weight: 600; }

/* THE RANGE IS THE ONE HONEST CLAIM ABOUT A COUNT, so its two bounds
   stand out of the sentence in the primary ink. */
.proof .range { margin: var(--s1) 0 0; font-size: var(--fs-body); line-height: 1.5; color: var(--ink-2); }
.proof .range .n { color: var(--ink); }

/* THE TWO CONTROLS, BETWEEN HAIRLINES. Both are groups of plain GET
   links: no form, no script, nothing to post, and a reader can middle
   click a month or read the page with scripts switched off. */
.proof .controls {
  display: flex;
  gap: var(--s4) var(--s5);
  align-items: center;
  flex-wrap: wrap;
  margin: var(--gap) 0 0;
  padding: 14px 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

.proof .ctl { display: flex; gap: var(--s2); align-items: center; flex-wrap: wrap; }
.proof .controls .lbl { font-size: var(--fs-meta); color: var(--ink-2); margin-right: 2px; }

/* ONE SECTION, ONE DESCRIPTION LINE. The line under a heading says what
   the section is, at the description size. */
.proof .p-sec { margin: 28px 0 0; }
.proof .p-sec h2 { font-size: var(--fs-h3); font-weight: 600; letter-spacing: 0; line-height: 1.35; margin: 0; }
.proof .p-sec .desc { margin: 2px 0 var(--s3); font-size: var(--fs-meta); line-height: 1.5; color: var(--ink-2); }

/* THE TWO VERBATIM ANSWERS, side by side at 880 and stacked under 640.
   The workspace sheet draws the same object for the month page; this is
   the public shell's copy of it. */
.excerpts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--gap); align-items: start; }
.excerpts .answer { margin: 0; }

/* ONE ANSWER TAKES THE WHOLE ROW. A month with a single sampled Monday has
   one excerpt to show, and half a row of nothing beside it is the hole the
   owner's measure law names (2026-08-07). The column earns its width or the
   width goes away. */
.excerpts:has(> :only-child) { grid-template-columns: minmax(0, 1fr); }

.excerpts .a-head {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--s2);
  margin: 0 0 var(--s2);
  font-size: var(--fs-meta);
  line-height: 1.5;
  color: var(--ink-2);
}

/* The vendor's own words: the measured face, NOT tabular, on the paper
   ground inside a hairline box. It is a sentence, and tabular
   punctuation inside prose is the tnum lesson. */
.excerpts .a-body {
  margin: 0;
  padding: var(--s3) 14px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  font-family: var(--font-mono);
  font-size: var(--fs-body);
  line-height: 1.6;
  overflow-wrap: break-word;
}

.excerpts .a-foot { margin: var(--s2) 0 0; font-size: var(--fs-mini); line-height: 1.5; color: var(--ink-2); }

/* ONE READING, ONE ROW: the finding with its date right aligned and the
   evidence under it. The state is .done and never .fixed, which the
   shipped sheet owns for the fixed fact drawn where an input would be
   (NOTES decision 5). */
.blk-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 2px 12px;
  align-items: baseline;
  padding: 10px 0;
  border-top: 1px solid var(--line);
  font-size: var(--fs-body);
}

.blk-row:first-child { border-top: 0; padding-top: 0; }
.blk-row .t { font-weight: 500; }
.blk-row .ev { grid-column: 1; font-size: var(--fs-meta); line-height: 1.5; color: var(--ink-2); }
.blk-row .when { font-family: var(--font-mono); font-size: var(--fs-meta); color: var(--ink-2); white-space: nowrap; }
.blk-row.done .t { color: var(--ink-2); font-weight: 400; }
.blk-row.done .when { color: var(--ok); }

/* THE PROVENANCE FOOT, WITH THE MARK. Who measured it, where the method
   is written down, what is on every proof page whatever the scope says,
   and which sections are here because the business allowed them. No
   plan and no brand removes this line or the link in it. */
.prov-line {
  display: flex;
  align-items: center;
  gap: var(--s2);
  flex-wrap: wrap;
  margin: 36px 0 0;
  padding: var(--s4) 0 0;
  border-top: 1px solid var(--line);
  font-size: var(--fs-meta);
  line-height: 1.5;
  color: var(--ink-2);
}

.prov-line img { height: 16px; width: auto; flex: none; }
.prov-line strong { font-weight: 500; color: var(--ink); }
.prov-line span { min-width: 0; }

/* THE DEAD PAGE. One sentence, centred, and nothing else: this rule is
   the whole layout of it. There is no door on it on purpose, because a
   door would tell a stranger there is somebody to ask. */
.dead { max-width: 880px; margin: 0 auto; padding: var(--s9) var(--s5); text-align: center; }
.dead p { margin: 0; font-size: 18px; line-height: 1.4; font-weight: 500; }

/* ---------------------------------------------------------------------
   S3.1 THE PHONE, 390.
   --------------------------------------------------------------------- */
@media (max-width: 640px) {
  .proof { padding: var(--s5) var(--s4) var(--s7); }
  .proof .p-head h1 { font-size: 24px; }
  .proof .count { font-size: var(--fs-lede); }
  .excerpts { grid-template-columns: minmax(0, 1fr); }
  .blk-row { grid-template-columns: minmax(0, 1fr); }
}

/* =====================================================================
   ==== P6R-S2A THE PUBLIC SHEET ====

   T2.12. The public site re-skinned onto the Public reference sheet,
   design/mockups/phase6r/s7/PUBLIC-SHEET.md, which is the measured source
   and is binding; the acceptance mockups are s7/site-landing-v2.html and
   s7/site-pricing-v2.html and the CSS they were built from is
   s7/parts/public.css.

   WHY THERE ARE TWO SHEETS NOW. The 6R skin put one dashboard-scale Geist
   system on the public site: 14px body, a 40 to 56 clamp on the one
   display head, 13px button labels, 34 to 40px controls. The owner's
   review of 2026-09-05 measured the reference's own public templates and
   found the difference material: Satoshi at 16/24, a 72/92 hero, 18px
   controls with 12px corners, and a heading scale that differs per
   template rather than one generic small title. The ruling is two
   reference sheets, Public and App, each measured, sharing our colours
   and nothing else. design/rules/phase6r-skin.md carries both.

   IT IS APPENDED AS ITS OWN REGION and edits none of the four regions
   above, exactly as P6R-S1 and P6R-S3 are appended. Three rules in the
   baseline DID have to change, and each says so where it stands: the
   input boundary (--edge, not the hairline), the placeholder (4.5:1) and
   the disabled field. Everything else on this sheet is an override under
   body.pub, so the workspace and the operator panel, which read the same
   file, are untouched.

   THE SCOPE IS body.pub, WHICH IS EVERY PUBLIC PAGE AND EVERY AUTH DOOR.
   x-site.layout puts the class on, so the landing, the marketing pages,
   the legal pages, the notice pages, the proof link and the six doors all
   inherit it in one move. It is NOT put on /sample, which is a workspace
   view rendered on the public shell: that page is the App sheet's, and a
   16px public body inside it would be the two sheets reaching into each
   other. The frame drawn on the landing is reset back to the App sheet
   here for the same reason.

   THE NAMES ARE SITE SCOPED (the six-collision lesson of 5g). Every new
   object carries a pub- prefix, because .closing, .receipt, .rules and
   .feat all name something else in this file or in the two panel sheets.
   ===================================================================== */

/* ------------------------------------------------ the public document */

/* Body 16/24 Satoshi (PUBLIC-SHEET.md section 2, home.body[0]). Figures
   inside a public sentence stay in Satoshi with tabular figures: "every
   digit in mono" was a PicksYou choice the review names as restrictive,
   and the reference sets its public numbers in its body face. The mono
   keeps the small caps labels, the money on /pricing and the app frame. */
body.pub {
  font-family: var(--font-pub);
  font-size: var(--fs-pub-body);
  line-height: 24px;
}

/* THE FACE, AND ONLY THE FACE, ON EVERY HEADING. Weight and tracking are
   set per role below: an h2 is a card title, a dialog title, a footer
   column head and a narrative heading all at once, and the first shot at
   1400 caught a blanket weight turning the footer's 12px mono labels into
   700 and dropping their tracking. */
body.pub h1, body.pub h2, body.pub h3 { font-family: var(--font-pub); }

body.pub p, body.pub li { text-wrap: pretty; }
body.pub .num, body.pub .fig { font-variant-numeric: tabular-nums; }

/* THE VERBATIM ANSWER IS SATOSHI ON EVERY SURFACE THAT DRAWS ONE. The App
   sheet's ruling (APP-SHEET.md section 1) is about the prose, not about
   which stylesheet happens to hold it: the free receipt, the proof link
   page and the frame on the landing are all drawn by this file, so the
   rule is restated here. Three or four lines of ordinary English set in a
   monospace read as a log entry rather than as what somebody was told
   about this business, which is the review's own finding. Nothing else
   moves: the prose is still not tabular, still not edited, and the one tag
   inside it is still <mark>. */
.answer .excerpt, .answer .rest p, .excerpts .a-body, .fr-answer .a-body {
  font-family: var(--font-pub);
  line-height: 1.55;
}

/* THE APP FRAME KEEPS THE APP SHEET (the sheets never reach into each
   other). The landing draws a rendering of the workspace at its own
   density; a 16px public body inside it would be a picture of a product
   nobody uses. Everything inside .workframe reads --font at 14/1.55, and
   the frame's own rules above set the rest. */
body.pub .workframe {
  font-family: var(--font);
  font-size: var(--fs-body);
  line-height: var(--lh);
}
body.pub .workframe :is(h1, h2, h3) { font-family: var(--font); }

/* -------------------------------------------------- the public scale */

/* The heading scale per template (PUBLIC-SHEET.md section 2). One 72px
   block per page: the hero, or the dark closing block. Everything else
   steps to the size its template measured.

   THE DEFAULT h1 IS THE COMPACT HEAD, 36/40, because a page that has not
   claimed a template is a notice, an error or a short document, and the
   review's complaint was a generic SMALL head, not a generic one. */
body.pub h1 { font-size: var(--fs-pub-compact); line-height: 40px; font-weight: 700; letter-spacing: normal; }

/* AND THE BLANKET STOPS AT h1. h2 and h3 name a card title, a dialog
   title, a footer column head and a section head as well as a narrative
   heading, and a blanket 36px would have set every one of them; the first
   shot at 1400 caught it on the footer. The narrative heading is written
   on the three objects that carry one, and every other h2 and h3 on a
   public page keeps the baseline's own rule. A card title inside a public
   page keeps the card's rule for the same reason. */
body.pub .pub-intro h2,
body.pub .pub-duo .copy h2,
body.pub .pub-faq-grid .lead h2 {
  font-size: var(--fs-pub-h2);
  line-height: 45px;
  font-weight: 700;
  letter-spacing: normal;
}

body.pub .card-title h1 { font-size: var(--fs-h3); line-height: 1.35; font-weight: 600; }

/* The hero, and nothing else on the site, takes 72/92. */
body.pub .hero-v3 h1 { font-size: var(--fs-pub-hero); line-height: 92px; }

/* The article template: 48/60 at -1.2px tracking (tpl[5]). Every legal
   page, /about, /contact, /faq and the changelog render in .article. */
body.pub .article h1 { font-size: var(--fs-pub-article); line-height: 60px; letter-spacing: -1.2px; }
body.pub .article h2 { font-size: 24px; line-height: 32px; font-weight: 600; letter-spacing: normal; }
body.pub .article h3 { font-size: var(--fs-pub-h3); line-height: 28px; font-weight: 600; }

/* The docs template, 28/42 at 600 with 24/32 subheads (tpl[6]): the
   methodology page is a reference document and reads as one. It is the
   one .article page that steps DOWN from the article head, so its rule
   comes after the article's. */
body.pub .article.docs h1 { font-size: var(--fs-pub-docs); line-height: 42px; font-weight: 600; letter-spacing: normal; }

/* The legal template, 30/40 (tpl[7], whose own 30/24 the sheet rejects
   as a line height under its size), with 20/28 subheads. */
body.pub .article.legal h1 { font-size: var(--fs-pub-legal); line-height: 40px; letter-spacing: normal; }
body.pub .article.legal h2 { font-size: var(--fs-pub-h3); line-height: 28px; }

/* The index template, 60/75 at -1.5px (tpl[3]): a page that lists other
   pages. /learn is the one we have. */
body.pub .article.index h1 { font-size: var(--fs-pub-index); line-height: 75px; letter-spacing: -1.5px; }

/* The comparison and pricing head, 56/70 (tpl[2]). The calculator embed
   and the comparison table under it are T6.2 and are not touched here. */
body.pub .pricing-top .price-head h1 { font-size: var(--fs-pub-compare); line-height: 70px; }

/* The compact head, 36/40 (tpl[0]): the error pages, the notice cards and
   the proof link page, which is a short document a stranger was sent. */
body.pub .err-copy h1 { font-size: var(--fs-pub-compact); line-height: 40px; }
body.pub .notice-card h1 { font-size: var(--fs-pub-compact); line-height: 40px; font-weight: 700; }

/* The reading roles. The lede is 20/32 at 500, the intro under a section
   head 18/28, a blurb 14/22, meta 14/20; the 12px mono label is the floor
   and it does not move. */
body.pub .lede { font-size: var(--fs-pub-lede); line-height: 32px; font-weight: 500; }
body.pub .fine, body.pub .meta { font-size: var(--fs-pub-blurb); line-height: 20px; }
body.pub .section-sub { font-size: 18px; line-height: 28px; }
body.pub .pub-blurb { font-size: var(--fs-pub-blurb); line-height: 22px; color: var(--ink-2); }
body.pub .pub-meta { font-size: var(--fs-pub-blurb); line-height: 20px; color: var(--ink-2); }

/* ------------------------------------------ width, surfaces, rhythm */

/* 1280 wide, 32 in from 1024, 20 under (home.nav[0].maxWidth 1280 and
   tpl[3] content width 1216). The reading measure on a document page is
   unchanged: that cap is what makes a legal page readable. */
body.pub { --gutter: 20px; }
@media (min-width: 1024px) {
  body.pub { --gutter: 32px; }
}

/* 96 above and below a section from 1024, 64 at 768, 48 at 390. */
body.pub { --section: 96px; --hero: 96px; }
body.pub .section { padding: var(--section) 0; }
body.pub .section.tight { padding: var(--s7) 0; }

/* A section head centred at 720 with its intro under it, for the
   narrative sections the landing gained. The document pages keep the
   left set head they already have. */
body.pub .pub-intro { max-width: 720px; margin: 0 auto 40px; text-align: center; }
body.pub .pub-intro h2 { margin: 0; }
body.pub .pub-intro p { margin: 12px 0 0; font-size: 18px; line-height: 28px; color: var(--ink-2); }

/* -------------------------------------------------------- controls */

/* THE PUBLIC BUTTON (PUBLIC-SHEET.md section 3). 16/24 at 700 in 8 by 16,
   12px corners; the big one 18/27 in 16 by 32, which is the hero's and
   the closing block's. Filled is ink with a white label, quiet is the
   panel with an ink label and no border, ghost is the label alone.
   Raspberry is still never a button. */
body.pub .btn {
  min-height: 40px;
  padding: 8px var(--s4);
  border: 0;
  border-radius: var(--radius-pub);
  background: var(--band);
  color: var(--ink);
  font-family: var(--font-pub);
  font-size: var(--fs-pub-body);
  font-weight: 700;
  line-height: 24px;
  gap: var(--s2);
}

body.pub .btn.big {
  min-height: 59px;
  padding: var(--s4) var(--s6);
  font-size: var(--fs-pub-cta);
  line-height: 27px;
}

body.pub .btn.small { min-height: 40px; padding: 8px var(--s4); }

/* A filled button is the ink one. The site's own component emits .btn
   with no modifier for the filled kind and .outline or .quiet for the
   second action, so the filled rule is written on the bare class and the
   quiet one takes it back. */
body.pub .btn:not(.outline):not(.quiet):not(.ghost):not(.danger):not(.inverse) {
  background: var(--button);
  color: var(--button-ink);
}

body.pub .btn.outline, body.pub .btn.quiet {
  background: var(--band);
  border: 0;
  color: var(--ink);
}

body.pub .btn.ghost { background: transparent; color: var(--ink-2); font-weight: 500; }

/* The white primary on the dark closing block: a filled ink button
   disappears on ink, which is what the first shot at 1400 showed. It is
   taken out of the filled rule's :not() chain above rather than fought
   with specificity. */
body.pub .btn.inverse { background: var(--surface); color: var(--ink); }
body.pub .btn.inverse:focus-visible { outline-color: var(--surface); }

@media (hover: hover) and (pointer: fine) {
  body.pub .btn:not(.outline):not(.quiet):not(.ghost):not(.danger):not(.inverse):hover { background: var(--button-2); }
  body.pub .btn.outline:hover, body.pub .btn.quiet:hover { background: #e4eaf0; }
  body.pub .btn.ghost:hover { background: var(--band); color: var(--ink); }
  body.pub .btn.inverse:hover { background: var(--band); }
}

/* Disabled is the quiet button in secondary ink, never a half opacity
   white label on grey (the acceptance matrix, control states). */
body.pub .btn[disabled], body.pub .btn[aria-disabled="true"] {
  background: var(--band);
  color: var(--ink-2);
  opacity: 1;
  cursor: not-allowed;
}

/* Pending keeps the width and swaps the label; the shipped rule already
   does that and only the opacity moves, so a label stays readable. */
body.pub .btn.is-pending { opacity: 0.85; }

/* --------------------------------------------------------- the input */

/* 18/27 in 16 by 24, 12px corners, the --edge boundary the baseline now
   sets, hover one step darker, focus the 2px ink ring at offset 0 so the
   ring and the edge are one line (PUBLIC-SHEET.md section 4). */
body.pub .input, body.pub select.input, body.pub textarea.input,
body.pub .check-v3 .cell-input, body.pub .check-v3 .cell-select {
  min-height: 59px;
  padding: var(--s4) var(--s5);
  border-radius: var(--radius-pub);
  border-color: var(--edge);
  font-family: var(--font-pub);
  font-size: var(--fs-pub-input);
  line-height: 27px;
}

body.pub textarea.input { min-height: 140px; }

@media (hover: hover) and (pointer: fine) {
  body.pub .check-v3 .cell-input:hover,
  body.pub .check-v3 .cell-select:hover { border-color: var(--edge-hover); }
}

body.pub .input:focus, body.pub .check-v3 .cell-input:focus, body.pub .check-v3 .cell-select:focus {
  border-color: var(--ink);
  outline: 2px solid var(--ink);
  outline-offset: 0;
}

/* The select's chevron is 20px, 20px in from the right edge. */
body.pub select.input, body.pub .check-v3 .cell-select {
  padding-right: 52px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Cpath d='M5 8l5 5 5-5' fill='none' stroke='%2352606e' stroke-width='2'/%3E%3C/svg%3E");
  background-position: right 20px center;
  background-size: 20px;
}

/* The label over a field, 15/20 at 500 with 8 under it. */
body.pub .field label, body.pub .check-v3 .cell label {
  font-size: 15px;
  line-height: 20px;
  font-weight: 500;
  margin-bottom: var(--s2);
}

/* An error is a 2px failing edge with the message under the field at
   14/20; the padding steps in by one so the box does not grow. */
body.pub .field.error .input,
body.pub .check-v3 .cell.error .cell-input,
body.pub .check-v3 .cell.error .cell-select { padding: 15px 23px; }
body.pub .field .error-text, body.pub .check-errors p { font-size: var(--fs-pub-blurb); line-height: 20px; }

/* ------------------------------------------------ the bar, our placement */

/* THE PLACEMENT IS OURS AND DOES NOT MOVE (PUBLIC-SHEET.md section 6, and
   the review: "Different placement is allowed... do not require identical
   coordinates"). What the review DOES ask for is the navigation's
   typography, control styling and visual weight, so the shipped slim bar
   keeps its shape and its markup, which the signed in header test pins
   byte for byte, and its contents move onto the public scale: links
   16/24 at 500 in 40 tall targets, Sign in at 14/20, the door as a public
   button with 12px corners.

   The bar is taller than 46 with 40px controls in it, so the header token
   moves with it under this scope only; the anchors that clear the bar
   read the same token, so a linked FAQ row still lands clear of it. */
body.pub { --header: 64px; }
body.pub .topbar nav { gap: var(--s1); font-size: var(--fs-pub-body); }

/* THE LINKS ARE ONLY RE-SET WHERE THEY ARE DRAWN. Under 1024 the baseline
   hides them and the menu disclosure carries them, so the display here is
   inside a min-width query: an unconditional display would put two text
   links back into a 390px bar and push it sideways, which is exactly what
   the first shot at 390 caught. */
@media (min-width: 1024px) {
  body.pub .topbar nav > a:not(.btn) {
    display: inline-flex;
    align-items: center;
    height: 40px;
    padding: 0 var(--s3);
    border-radius: var(--radius-xs);
    font-size: var(--fs-pub-body);
    line-height: 24px;
    font-weight: 500;
  }
}

@media (hover: hover) and (pointer: fine) and (min-width: 1024px) {
  body.pub .topbar nav > a:not(.btn):not([aria-current="page"]):hover {
    background: var(--band);
    text-decoration: none;
  }
}

/* THE BAR'S OWN BUTTON STEPS BACK DOWN ON A PHONE, as the shipped bar does:
   a 16px label in 16px of padding beside a 40px menu button and the mark
   does not fit 390. The label is the short one there anyway. */
@media (max-width: 479px) {
  body.pub .topbar .btn.small { padding: 0 var(--s2); font-size: var(--fs-pub-blurb); }
}

body.pub .brand { font-size: var(--fs-pub-body); }
body.pub .site-menu > ul a { font-size: var(--fs-pub-body); line-height: 24px; font-weight: 500; min-height: 44px; }

/* ------------------------------------------------------------ the hero */

/* 96 above the h1 from 1024, the head capped at 1040, the line under it
   at 760, the form at 1000 (PUBLIC-SHEET.md section 5). */
body.pub .hero.hero-v3 { padding: var(--hero) 0 56px; }
body.pub .hero-v3 .hero-copy { max-width: 1040px; }
body.pub .hero-v3 h1 { max-width: 1040px; margin: 0 auto; }
body.pub .hero-v3 .lede { max-width: 760px; margin: 20px auto 0; }
body.pub .hero-v3 .check { max-width: 1000px; margin: 40px auto 0; }
body.pub .check-v3 .cell { flex: 1 1 260px; }
body.pub .check-v3 .cell.kind { flex: 1 1 260px; }
body.pub .check-v3 .check-foot { margin-top: 20px; }
body.pub .check-more > .more-toggle { font-size: var(--fs-pub-body); line-height: 24px; }

/* --------------------------------------------- the narrative objects */

/* Three cards, 20 gap, a 40px icon well, 16px corners and 24 inside; on
   the band they lose the hairline and take the 1px seat shadow, because
   a card is on the band with a shadow or on paper with a hairline and
   never both. Under 1024 a card becomes a row with the icon at the left. */
.pub-feats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--gap); }
.pub-feat {
  min-width: 0;
  padding: var(--s5);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--s4);
}
.pub-feat .ico {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  margin: 0 0 20px;
  border-radius: var(--radius-pub);
  background: var(--band);
}
.pub-feat .ico svg { width: 20px; height: 20px; color: var(--ink); }
.pub-feat h3 { margin: 0 0 var(--s2); font-size: var(--fs-pub-h3); line-height: 28px; font-weight: 600; }
.pub-feat p { margin: 0; font-size: var(--fs-pub-body); line-height: 24px; color: var(--ink-2); }
.pub-feat p + p { margin-top: 10px; font-size: var(--fs-pub-blurb); line-height: 22px; }
.band .pub-feat { border: 0; box-shadow: var(--shadow-1); }

/* A two column narrative row: the copy at 5, the object beside it at 7,
   56 apart, so no capped block stands beside a hole at 1920. .flip puts
   the copy on the right. */
.pub-duo { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 56px; align-items: center; }
.pub-duo > .copy, .pub-duo > .figure { min-width: 0; }
.pub-duo.flip > .copy { order: 2; }
.pub-duo .copy h2 { margin: 0 0 var(--s4); }
.pub-duo .copy > p { margin: 0; color: var(--ink-2); }
.pub-duo .copy ul { list-style: none; margin: 20px 0 0; padding: 0; display: grid; gap: 14px; }
.pub-duo .copy li { display: grid; grid-template-columns: 24px minmax(0, 1fr); gap: var(--s3); margin: 0; }
.pub-duo .copy li svg { width: 20px; height: 20px; margin-top: 2px; color: var(--ink); }
.pub-duo .copy li b { font-weight: 700; }
.pub-duo .copy li span { display: block; color: var(--ink-2); }
.pub-duo .copy .after { margin-top: var(--s5); }
.pub-duo .figure > .card { border-radius: var(--s4); box-shadow: var(--pub-shadow); }
.pub-duo .figure.stack-2 { display: grid; gap: var(--s4); }

/* The dated receipts of one worked fix. A 200px date column in the mono,
   the sentence beside it, the last row on the soft accent, a panel foot
   carrying the label that says the whole thing is an example. */
.pub-evidence {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--s4);
  overflow: hidden;
}
.pub-evidence ol { list-style: none; margin: 0; padding: 0; }
.pub-evidence li {
  display: grid;
  grid-template-columns: 200px minmax(0, 1fr);
  gap: var(--s1) var(--s5);
  align-items: start;
  margin: 0;
  padding: 18px var(--s5);
  border-top: 1px solid var(--line);
}
.pub-evidence li:first-child { border-top: 0; }
.pub-evidence .when {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-meta);
  font-weight: 500;
  line-height: 20px;
  color: var(--ink);
}
/* The kind of receipt under its stamp. `small` shrinks itself to 0.83em by
   the browser's own sheet, which put this line at 10.8px against a floor of
   12; it takes the stamp's own size back. */
.pub-evidence .when small { display: block; font-size: inherit; line-height: inherit; font-weight: 400; color: var(--ink-2); }
.pub-evidence .what { font-size: var(--fs-pub-body); line-height: 24px; }
.pub-evidence .what b { font-weight: 700; }
.pub-evidence .what span { display: block; color: var(--ink-2); }
.pub-evidence li.now { background: var(--accent-soft); }
.pub-evidence li.now .when { color: var(--accent); }
.pub-evidence .foot {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--s3);
  padding: 14px var(--s5);
  border-top: 1px solid var(--line);
  background: var(--band);
  font-size: var(--fs-pub-blurb);
  line-height: 20px;
  color: var(--ink-2);
}

/* The FAQ: the heading and one sentence at 4, the list at 8, so the
   capped lead has the questions beside it rather than a hole. */
.pub-faq-grid { display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); gap: 56px; align-items: start; }
.pub-faq-grid > .lead, .pub-faq-grid > .faq-list { min-width: 0; }
.pub-faq-grid .lead h2 { margin: 0 0 var(--s3); }
.pub-faq-grid .lead p { margin: 0; color: var(--ink-2); }
.pub-faq-grid .lead .after { margin-top: 20px; }
.pub-faq-grid .faq-list { max-width: none; }

/* The FAQ trigger is 20/28 at 500 with 16 above and below, and its answer
   16/26 (home.button[5], tpl[2].elements[31]). */
body.pub .faq-item summary { padding: var(--s4) 0; font-size: var(--fs-pub-h3); line-height: 28px; }
body.pub .faq-item summary .chevron { width: 20px; height: 20px; }
body.pub .faq-item .rest p { font-size: var(--fs-pub-body); line-height: 26px; }

/* THE ONE DARK BLOCK, AND THE SECOND 72px HEADING (PUBLIC-SHEET.md
   section 5). Ink, 24px corners, 80 by 64 inside, a white heading, the
   sentence in --closing-ink at 11.6:1, ONE white primary. It is the
   second decision region on the landing that carries a filled button, and
   it is allowed one because it comes after the whole explanation. */
.pub-close {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  gap: var(--s7);
  align-items: center;
  padding: 80px var(--s8);
  border-radius: var(--s5);
  background: var(--ink);
  color: var(--surface);
}
.pub-close h2 {
  margin: 0;
  color: var(--surface);
  font-size: var(--fs-pub-hero);
  line-height: 92px;
  font-weight: 700;
  letter-spacing: normal;
}
.pub-close p { margin: 20px 0 0; font-size: var(--fs-pub-lede); line-height: 32px; font-weight: 500; color: var(--closing-ink); }
.pub-close .doors { display: flex; flex-direction: column; align-items: flex-start; gap: var(--s3); }
.pub-close .doors .pub-meta { color: var(--closing-ink); }

/* --------------------------------------------------------- the footer */

/* Footer links one step up from the reference's 14/20, because our
   secondary ink is a 4.5:1 grey and a 14px link in it is small for a
   doormat; the lines beside them stay 14/20. */
body.pub .foot { padding: var(--s7) 0 var(--s5); font-size: var(--fs-pub-blurb); }
/* The column heads are the 12px mono caps label, which is the one role on a
   public page the measured face keeps. The heading rule above sets the face
   on every h2, so this says the label's own face back. */
body.pub .foot h2 { font-family: var(--font-mono); }
body.pub .foot a { font-size: 15px; line-height: 22px; }
body.pub .foot .foot-line { font-size: var(--fs-pub-blurb); line-height: 20px; }
body.pub .foot-legal { font-size: var(--fs-pub-blurb); }
body.pub .foot-legal nav a { font-size: var(--fs-pub-blurb); }

/* ---------------------------------------- motion, normal then reduced */

/* NORMAL MOTION (PUBLIC-SHEET.md section 8). It is written first, and as
   a positive statement, because the review found the old ruling read as
   if everything ran under reduced motion.

   150ms on a control's colour and transform on the D0 ease, press is
   scale(.98); 200ms on a disclosure's chevron; 200ms on the frame's one
   entrance. Nothing loops, nothing pings, nothing shines, and nothing
   nudges a reader toward a purchase. */
@media (prefers-reduced-motion: no-preference) {
  body.pub .btn {
    transition: background-color var(--dur-1) var(--ease), color var(--dur-1) var(--ease), transform var(--dur-1) var(--ease);
  }
  body.pub .topbar nav > a:not(.btn) { transition: background-color var(--dur-1) var(--ease); }
  body.pub .input, body.pub .check-v3 .cell-input, body.pub .check-v3 .cell-select {
    transition: border-color var(--dur-1) var(--ease);
  }
  body.pub .faq-item summary .chevron, body.pub .check-more .chevron {
    transition: transform var(--dur-3) var(--ease);
  }
}

/* REDUCED MOTION is the alternative, not the specification. Every
   duration on a public page is zero, the open chevron is drawn already
   turned, and the frame is simply there. COLOUR STILL CHANGES on hover
   and on focus, instantly, because a control that does not answer a
   pointer is a control a reader cannot tell is one. */
@media (prefers-reduced-motion: reduce) {
  body.pub *, body.pub *::before, body.pub *::after {
    transition-duration: 0s !important;
    animation-duration: 0s !important;
    animation-iteration-count: 1 !important;
  }
  body.pub .faq-item[open] summary .chevron { transform: rotate(180deg); }
}

/* --------------------------------------------- 1023 and under, the tablet */

@media (max-width: 1023px) {
  body.pub { --section: 64px; --hero: 72px; }
  body.pub .hero-v3 h1 { font-size: 56px; line-height: 64px; }
  body.pub .article h1 { font-size: var(--fs-pub-article); line-height: 56px; }
  body.pub .article.index h1 { font-size: var(--fs-pub-article); line-height: 56px; }
  body.pub .pricing-top .price-head h1 { font-size: var(--fs-pub-article); line-height: 56px; }
  body.pub .hero.hero-v3 { padding: var(--hero) 0 40px; }
  .pub-feats { grid-template-columns: minmax(0, 1fr); }
  .pub-feat { display: grid; grid-template-columns: 40px minmax(0, 1fr); gap: 0 20px; padding: 20px; }
  .pub-feat .ico { margin: 0; grid-row: 1 / span 3; }
  .pub-duo, .pub-duo.flip { grid-template-columns: minmax(0, 1fr); gap: var(--s6); }
  .pub-duo.flip > .copy { order: 0; }
  .pub-faq-grid { grid-template-columns: minmax(0, 1fr); gap: var(--s5); }
  .pub-close { grid-template-columns: minmax(0, 1fr); gap: 28px; padding: 56px 40px; }
  .pub-close h2 { font-size: 48px; line-height: 56px; }
  .pub-evidence li { grid-template-columns: 150px minmax(0, 1fr); padding: var(--s4) 20px; }
}

/* --------------------------------------------------- 599 and under, the phone */

@media (max-width: 599px) {
  body.pub { --section: 48px; --hero: 40px; }
  /* Every head at or above 36 becomes 36/45, and the hero 48/50
     (tpl[8].elements[4]). */
  body.pub .hero-v3 h1 { font-size: 48px; line-height: 50px; letter-spacing: normal; }
  body.pub .pub-intro h2, body.pub .pub-duo .copy h2, body.pub .pub-faq-grid .lead h2,
  body.pub .article h1, body.pub .article.index h1,
  body.pub .pricing-top .price-head h1, body.pub .pub-close h2 {
    font-size: var(--fs-pub-compact);
    line-height: 45px;
    letter-spacing: normal;
  }
  body.pub .article.docs h1, body.pub .article.legal h1 { font-size: 26px; line-height: 34px; }
  body.pub .lede { font-size: 17px; line-height: 26px; }
  body.pub .pub-intro p { font-size: var(--fs-pub-body); line-height: 24px; }
  body.pub .hero-v3 .check { margin-top: var(--s5); }
  body.pub .check-v3 .cell, body.pub .check-v3 .cell.kind { flex: 1 1 100%; }
  body.pub .check-v3 .check-foot { flex-direction: column; align-items: stretch; }
  body.pub .check-v3 .check-foot .btn { width: 100%; }
  body.pub .faq-item summary { font-size: 18px; line-height: 26px; }
  .pub-feat { grid-template-columns: minmax(0, 1fr); }
  .pub-feat .ico { grid-row: auto; margin-bottom: 14px; }
  .pub-close { padding: 40px var(--s5); border-radius: 20px; }
  .pub-close p { font-size: 17px; line-height: 26px; }
  .pub-evidence li { grid-template-columns: minmax(0, 1fr); gap: 6px; padding: 14px var(--s4); }
  .pub-evidence .foot { padding: var(--s3) var(--s4); }
}

/* =====================================================================
   ==== P6R-S6 ====

   T6.6. The Stage 6 pages dressed: /proof, /pricing (the three plan
   tracks, the calculator embed and the dated vendors table) and
   /changelog. The class list is design/css-requests-phase6r-s6.md, one
   section per task, and the drawings are design/mockups/phase6r/s6/
   proof.html, pricing.html and changelog.html with section 9 of the
   NOTES beside them.

   TWO SHEETS ON THREE PAGES, AND EACH RULE SAYS WHICH ONE IT IS ON.
   /pricing and /changelog are body.pub, the Public sheet
   (design/mockups/phase6r/s7/PUBLIC-SHEET.md). /proof is the one public
   page rendered with :app-sheet, the same arrangement /sample has: it
   draws the workspace's own objects, it carries no body.pub, and its
   rules below are scoped by .proof-property so nothing here reaches a
   customer's screen.

   WHERE THE REQUEST AND THE PUBLIC SHEET DISAGREE, THE SHEET WINS, which
   is what design/rules/phase6r-skin.md section 0 says in as many words.
   The s6 request was written against the D0 mockups, before the owner's
   review of 2026-09-05 measured the reference's public templates, so it
   asks for a 13px sentence in a dozen places. On a public page the
   smallest SENTENCE is 14 / 20 ("the floor for a sentence a reader must
   read", PUBLIC-SHEET.md section 2) and the smallest text of any kind is
   the 12px mono label. Every 13 in the request for /pricing and
   /changelog is therefore a 14 here, and every label the request pins at
   12 stays 12. The heads and ledes those two pages already inherit from
   P6R-S2A are not touched: an article head is 48 / 60 and a lede is
   20 / 32, and shrinking them back to the D0 scale is the regression the
   review named. On /proof the request's sizes are kept as written,
   because that page is on the App sheet, whose scale really is 14 / 13 /
   12.

   ONE SHIPPED RULE CHANGED, IN THE REGION WHERE IT STANDS, and it says
   so there: .pricing-top .plans in P6R-3 was two tracks and T6.2 added a
   third card, so the free check wrapped onto a row of its own with a
   hole beside it at 1400 and 1920. Scoping a three track override to
   this region would have left the two track rule in the file for the
   next reader to believe.

   THREE NAMES WERE TAKEN, AND THE MARKUP GAVE EACH OBJECT ITS OWN. Every
   one of them was a shipped name meaning something else in this file or
   in the operator sheet, which is the six-collision lesson of 5g:

    - the dated line over the vendors table is `.checked-on`, because
      `.checked` is the checks ledger in P6R-3, a `ul` with a hairline
      over it, and the paragraph would have inherited the hairline and
      lost its margins;
    - the calculator's in-page link to a plan card is `.plan-door`,
      because `.door` is the admin staff door's own class in
      design/admin.css and an admin page loads this sheet first;
    - the online shape checkbox and its sentence are `.shape-choice` and
      `.shape-choice-note`, because `.choice` is x-app.choice-cards in
      P6R-S1, a white card with an ink edge when its radio is ticked, and
      the first draft of the row rendered as a 1000px wide empty card
      with a tick box in the corner of it.
   ===================================================================== */

/* --------------------------------------------------- /proof, the property */

/* THE PAGE COLUMN. .wrap already caps at 1280, which is the app frame's
   own width, so what is left is the rhythm: the head 48 under the bar and
   24 between the cards. app.css gives .wrap.panel that 24px card stack
   only INSIDE .app-main, and this page is not inside it, which is why
   every card here sat against the next one with nothing between them. */
.section:has(> .proof-property) { padding-top: var(--s7); }
.proof-property { display: flex; flex-direction: column; gap: var(--s5); }

/* THE HEAD. app.css already draws it as two columns with the strip on the
   inner right edge, aligned to the head's foot, and stacks it under 900,
   which is the shape the request asks for. What it assumes is the panel
   ground of the workspace: on paper the strip is the only thing in the
   right column, so it is pushed to the head's own right edge rather than
   left floating in the middle of a 360px track. */
.proof-property .app-head .head-right { align-items: flex-end; }
.proof-property .app-head .head-right .weeks { justify-self: end; }

/* A CARD FOOT'S SENTENCE RUNS THE CARD'S WIDTH. The foot is a wrapping
   flex row that justifies its children apart, so a foot carrying one
   sentence left that sentence at its own width with the rest of a 1182px
   card empty beside it: four of them at 1920 on the first shot, which is
   the owner's layout law of 2026-08-07 broken by a flex row rather than
   by a measure cap. Where the foot also carries a link the sentence still
   grows and the link still sits on the inner right edge. */
.proof-property .card-foot > p { flex: 1 1 auto; margin: 0; }

/* A MONDAY STILL BEING SAMPLED. A quiet dot in front of the line and no
   colour: it is a fact about a job, not a warning, and nothing on it is a
   count. The dot is the hairline's own heavier edge, so it reads as
   punctuation rather than as a status light. */
.proof-running { display: flex; align-items: baseline; gap: var(--s2); }
.proof-running::before {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: var(--radius-pill);
  background: var(--line-2);
  transform: translateY(-1px);
}

/* THE TWO SIDE CARDS UNDER THE LEDGER. The mockup draws them as a rail
   beside it; the shipped markup puts them in their own row underneath, so
   the ledger keeps the full width its table needs and neither card runs
   past what it stands beside. Two tracks from 1024, one under it, both
   stretched to one height. */
.proof-rail {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--gap);
  align-items: stretch;
}

@media (min-width: 1024px) {
  .proof-rail { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* AND A STRETCHED CARD PUTS ITS FOOT ON THE FLOOR. Two cards of one height
   is two cards with different amounts in them, so the shorter one's foot
   sat in the middle of its own card with the hairline it bleeds to the
   edges floating over white. The card becomes a column and the foot takes
   the space that is left. */
.proof-rail .card { display: flex; flex-direction: column; }
.proof-rail .card > .card-foot { margin-top: auto; }

/* THE BASE WEEK'S FACTS, in a card that is not .rail. The workspace writes
   this row as `.rail .kv` and the shipped markup here is the same shape
   under its own class, so the label and its value sit on one justified
   line with a hairline over each row and the value in the measured face
   where it is a figure. A value that is a WORD (the plan, the market, the
   language) carries no .mono and stays in the text face: being true is
   not what decides a face, being measured is. */
.proof-facts .kv {
  display: flex;
  justify-content: space-between;
  gap: var(--s3);
  padding: 7px 0;
  border-top: 1px solid var(--line);
  font-size: var(--fs-meta);
}
.proof-facts .kv:first-child { border-top: 0; padding-top: 0; }
.proof-facts .kv span { min-width: 0; color: var(--ink-2); }
.proof-facts .kv b {
  font-size: var(--fs-meta);
  font-weight: 500;
  color: var(--ink);
  white-space: nowrap;
}

/* THE QUESTIONS AS ASKED. A real two track grid and not a multicolumn
   block: a column box measures as a narrow column with a hole beside it
   and the harness is right to say so. No markers, because the slot number
   IS the marker, and it is measured, so it stands in the mono face in its
   own 28px gutter with the question beside it. */
.proof-questions {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 10px var(--s7);
}

@media (min-width: 1024px) {
  .proof-questions { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* AN ODD LAST QUESTION SPANS BOTH TRACKS (fix batch F19, item 9). Twenty
     five questions in two tracks left the last one alone on a row with a
     hole beside it, which design/harness/hole-1920.mjs names as the layout
     law of 2026-08-07 broken; spanning it gives that row content across
     its width. */
  .proof-questions li:last-child:nth-child(odd) { grid-column: 1 / -1; }
}

.proof-questions li {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr);
  gap: 0 var(--s2);
  align-items: baseline;
  margin: 0;
  font-size: var(--fs-body);
}
.proof-questions .mono { font-size: var(--fs-mini); color: var(--ink-2); text-align: right; }

/* ENGINES AND MODELS, one row an assistant. Three lines as three blocks,
   so a model string can wrap without dragging the assistant's name with
   it and the pin date after it never breaks mid word. The whole model
   string keeps the ink: the mockup dims its pin date with a span the
   shipped markup does not carry, and dimming half a string with a
   selector that matches nothing would have been a rule that lies. */
.proof-models { list-style: none; margin: 0; padding: 0; }
.proof-models li { margin: 0; padding: 10px 0; border-top: 1px solid var(--line); }
.proof-models li:first-child { border-top: 0; padding-top: 0; }
.proof-models li:last-child { padding-bottom: 0; }
.proof-models .m-name { display: block; font-size: var(--fs-body); font-weight: 600; color: var(--ink); }
.proof-models .m-model {
  display: block;
  margin-top: 1px;
  font-size: var(--fs-meta);
  color: var(--ink);
  overflow-wrap: anywhere;
}
.proof-models .m-weeks { display: block; font-size: var(--fs-mini); color: var(--ink-2); }

/* THE WEEK BEING READ. Panel ground, so the current row reads as a
   different KIND of row and not as a state. No colour, and never a second
   border: tr.total already owns the 2px rule under the last row, and the
   baseline already gives tr.now its ink and its 500. Scoped to this page
   because the workspace draws its own current row on its own ground. */
.proof-property .card-table .table tbody tr.now td { background: var(--band); }

/* THE SUM ROW SITS ON THE CARD. app.css puts the card ground under
   `.app-main .table tbody tr.total td` and this page is not inside
   .app-main, so the same rule is restated here rather than left to the
   panel band showing through the one row the reader is asked to add up. */
.proof-property .card-table .table tbody tr.total td { background: var(--surface); }

/* THE PROVENANCE LINE, on the paper under the cards: the lead in ink, the
   sentence in secondary, capped at the reading measure and CENTRED, so
   the leftover at 1920 is symmetrical margin rather than a hole beside it
   (the owner's layout law of 2026-08-07, second valid answer). The door
   under it is centred for the same reason, so the page ends on one
   measured column. */
.proof-prov {
  max-width: 78ch;
  margin: var(--s4) auto 0;
  font-size: var(--fs-meta);
  line-height: 1.55;
  color: var(--ink-2);
}
.proof-prov strong { color: var(--ink); font-weight: 600; }

/* THE ONE FILLED BUTTON OF THE PAGE, and the line under it that says what
   pressing it costs.

   AND IT IS THE PUBLIC CTA (fix batch F19, item 8). /proof is a public page
   whose tables and ledger are the workspace's own objects, so the page is
   rendered with the App sheet under it and carries no body.pub; that left
   its door at the App sheet's 13px label in a 34px box with 8px corners,
   beside every other public page's 16 / 24 at 700 in a 40px box with 12px
   corners. A reader walking from the front page to this one and back met
   two sizes of the same button. The control is restated here exactly as
   body.pub .btn writes it, scoped to this page's door and nothing else: the
   tables keep the App grammar the mockup drew them in. */
.proof-door { margin-top: 40px; text-align: center; }
.proof-door .meta { margin: var(--s3) 0 0; font-size: var(--fs-meta); color: var(--ink-2); }

.proof-property .proof-door .btn {
  min-height: 40px;
  padding: 8px var(--s4);
  border: 0;
  border-radius: var(--radius-pub);
  background: var(--button);
  color: var(--button-ink);
  font-family: var(--font-pub);
  font-size: var(--fs-pub-body);
  font-weight: 700;
  line-height: 24px;
  gap: var(--s2);
}

/* ------------------------------------------------------------- /pricing */

/* THE ODD LAST FACT OF "WHAT BOTH PLANS SHARE" SPANS BOTH TRACKS (fix batch
   F19, item 9). .includes has been two tracks from 760 since P6R-3, and an
   odd count left its last item beside a hole at 1920; this is the rule the
   proof page's questions take above, written on the public sheet's list. */
@media (min-width: 760px) {
  body.pub .includes li:last-child:nth-child(odd) { grid-column: 1 / -1; }
}

/* THE PAGE HEAD IS ONE CENTRED COLUMN, which is how both accepted mockups
   draw it: design/mockups/phase6r/s6/pricing.html (.price-head, 760
   centred) and s7/site-pricing-v2.html (.price-head-v2, 800 centred). The
   shipped rule was a 70ch cap pinned to the left edge of a 1216 frame, and
   the two "asks N assistants" lines under it carry a 70ch cap of their own
   at 13px, so at 1920 they measured 622 of 1216: 51 of a hundred, with
   nothing beside them. That is the owner's layout law of 2026-08-07, and
   the mockups' own answer is its third valid one, a single measured column
   with the whole head sharing its two edges. */
body.pub .pricing-top .price-head {
  max-width: 800px;
  margin: 0 auto var(--s6);
  text-align: center;
}
body.pub .pricing-top .price-head .lede { margin-left: auto; margin-right: auto; }
body.pub .pricing-top .assistants { margin-left: auto; margin-right: auto; }

/* The fine print under the plan row takes the same column, so the head and
   the foot of this row have one width and one centre. */
body.pub .pricing-top .plans-notes {
  max-width: 800px;
  margin-left: auto;
  margin-right: auto;
  text-align: center;
}

/* THE CANCEL FACT UNDER THE THREE ROWS. It is the only line on a card
   that is true of every plan, so it reads as a footnote to the card and
   never as a fourth row: no rule over it, because the rows already end on
   one, and its lead-in carries the ink. */
body.pub .pricing-top .plan-cancel {
  margin: var(--s3) 0 0;
  font-size: var(--fs-pub-blurb);
  line-height: 20px;
  color: var(--ink-2);
}
body.pub .pricing-top .plan-cancel b { color: var(--ink); font-weight: 600; }

/* ------------------------------- the illustration, .calc-embed (T2.8 F5) */

/* THE SAME OBJECT AS THE WORKSPACE'S CALCULATOR, on the public sheet.
   design/app.css draws .calc, .dial, .ibars and .plan-fact for the
   workspace page and /pricing does not load that file, so the same
   declarations are restated here under .calc-embed. The scope is what
   keeps them apart: a page that loads both sheets can only reach these
   rules through the embed, so the workspace's own copy is untouched.

   THREE VALUES DIFFER FROM THE WORKSPACE'S, ON PURPOSE: the slider takes
   a 4px track and a 2px INK focus ring at offset 2 (the Public sheet's
   ring is ink, T0.6 decision 3, and a control carries its own boundary at
   3:1 before it is focused), the band's track is 28px on the panel, and
   every size steps up to the public scale. */
body.pub .calc-embed { margin-top: var(--s5); }

/* THE MODEL, STATED, ABOVE THE DRAWING AND NEVER BESIDE IT. Four facts on
   the panel ground. They take two tracks from 1024 because four sentences
   in one column across a 1216 frame run past 180 characters a line, which
   is three times the measure this sheet reads at. */
body.pub .calc-embed .assumptions {
  margin: 0;
  padding: var(--s4);
  background: var(--band);
  border-radius: var(--radius-pub);
}
body.pub .calc-embed .assumptions .lbl {
  margin: 0 0 var(--s2);
  font-family: var(--font-mono);
  font-size: var(--fs-mini);
  font-weight: 500;
  line-height: 1.2;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-2);
}
body.pub .calc-embed .assumptions ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 6px var(--s6);
}
body.pub .calc-embed .assumptions li {
  margin: 0;
  font-size: var(--fs-pub-blurb);
  line-height: 21px;
  color: var(--ink-2);
}
body.pub .calc-embed .assumptions > p:last-child {
  margin: var(--s3) 0 0;
  font-size: var(--fs-pub-blurb);
  line-height: 20px;
}

@media (min-width: 1024px) {
  body.pub .calc-embed .assumptions ul { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* TWO CARDS SIDE BY SIDE FROM 1024, one column under it. This is the
   section's answer to the measure law: the dials on the left and the
   reading on the right, both keeping their width at 1920 rather than one
   capped block beside a hole. */
body.pub .calc-embed .calc {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--gap);
  align-items: start;
  margin-top: var(--gap);
}

@media (min-width: 1024px) {
  body.pub .calc-embed .calc { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
}

/* The card head here is an h3 and its sentence, without the .card-title
   wrapper the panel's own cards use, so the two elements are named
   directly. The section above owns the h2; a card inside it never does. */
body.pub .calc-embed .card-head h3 {
  margin: 0;
  font-size: var(--fs-h3);
  font-weight: 600;
  line-height: 1.35;
}
body.pub .calc-embed .card-head p {
  margin: 2px 0 0;
  font-size: var(--fs-pub-blurb);
  line-height: 20px;
  color: var(--ink-2);
}
body.pub .calc-embed .card-foot { font-size: var(--fs-pub-blurb); line-height: 20px; }

/* THE RATE THE WHOLE DRAWING IS HELD AT, under the head and over the
   dials. The line is secondary because it is the frame and not the
   reading; the rate inside it takes the ink where the sentence marks it. */
body.pub .calc-embed .fixed-point {
  margin: var(--s3) 0 0;
  font-size: var(--fs-pub-blurb);
  line-height: 1.5;
  color: var(--ink-2);
}
body.pub .calc-embed .fixed-point .ex,
body.pub .calc-embed .fixed-point .fig { color: var(--ink); font-weight: 500; }

/* ONE DIAL: the label and its value justified on one line, the help
   sentence under them, the slider, then the stops. A hairline over each
   dial and none over the first, so the two read as a list and not as two
   boxes. */
body.pub .calc-embed .dial { padding: var(--s4) 0 0; border-top: 1px solid var(--line); margin-top: var(--s4); }
body.pub .calc-embed .dial:first-of-type { border-top: 0; padding-top: 0; }
body.pub .calc-embed .dial .dial-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s3);
}
body.pub .calc-embed .dial .dial-head label { font-size: 15px; line-height: 20px; font-weight: 500; }
body.pub .calc-embed .dial .dial-head .val { font-size: 24px; font-weight: 600; line-height: 1; }
body.pub .calc-embed .dial p {
  margin: 2px 0 0;
  font-size: var(--fs-pub-blurb);
  line-height: 20px;
  color: var(--ink-2);
}

/* THE ONE CONTROL ON A PUBLIC PAGE THAT IS NEITHER A BUTTON NOR A FIELD.
   The native appearance is dropped so the track and the thumb are this
   sheet's, and the only thing that moves under a finger is the thumb. */
body.pub .calc-embed .dial input[type="range"] {
  width: 100%;
  height: 34px;
  margin: 10px 0 0;
  padding: 0;
  background: transparent;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}
body.pub .calc-embed .dial input[type="range"]::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: 2px;
  background: var(--line);
}
body.pub .calc-embed .dial input[type="range"]::-moz-range-track {
  height: 4px;
  border-radius: 2px;
  background: var(--line);
}
body.pub .calc-embed .dial input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 16px;
  height: 16px;
  margin-top: -6px;
  border-radius: var(--radius-pill);
  background: var(--ink);
  border: 2px solid var(--surface);
  box-shadow: 0 0 0 1px var(--ink);
  transition: transform var(--dur-1) var(--ease);
}
body.pub .calc-embed .dial input[type="range"]::-moz-range-thumb {
  width: 16px;
  height: 16px;
  border-radius: var(--radius-pill);
  background: var(--ink);
  border: 2px solid var(--surface);
  box-shadow: 0 0 0 1px var(--ink);
  transition: transform var(--dur-1) var(--ease);
}
body.pub .calc-embed .dial input[type="range"]:active::-webkit-slider-thumb { transform: scale(1.1); }
body.pub .calc-embed .dial input[type="range"]:active::-moz-range-thumb { transform: scale(1.1); }
/* THE RING IS INK ON THIS SHEET, at 2px and offset 2. Raspberry draws a
   ring in the workspace; on a public page the ring is the ink one every
   other control here takes, which is also the 14.6:1 reading. */
body.pub .calc-embed .dial input[type="range"]:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

/* THE STOPS. They are not evenly spaced, so the row is justified rather
   than laid on a grid: first left, last right, the rest centred over the
   stop each one names. They stay in the text face with tabular figures,
   which is what the Public sheet says a public number is. */
body.pub .calc-embed .ticks {
  display: flex;
  justify-content: space-between;
  margin: 2px 0 0;
  font-size: var(--fs-mini);
  line-height: 16px;
  color: var(--ink-2);
}
body.pub .calc-embed .ticks span { flex: 1; text-align: center; }
body.pub .calc-embed .ticks span:first-child { text-align: left; }
body.pub .calc-embed .ticks span:last-child { text-align: right; }
body.pub .calc-embed .ticks .on { color: var(--ink); font-weight: 500; }

/* Who is asked and how many times, read out under the assistants dial. */
body.pub .calc-embed .dial .roster {
  margin: var(--s2) 0 0;
  font-size: var(--fs-pub-blurb);
  line-height: 20px;
  color: var(--ink-2);
}
body.pub .calc-embed .dial .roster .fig { color: var(--ink); }

/* THE BAND ON ITS AXIS. One band, because there is no reading of the
   reader's own to draw beside it, and the tick is the rate the whole
   illustration is held at. */
body.pub .calc-embed .ibars { display: grid; gap: 14px; }
body.pub .calc-embed .ibar { display: grid; gap: var(--s1); }
body.pub .calc-embed .ibar .ib-label {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s3);
  font-size: var(--fs-pub-blurb);
  line-height: 20px;
  color: var(--ink-2);
}
body.pub .calc-embed .ibar .ib-label b { color: var(--ink); font-weight: 500; }
body.pub .calc-embed .ibar .ib-track {
  position: relative;
  height: 28px;
  border-radius: var(--radius-xs);
  background: var(--band);
}

/* THE FRACTIONS ARE MULTIPLIED HERE, which is the point of them being
   fractions: the copy law keeps the percent sign out of every file a
   customer can read, and a markup that writes "21.5%" is a markup with a
   rate in it. */
body.pub .calc-embed .ibar .ib-band {
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(var(--low, 0) * 100%);
  width: calc(var(--width, 0) * 100%);
  background: var(--accent-soft);
  border-left: 2px solid var(--accent);
  border-right: 2px solid var(--accent);
  border-radius: 3px;
}
body.pub .calc-embed .ibar .ib-tick {
  position: absolute;
  top: -3px;
  bottom: -3px;
  left: calc(var(--tick, 0) * 100%);
  width: 2px;
  margin-left: -1px;
  background: var(--ink);
}
body.pub .calc-embed .ibar .ib-reads {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s3);
  font-size: var(--fs-pub-blurb);
  line-height: 20px;
}
body.pub .calc-embed .ibar .ib-reads .pts { color: var(--ink-2); }

/* "An example, not a measurement.", with the band and not under the
   section, so a screenshot of the band alone still carries its label. It
   is a caption on a drawing rather than a sentence in the page, which is
   why it may sit on the 12px floor. */
body.pub .calc-embed .ibar .note {
  margin: var(--s1) 0 0;
  font-size: var(--fs-mini);
  line-height: 16px;
  color: var(--ink-2);
}

/* The axis is named, never numbered. */
body.pub .calc-embed .ib-axis {
  display: flex;
  justify-content: space-between;
  gap: var(--s3);
  margin: 2px 0 0;
  font-size: var(--fs-mini);
  line-height: 16px;
  color: var(--ink-2);
}

/* THE ONE SENTENCE UNDER THE BANDS. A range set in the measured face
   inside spoken text reads double spaced, so the figure keeps the
   sentence's own word spacing. */
body.pub .calc-embed .calc-sentence { margin: var(--s4) 0 0; font-size: var(--fs-pub-body); line-height: 1.5; }
body.pub .calc-embed .calc-sentence .fig { font-weight: 500; }

/* THE SHAPE'S PLAN AND THE DOOR TO ITS CARD. A justified row that wraps
   on a phone. The door is a quiet in-page link and never a button: the
   shape is a fact and the purchase is a decision made at the card forty
   pixels up this page. */
body.pub .calc-embed .plan-fact {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s2) var(--s3);
  margin: var(--s4) 0 0;
  padding: var(--s3) 14px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  font-size: var(--fs-pub-blurb);
  line-height: 20px;
}
body.pub .calc-embed .plan-fact .fig { color: var(--ink); font-weight: 500; }
/* AND IT IS .plan-door AND NOT .door. `.door` is the ADMIN staff door's own
   name (design/admin.css `body.admin.door`), an admin page loads site.css
   before admin.css, and that is the collision FrontPagePolishTest has stood
   over since the landing's closing door repainted /admin/login. The second
   name says what this one opens: the plan card forty pixels up this page. */
body.pub .calc-embed .plan-fact .plan-door {
  color: var(--ink);
  font-weight: 500;
  text-decoration: none;
}
body.pub .calc-embed .plan-fact .plan-door:hover { text-decoration: underline; }

body.pub .calc-embed > .meta { margin: var(--s4) 0 0; color: var(--ink-2); }

/* ----------------------------------- the dated table, .vendors (T6.2) */

/* THE DATE OVER THE TABLE, not under it: a table of other people's terms
   is worth what its date is worth, and a date under a table is a date
   read after the reader has already believed the cells.

   IT IS .checked-on AND NOT .checked. `.checked` is the checks ledger in
   P6R-3, a `ul` with a hairline over it, and this line would have
   inherited the hairline and lost its margins. The second name says what
   the line actually marks: the day the eight columns were read. */
body.pub .checked-on {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s2) var(--s3);
  margin: 0 0 var(--s3);
  padding: 0;
  border-top: 0;
  font-size: var(--fs-pub-body);
}
body.pub .checked-on .on { color: var(--ink); font-weight: 500; }
body.pub .checked-on .meta { font-size: var(--fs-pub-blurb); line-height: 20px; color: var(--ink-2); }

/* THE SCROLL BOX, AND THE FADE ONLY WHILE THERE IS SOMETHING TO SCROLL
   TO. The two layers are the CSS-only scroll shadow: the top one is
   painted with the CONTENT (background-attachment: local) so it sits over
   the shadow once the reader has reached the right edge, and the bottom
   one is painted with the BOX, so it shows through until then. No script,
   and nothing to get out of step with the box's real position.

   BOTH LAYERS ARE LINEAR AND FULL HEIGHT. The usual recipe draws the
   shadow with a radial gradient, whose farthest-side ellipse is half the
   box tall: on a table this long it showed as a smudge level with the
   middle row and as nothing at all at the head, which is where a reader
   is when they find out the table moves. */
body.pub .vendor-scroll {
  margin: 0;
  background:
    linear-gradient(to left, var(--band) 40%, transparent) right center / 32px 100% no-repeat local,
    linear-gradient(to left, rgba(var(--shadow-ink), 0.16), transparent) right center / 18px 100% no-repeat;
}

/* 1180 AND A FIXED LAYOUT, so eight fact columns keep one width whatever
   a cell says in them. At 1400 and 1920 the table fits inside the frame;
   at 768 and 390 it scrolls in its own box and the page does not move. */
body.pub .vendor-scroll .table.vendors { min-width: 1180px; table-layout: fixed; }

/* Eight column heads, two and three words each, so they wrap and sit on
   the bottom of the cell where the data starts. */
body.pub .vendor-scroll .table.vendors th {
  white-space: normal;
  vertical-align: bottom;
  height: auto;
  line-height: 1.35;
  padding: 10px;
}
body.pub .vendor-scroll .table.vendors th:first-child,
body.pub .vendor-scroll .table.vendors td:first-child { padding-left: var(--s4); }
body.pub .vendor-scroll .table.vendors th:last-child,
body.pub .vendor-scroll .table.vendors td:last-child { padding-right: var(--s4); }

/* The vendor's name, and its address under it as a span. NOT a <small>: a
   browser scales <small> off its parent, which put this line at 10px
   inside a 13px cell and under the harness floor before this sheet
   existed. Every 12px in this table is set, never inherited. */
body.pub .vendor-scroll .table.vendors th[scope="row"] {
  width: 104px;
  vertical-align: top;
  font-family: var(--font-pub);
  font-size: var(--fs-pub-blurb);
  font-weight: 500;
  line-height: 1.35;
  color: var(--ink);
  text-transform: none;
  letter-spacing: normal;
}
body.pub .vendor-scroll .table.vendors th[scope="row"] .site {
  display: block;
  margin-top: 2px;
  font-size: var(--fs-mini);
  font-weight: 400;
  line-height: 1.4;
  color: var(--ink-2);
}

/* A cell is four blocks tall at most: the value, the scope, the note and
   the source line. The value is a sentence, so it sits on the public
   sheet's own floor for one; the three under it are labels and sources
   and sit on the 12px floor. */
body.pub .vendor-scroll .table.vendors td {
  vertical-align: top;
  white-space: normal;
  padding: 10px 10px 11px;
  font-size: var(--fs-pub-blurb);
  line-height: 1.45;
  color: var(--ink-2);
}
body.pub .vendor-scroll .table.vendors td .fig,
body.pub .vendor-scroll .table.vendors td .n { color: var(--ink); }
body.pub .vendor-scroll .table.vendors td .scope,
body.pub .vendor-scroll .table.vendors td .note {
  display: block;
  margin-top: var(--s1);
  font-size: var(--fs-mini);
  line-height: 1.4;
  color: var(--ink-2);
}

/* THE SOURCE LINE. The page's NAME is the link and the address is on its
   title, because at this size a printed address breaks mid word and a URL
   broken mid word is the one thing that makes a source line look untrue.
   The links are secondary on a hairline underline so eight of them in a
   column do not read as eight accents; the date after them is measured. */
body.pub .vendor-scroll .table.vendors td .src {
  display: block;
  margin-top: 5px;
  font-size: var(--fs-mini);
  line-height: 1.4;
  color: var(--ink-2);
}
body.pub .vendor-scroll .table.vendors td .src a {
  color: var(--ink-2);
  text-decoration: underline;
  text-decoration-color: var(--line);
  text-underline-offset: 2px;
}
body.pub .vendor-scroll .table.vendors td .src a:hover {
  color: var(--ink);
  text-decoration-color: var(--ink-2);
}
body.pub .vendor-scroll .table.vendors td .src .on {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

/* OUR OWN ROW, LAST, under the 2px ink rule on the card ground. It is the
   only marked row and it is marked because it is ours, not because it is
   better. */
body.pub .vendor-scroll .table.vendors tr.ours th[scope="row"],
body.pub .vendor-scroll .table.vendors tr.ours td {
  border-top: 2px solid var(--ink);
  background: var(--surface);
  color: var(--ink);
}
body.pub .vendor-scroll .table.vendors tr.ours th[scope="row"] { font-weight: 600; }

/* The foot under the table, capped at the reading measure with the
   address in ink. It is left where the table starts, under a table that
   runs the frame, so there is nothing beside it to be a hole. */
body.pub .tbl-foot {
  margin: var(--s3) 0 0;
  max-width: 78ch;
  font-size: var(--fs-pub-blurb);
  line-height: 20px;
  color: var(--ink-2);
}

/* ----------------------------------------------------------- /changelog */

/* ONE MEASURED COLUMN AND EVERYTHING ON THE PAGE INSIDE IT. The head, the
   grid of major releases and the stream share one left edge and one right
   edge, so at 1920 the leftover is symmetrical margin and not a hole
   beside the text (the owner's layout law of 2026-08-07, third valid
   answer). 720 is wider than .article's 68ch cap, which this supersedes
   on this page and on no other: the grid of three needs the width and the
   entries are short. */
body.pub .article.log { max-width: 720px; padding-bottom: 0; }
body.pub .section:has(.log) { padding: var(--s7) 0 var(--s8); }

body.pub .log-head .mini { margin: 0 0 var(--s3); }
body.pub .log-head .lede { margin: var(--s3) 0 0; }

/* THE FEED IS PRINTED, NOT ONLY LINKED: a reader who wants it in their own
   reader needs the address, and an icon that says RSS to somebody who
   already knows what RSS is helps nobody type it. The mark goes in front
   of the link for the reader who reads marks. */
body.pub .log-head .feeds {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s2) var(--s4);
  margin: 14px 0 0;
  font-size: var(--fs-pub-blurb);
  line-height: 20px;
  color: var(--ink-2);
}
body.pub .log-head .feeds a { display: inline-flex; align-items: center; gap: 6px; }
body.pub .log-head .feeds a svg { width: 14px; height: 14px; }

/* A SECTION LABEL OVER A HAIRLINE, so "Major releases" and "All updates"
   read as the two halves of one page rather than as two more entries. */
body.pub .log .mini.sec {
  margin: var(--s6) 0 var(--s3);
  padding-top: var(--s5);
  border-top: 1px solid var(--line);
}

/* THE MAJOR RELEASES: the one place a card is allowed on this page, and
   each card is a door into its own entry below. Three tracks inside a 720
   column is a 232px card, which is why its title steps down from the
   sheet's card title: at 20px the same words ran five lines. */
body.pub .log .releases {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s3);
}
body.pub .log .rel {
  display: block;
  min-width: 0;
  padding: var(--s3) 14px 14px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: inherit;
  text-decoration: none;
  transition: border-color var(--dur-1) var(--ease);
}
body.pub .log .rel:hover { border-color: var(--ink-2); text-decoration: none; }
body.pub .log .rel .d {
  display: flex;
  justify-content: space-between;
  gap: var(--s2);
  font-family: var(--font-mono);
  font-size: var(--fs-mini);
  line-height: 1.4;
  font-variant-numeric: tabular-nums;
  color: var(--ink-2);
}
body.pub .log .rel h2 {
  margin: 6px 0 0;
  font-size: 15px;
  line-height: 1.35;
  font-weight: 600;
  letter-spacing: normal;
  color: var(--ink);
}
body.pub .log .rel p {
  margin: var(--s1) 0 0;
  font-size: var(--fs-pub-blurb);
  line-height: 20px;
  color: var(--ink-2);
}

/* THE STREAM: one list, no cards, a hairline between entries and nothing
   else. An ordered list because the order is the point: it is the order
   the tags were cut in. */
body.pub .log .stream { list-style: none; margin: 0; padding: 0; }
body.pub .log .stream > li {
  margin: 0;
  padding: 22px 0;
  border-top: 1px solid var(--line);
  /* The grid above and the feed's own guid both link to an entry by
     anchor, and the bar sits over the top of the page. */
  scroll-margin-top: calc(var(--header) + var(--s5));
}
body.pub .log .stream > li:first-child { border-top: 0; padding-top: var(--s1); }
body.pub .log .stream .d {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--s3);
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--fs-meta);
  line-height: 1.4;
  font-variant-numeric: tabular-nums;
  color: var(--ink-2);
}
/* The version in ink, so the two figures on the line are told apart
   without a second colour being spent on it. */
body.pub .log .stream .d .v { color: var(--ink); }
body.pub .log .stream h2 {
  margin: 6px 0 0;
  font-size: 18px;
  line-height: 26px;
  font-weight: 600;
  letter-spacing: normal;
}
body.pub .log .stream p { margin: var(--s2) 0 0; }
/* The same words open every entry's reason, so the lead-in must read as a
   label rather than as a second sentence of the body. */
body.pub .log .stream p.why {
  font-size: var(--fs-pub-blurb);
  line-height: 20px;
  color: var(--ink-2);
}
body.pub .log .stream p.why b { color: var(--ink); font-weight: 600; }

body.pub .log .foot-note {
  margin: var(--s5) 0 0;
  font-size: var(--fs-pub-blurb);
  line-height: 20px;
  color: var(--ink-2);
}

/* -------------------------------------------- 1023 and under, the tablet */

@media (max-width: 1023px) {
  /* The two side cards and the questions fall to one track with the
     .proof-rail and .proof-questions rules above; nothing else on /proof
     moves, because the app head already stacks at 900. */
  body.pub .log .releases { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ------------------------------------------------ 599 and under, the phone */

@media (max-width: 599px) {
  .section:has(> .proof-property) { padding-top: var(--s6); }
  .proof-property .app-head .head-right { align-items: stretch; }
  .proof-door { margin-top: var(--s6); }
  .proof-door .btn { width: 100%; }

  body.pub .calc-embed .plan-fact { flex-direction: column; align-items: flex-start; }

  /* The dated line stacks: the date first, the account sentence under it. */
  body.pub .checked-on { flex-direction: column; align-items: flex-start; gap: var(--s1); }

  body.pub .section:has(.log) { padding: var(--s6) 0 var(--s7); }
  body.pub .log .releases { grid-template-columns: minmax(0, 1fr); }
  body.pub .log .stream > li { padding: 18px 0; }
}

/* ----------------------- /fix-approval, the client's approval page (T5.6) */

/* THE DRAFT, WORD FOR WORD, IN A BOX THAT MOVES INSTEAD OF THE PAGE.
   x-site.layout draws this page on the public shell, so design/app.css and
   its own `.code-box` (a table of numbered lines, for the workspace) are not
   on it at all and the `<pre>` fell back to the browser's `white-space:
   pre`: one long line of a draft pushed the document to 414 at a 390
   viewport. That is the tables law broken by a code block, and a reader on a
   phone was being asked to swipe the whole page to read one attribute.

   PROSE WRAPS, A WORD BREAKS, AND ONLY THE BOX EVER SCROLLS. pre-wrap keeps
   the draft's own line breaks, which is the point of showing it verbatim,
   and lets an ordinary sentence fold at the box's edge; overflow-wrap breaks
   a run that has no space in it at all, which is what a long attribute or a
   URL is; and the box still carries its own sideways scroll for anything
   neither of those can help. The page itself never moves.

   13 IS THE VERBATIM SIZE, NOT A SENTENCE SIZE. The Public sheet's 14 / 20
   floor is for a sentence a reader must read. This is an artefact a reader
   must be able to check character by character, it is the size the workspace
   shows the same object at (design/app.css, `.code-box table`), and it
   stands above the 12px floor. */
/* AND THE ADDRESS ABOVE IT WRAPS, which is what really moved the page. The
   target is printed as a measured string with no space in it
   ("https://petraitisroofing.com/robots.txt"), so at 390 it stood 394 wide
   inside a 350 column and took the document to 414 with it. Every other
   address this sheet draws already breaks anywhere (the vendors table's
   `.site`, the proof page's model strings); this page is on the public shell
   and had no rule of its own. Scoped to the page, because a measured string
   inside a table cell is a column that is allowed to be wide. */
body.pub .approve .mono { overflow-wrap: anywhere; }

body.pub pre.code-box {
  min-width: 0;
  max-width: 100%;
  margin: var(--s2) 0 0;
  padding: var(--s3) 14px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  background: var(--band);
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  font-family: var(--font-mono);
  font-size: var(--fs-meta);
  line-height: 1.6;
  color: var(--ink);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  tab-size: 2;
}

/* ------------------------- the online choice, and the town it switches off */

/* T6.0's checkbox row, on all four forms that ask for a town: the front
   page's check object and the three panel forms. What is INSIDE the row is
   the same markup on both sheets, so the label, its checkbox and its
   sentence are written once here rather than twice; only the row that holds
   them differs, and both rows are below.

   THE IMPORT PREVIEW'S SEVENTH COLUMN IS NOT HERE. `.import-table` is the
   panel's object and design/app.css does not carry it yet (it is still an
   open line of design/css-requests-phase6r-s5.md), so raising a min-width
   that has never been set would be building somebody else's object in this
   file. */

/* A FULL WIDTH ROW OF THE CHECK OBJECT'S FLEX GRID, under the town cell and
   over the kind cell. It is never BESIDE the town: the sentence under the
   label is the load bearing half of the choice, and a two column split would
   put it off the measure. */
.check-v3 .cell-choice { flex: 1 0 100%; min-width: 0; margin-top: 6px; }

/* AND FROM 1024 IT RUNS UNDER THE WHOLE ROW, not through the middle of it.
   The request's own 1400 line is "the check object keeps its shipped three
   cell row and the choice row runs under it at the object's own width", and
   the Public sheet says the same thing in section 4: three fields in one row
   from 1024, each about 325 wide. The markup writes the choice between the
   town and the kind, which is where it belongs when the grid is one column,
   so the ORDER is what moves at the width where three cells really do share
   a line. Everything the markup writes after the kind cell moves with it, or
   the "More options" row and the button would jump in front of the choice. */
@media (min-width: 1024px) {
  .check-v3 .cell-choice { order: 1; }
  .check-v3 .cell-more,
  .check-v3 .cell.website,
  .check-v3 .cell.country,
  .check-v3 .check-foot { order: 2; }
}

/* The same row inside the panel's two column form grid. `.fgrid` is
   design/app.css's object and `.field` is this file's; the row is written
   here because every panel page loads both sheets in this order and a rule
   that spans the grid belongs beside the field it follows. */
.fgrid .field-choice { grid-column: 1 / -1; }

/* THE LABEL IS THE WHOLE TARGET, AND IT IS NOT A CARD. It is
   `.shape-choice` and not `.choice`, because `.choice` is x-app.choice-cards
   in region P6R-S1: a white card on a hairline at 10px with 12 by 14 inside
   and an ink edge when its radio is ticked, drawn on the claim card, the
   members form and the workspace kind. The first draft of this row wore that
   name and rendered as a 1000px wide empty card with a tick box in the
   corner of it, which is the six-collision lesson of 5g happening again. The
   second name says what this control chooses: the business's shape.

   The checkbox sits on the first line's baseline rather than on the top edge
   of its box, so a label that wraps does not leave the control floating
   beside the wrong line. */
.shape-choice {
  display: flex;
  align-items: flex-start;
  gap: var(--s2);
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
  font-size: var(--fs-body);
}

/* The front page asks one step larger than the panel, because the check
   object's own controls do. */
.check-v3 .shape-choice { font-size: 15px; }

/* THE ONE NATIVE CHECKBOX ON A PUBLIC FORM. accent-color rather than a drawn
   box: every browser already draws a checkbox a reader recognises, and what
   it needs from this sheet is our ink on the checked state and the ink ring
   on focus. The unchecked box keeps the browser's own boundary, which is the
   only part of a native control we are not allowed to repaint without
   repainting all of it. */
.shape-choice input[type="checkbox"] {
  flex: none;
  width: 16px;
  height: 16px;
  margin: 3px 0 0;
  accent-color: var(--ink);
}
.shape-choice input[type="checkbox"]:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

/* THE SENTENCE UNDER THE LABEL, indented to the label's own text edge (the
   box plus the gap) so the two read as one block. It carries its own name
   too: `.choice-note` is still on a paragraph of the schedule step that has
   no control in front of it, and indenting that one would be a rule reaching
   a page it was never written for. */
.shape-choice-note {
  margin: var(--s1) 0 0;
  padding-left: calc(16px + var(--s2));
  font-size: var(--fs-meta);
  line-height: 1.5;
  color: var(--ink-2);
}

/* THE TOWN CELL WHILE THE CHOICE IS TICKED. Quietened, never hidden: a cell
   that vanishes moves everything under it while somebody is reading it, and
   the reader has to be able to see that the town is the thing being switched
   off. The input's own :disabled already stops the caret. */
.check-v3 .cell.is-off,
.field.is-off { opacity: 0.55; }
