/* =====================================================================
   SEALED — production stylesheet. GENERATED by scripts/build-css.mjs.
   DO NOT HAND-EDIT: edit web/preview/intaglio/{tokens,system,surface-app}.css
   and re-run `npm run web:css`. A fix made only here is lost on the next
   build; a fix made only there never reaches production.

   The colourway switcher (colourways.css / colourways.js) is preview-only and
   deliberately absent — the chosen field lives in the tokens below.
   ===================================================================== */
/* =====================================================================
   SEALED — DIRECTION 5: "INTAGLIO"
   tokens.css — the whole vocabulary. Nothing below is decorative for its
   own sake; every token exists because the composition needs it.

   THESIS IN ONE LINE
   A seal's entire meaning is that it is destroyed by being opened. So the
   page IS the seal: one inked sheet, edge to edge, with four
   apertures cut through it. Everything Sealed will actually show you — a
   run, the price, the catalogue, the one action — is a hole in the sheet.
   Everything else is material.

   WHAT THIS FORCES, AND WHY THE TOKEN SET IS SO SHORT
   · There is no accent colour. Inside a flood, a second hue would be an
     accent applied to an accent. Emphasis is carried by INK OPACITY
     (86 → 100) and by the WIDTH AXIS of the typeface (wdth 100 → 112).
   · There are four type sizes on the entire page: 13 / 17 / 34 / 96.
   · Radii are 0 everywhere except the two receipt notches.
   · There are no shadows. A cut is drawn with a dark edge and a lit edge,
     never with a blur.
   · Dark mode is not a mode. The flood IS the mode; there is one page.
   ===================================================================== */

/* ---------------------------------------------------------------------
   FONTS — SELF-HOSTED. No CDN request, so the fallback below is a genuine last
   resort rather than a routine outcome: Google Fonts is blocked outright in
   some regions and by many corporate proxies and privacy tools, and the failure
   was total (see the font-stretch/font-weight note in section 3).
   Verified identical to the CDN build — font-stretch 112% measures 225.2px and
   font-weight 800 measures 228.63px on both, and both axes stay live.
   --------------------------------------------------------------------- */
@font-face{
  font-family:"Archivo";
  src:url("/public/fonts/archivo-latin.woff2") format("woff2");
  font-weight:100 900; font-stretch:62% 125%; font-style:normal; font-display:swap;
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:"Archivo";
  src:url("/public/fonts/archivo-latin-ext.woff2") format("woff2");
  font-weight:100 900; font-stretch:62% 125%; font-style:normal; font-display:swap;
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face{
  font-family:"Departure Mono";
  src:url("/public/fonts/departure-mono.woff2") format("woff2");
  font-weight:400; font-style:normal; font-display:swap;
}
@font-face{
  font-family:"Archivo Fallback";
  src:local("Helvetica Neue"),local("Arial"),local("Liberation Sans");
  size-adjust:97%; ascent-override:92%; descent-override:24%; line-gap-override:0%;
}
@font-face{
  font-family:"Departure Fallback";
  src:local("Menlo"),local("Consolas"),local("DejaVu Sans Mono");
  size-adjust:88%; ascent-override:96%; descent-override:24%; line-gap-override:0%;
}


:root{
  /* =================================================================
     1. COLOUR — one high-chroma field, one dark stock, nothing else.
     ================================================================= */

  /* THE FIELD. Prussian — iron-gall ink, banknote intaglio, blueprint.
     ~48% lightness, cool, and deliberately LOW chroma (0.097, half of
     Apple blue) so a full-viewport flood stays livable. It covers 100% of the viewport that is not an aperture. */
  --sheet-true:  #246290;   /* the true sheet colour, held addressable so the
                             app surface can remap --sheet to aperture stock while
                             the seam and the withheld field keep real sheet. */
  --sheet:        #246290;
  /* the debossed (shadowed) edge of a cut, and the counterseal fold */
  --sheet-deep:   #003D6A;
  /* the lit edge of a cut */
  --sheet-lift:   #5088B7;

  /* INK ON INTAGLIO. Opacity is the emphasis mechanism; there is no second hue.
       100%  clause numbers, the display line, strong runs-in   5.81:1
        86%  body — the AA floor on this ground                4.77:1
        60%  LARGE TEXT AND DECORATION ONLY                    3.18:1
     Nothing essential and small is ever set at 60%. */
  --ink:        #ECF3F8;
  --ink-86:     #ECF3F8DB;
  --ink-60:     #ECF3F899;
  /* pre-composited flats, for borders and SVG where alpha is awkward */
  --ink-86-flat:#D0DEEA;
  --ink-60-flat:#9CB9CF;

  /* THE APERTURE. A different stock entirely — near-black card seen
     through a cut in the sheet. Everything the product actually shows
     you sits on this. */
  --aperture:      #081018;
  --aperture-hi:   #0F1820;  /* hover / raised aperture, inputs        */
  --aperture-ink:  #E4E8ED;  /* 15.55:1 on --aperture                  */
  --aperture-ink-2:#909498;  /*  6.26:1 on --aperture — still AA       */
  --aperture-ink-86:#E4E8EDDB;  /* 86% — app-surface body ink        */
  --aperture-ink-60:#E4E8ED99;  /* 60% — app-surface decoration     */
  --aperture-rule: #E4E8ED1F;/* 12% hairline between rows — a DIVIDER,
                                which 1.4.11 does not govern            */
  /* 40% form-control edge. Was 20% (#E4E8ED33), which measured 1.76:1
     against --aperture-hi — an input whose own fill is 1.06:1 against the
     aperture behind it, so the field had no perceivable boundary at all.
     At 40% it measures 3.33:1 and clears 1.4.11 for a UI component edge. */
  --aperture-edge: #E4E8ED66;

  /* SEMANTIC COLOUR — a prohibition, not a palette.
     These may only ever be set INSIDE an aperture, on --aperture. On sheet
     they are meaningless: a red ground destroys the meaning of red, and
     green-on-red is the one pairing this page must never make.
     They are used as a 1px EDGE or a rule, never as text colour, because
     at these values only --warn clears 4.5:1 on the aperture stock. */
  --ok:      #2F7D53;   /* 3.81:1 on aperture — edge only              */
  --warn:    #C08A1E;   /* 6.28:1 on aperture — text-safe              */
  --danger:  #B03A2A;   /* 3.17:1 on aperture — edge only              */
  --info:    #909498;   /* informational uses the neutral, by design   */

  /* THE GRAIN. This is what makes the flood read as a material instead of
     a coloured div, and it is the single most load-bearing decoration in
     the direction.

     REVISED 2026-08-12, and be careful about WHY — the lab that proposed this
     change argued the old tile was aliased (lag-1 autocorrelation -0.077, i.e.
     a checkerboard). That claim came from rasterising the tile in a canvas and
     it does NOT reproduce on the rendered page: measured off real pixels, the
     old and new tiles both sit at r1 ~0.55 at 1x and ~0.79 at 2x. The old grain
     was fine as texture. Do not repeat the aliasing story.

     What was actually wrong was CONTRAST. The tile composited in linearRGB and
     was painted TWICE — once on body, once as a fixed overlay — which lightened
     the field enough to put body ink at 4.444:1 at 1x, under the 4.5 floor, on
     every flood page. One layer alone measured 4.504:1, i.e. scraping past.
     At 2x it passed, so it only bit non-retina displays.

     Now: baseFrequency 0.45, one octave, an explicit filter region, sRGB
     compositing, and a two-stop duotone tuned to Prussian (#184362 <-> #2F81BE)
     at constant 0.22 alpha — painted once. Measured on the page: cast +0.30 at
     1x and 0.00 at 2x, body ink 4.692:1 at 1x and 4.771:1 at 2x.
     Re-derive it if the field changes: the two stops are baked from #246290. */
  --grain:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180' viewBox='0 0 180 180'%3E%3Cfilter id='g' filterUnits='userSpaceOnUse' x='0' y='0' width='180' height='180' color-interpolation-filters='sRGB'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.45' numOctaves='1' seed='7' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='.2126 .7152 .0722 0 0 .2126 .7152 .0722 0 0 .2126 .7152 .0722 0 0 0 0 0 0 1'/%3E%3CfeComponentTransfer%3E%3CfeFuncR type='table' tableValues='0.0941 0.1843'/%3E%3CfeFuncG type='table' tableValues='0.2627 0.5059'/%3E%3CfeFuncB type='table' tableValues='0.3843 0.7451'/%3E%3CfeFuncA type='table' tableValues='0.22 0.22'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23g)'/%3E%3C/svg%3E");

  /* =================================================================
     2. TYPE — two families, four sizes, and WIDTH as hierarchy.
     ================================================================= */
  --font-display:"Archivo","Archivo Fallback","Helvetica Neue",Arial,sans-serif;
  --font-mono:"Departure Mono","Departure Fallback",ui-monospace,"SF Mono",Menlo,Consolas,monospace;

  /* the entire scale. Four steps. There is no fifth. */
  --t-13:13px;   /* labels, margin notes, footer, mono detail          */
  --t-17:17px;   /* clause numbers AND clause text — the page's voice  */
  --t-34:34px;   /* the emphasised clause. Once, twice at most.        */
  --t-96:clamp(2.75rem, 2rem + 3.75vw, 6rem); /* 44→96px. The wordmark.
                    Ratio 2.18 across the range, so 1.4.4 (200% text
                    resize) holds without a scrollbar appearing.       */

  --lh-96:0.88;  /* one word; the descender may sit into the rule below */
  --lh-34:1.1;
  --lh-17:1.5;
  --lh-13:1.45;

  --ls-96:-0.04em;
  --ls-34:-0.02em;
  --ls-17:0;
  --ls-13:0.05em;
  --ls-mono:0;   /* a pixel font must NEVER be tracked */

  /* THE WIDTH AXIS. This is the hierarchy device — not size, not colour.
     Archivo is variable on wdth 62..125 and wght 100..900.

     ADDRESSED VIA font-stretch AND font-weight, NOT font-variation-settings.
     Revised 2026-08-12; the reason is not cosmetic and it is easy to undo by
     accident, so it is written down here:

     1. FAILURE MODE. font-variation-settings does not set computed font-weight.
        Every emphasis site on this site computed 400 while asking for 800
        through the axis. When Archivo does not load — blocked CDN, corporate
        proxy, privacy mode, offline, or China, where Google Fonts is blocked
        outright — the fallback has no axes at all, so the width was discarded
        AND no synthetic bold fired. Measured: the 96px wordmark rendered
        byte-identical to 17px body copy, 195.4px and 22.041% ink for both.
        With font-weight the same case computes 800 and synthesises bold at
        26.278% ink, 1.19x. The width half is still lost — font-stretch does
        nothing on a static face — but the weight half survives.
     2. THE REPLACE TRAP. font-variation-settings REPLACES rather than merges,
        so a rule setting only "wdth" silently reset an inherited "wght" to
        400. Measured before the change: wght 800 followed by a wdth-only rule
        rendered at 400. font-stretch and font-weight inherit independently, so
        that class of bug cannot occur.
     3. NO COST. With Archivo loaded the two spellings are identical to the
        pixel: font-stretch:112% measures 225.2px, exactly matching
        "wdth" 112; font-weight:800 measures 228.63px, exactly matching
        "wght" 800; both together 252.83px, exactly matching both axes.

     Keep the unitless --wdth-* values below in step with the --stretch-*
     percentages: they are the same numbers, and the lab pages still address
     the axis directly to demonstrate it. */
  --wdth-narrow:62;   /* stamp start frame only                         */
  --wdth-text:100;    /* clause text                                    */
  --wdth-wide:112;    /* clause numbers, display, emphasis              */
  --stretch-narrow:62%;
  --stretch-text:100%;
  --stretch-wide:112%;

  --wght-text:400;
  --wght-med:500;     /* the emphasised clause and strong runs-in       */
  --wght-heavy:800;   /* clause numbers and the wordmark                */

  --measure:54ch;     /* clause text. Hard rule: aim for ≤3 lines.      */

  /* =================================================================
     3. SPACE — the 96px clause pitch is the only rhythm on the page.
     ================================================================= */
  --s-1:4px;  --s-2:8px;  --s-3:16px; --s-4:24px;
  --s-5:32px; --s-6:48px; --s-7:64px; --s-8:96px; --s-9:128px;

  --pitch:96px;          /* min-height of one clause row               */
  --col-n:72px;          /* the number column                          */
  --col-n-sm:48px;       /* …below 560px                               */

  /* the sheet is deliberately UNEQUAL. The wide right margin is the room
     a sealed document leaves for a counterseal; the nav lives in it. */
  --margin-l:clamp(24px, 6vw, 128px);
  --margin-r:clamp(24px, 12vw, 320px);
  --aperture-inset:96px; /* apertures sit further in from the right so
                            they read as inside the sheet, not at its edge */

  /* =================================================================
     4. BORDERS, RADII, ELEVATION
     A cut is a shadowed near lip on top/left and a LIT WALL on bottom/right.
     That is the entire depth model — no blur, no shadow, ever.

     REVISED 2026-08-12. The two lips used to be 1px each at -0.062 and +0.072
     okL from the field, measuring 1.31:1 and 1.36:1 against it and only 1.78:1
     against each other. Measured on the rendered page, the top edge ran field
     L* 39.8 -> deep 32.5 -> fill 4.4: monotonic, so a 7.3 darkening immediately
     before a 35.4 darkening integrated into one soft edge and read as the fill
     being 1px bigger. Only the bottom/right was a true local maximum.
     Now +/-0.13 okL — 1.72:1 and 1.72:1 against the field, 2.96:1 as a pair —
     and the far side is a 5px wall rather than a 1px line: a hole you can see
     the thickness of. The deltas derive per colourway, so this holds on all
     nine fields rather than only on Prussian.
     ================================================================= */
  --edge:1px;                /* legacy alias — still used by non-aperture rules */
  --wall-near:1px;           /* top/left: the shadowed lip                     */
  --wall-far:5px;            /* bottom/right: the lit wall, with real depth    */
  --edge-deep:var(--sheet-deep);
  --edge-lift:var(--sheet-lift);
  --r-0:0;               /* everywhere */
  --r-notch:8px;         /* the ONE exception: the receipt tear-off */
  --shadow:none;         /* there are no shadows on this page */

  /* =================================================================
     5. MOTION — mechanical, and it happens once.
     ================================================================= */
  --stamp-dur:340ms;
  --stamp-ease:steps(6, end);   /* pressed in six discrete increments */
  --t-link:120ms;               /* ink opacity 86 → 100               */
  --t-disclose:180ms;
  --ease-disclose:cubic-bezier(0.2, 0, 0.38, 0.9);
  /* THE ONE LOOP. Everything above happens once; the landing's agent
     ticker (system.css §20) is the single deliberate exception, argued
     in that section's banner. Reading pace, pausable, and it wraps to
     a static row under prefers-reduced-motion. A second loop anywhere
     does not get to cite this token. */
  --ticker-dur:44s;

  /* =================================================================
     6. Z-INDEX — three layers, because there are only three things:
        the sheet, the sticky rule, and the grain that sits over both.
     ================================================================= */
  --z-base:0;
  --z-sticky:20;
  --z-grain:40;

  /* focus. Ink at 100% on the sheet is 5.81:1 — well past the 3:1 that a
     non-text indicator needs. Inside an aperture the ring flips stock. */
  --focus-ring:2px solid var(--ink);
  --focus-offset:2px;

  color-scheme:dark; /* so scrollbars and form controls render dark
                        against the flood. prefers-color-scheme: light
                        changes nothing — see README §Dark mode. */
}

/* One page. Light preference is acknowledged and deliberately ignored. */
@media (prefers-color-scheme: light){ :root{ color-scheme:dark; } }


/* =====================================================================
   SEALED — DIRECTION 5: "INTAGLIO"
   system.css — every component, built only on tokens.css.

   READING ORDER
   0  reset + the sheet          5  rows, receipt, chips, tables
   1  the wordmark + margin      6  buttons, links, forms
   2  the clause list            7  states, notes, compare
   3  apertures (the cuts)       8  diagram
   4  sticky rule + counterseal  9  responsive + reduced motion
   ===================================================================== */

/* ── 0. RESET AND THE SHEET ───────────────────────────────────────── */
*{box-sizing:border-box;margin:0;padding:0}
/* NO `overflow-x:hidden` here. Setting it on html/body computes overflow-y
   to `auto`, which turns BOTH into scroll containers and silently kills
   `position:sticky` on every descendant — including .stickyrule, the one
   sticky object the direction has. Nothing on this page overflows at 375px
   (measured), so the hack bought nothing and cost the sticky rule. */
html,body{max-width:100%}
html{scroll-behavior:smooth}

body{
  /* THE FLOOD. 100% of the viewport that is not an aperture is sheet. */
  background-color:var(--sheet);
  background-image:var(--grain);
  background-attachment:fixed;
  color:var(--ink-86);
  font-family:var(--font-display);
  font-size:var(--t-17);
  line-height:var(--lh-17);
  font-stretch:var(--stretch-text);font-weight:var(--wght-text);
  -webkit-font-smoothing:antialiased;
  overflow-wrap:break-word;
  min-height:100%;
}

/* REMOVED 2026-08-12 — a fixed full-viewport grain overlay used to sit here at
   opacity .5, on top of the grain body already paints. Two layers of the same
   tile is twice the texture and a repaint on every scroll.

   Its stated job was to carry grain over the sticky rule and the counterseal so
   the sheet reads as one piece of material. It was not doing that job: both
   .stickyrule and .counterseal set background-image:var(--grain) themselves, so
   the effect survives its removal. What it also did, and should not have, was
   lay sheet texture over the aperture stock — the one surface in this direction
   that is explicitly a DIFFERENT material. */

a{color:inherit;text-decoration:none}
/* headings carry no size of their own. In this direction hierarchy is
   carried by the width axis, so an h2 must not arrive pre-sized. */
h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit;line-height:inherit}
img,video,svg{max-width:100%}
.scroll-x{overflow-x:auto}

/* THERE IS NO CONTAINER. No max-width, nothing centred. Content is
   positioned by unequal margins measured from the viewport edges. */
.sheet{padding-inline:var(--margin-l) var(--margin-r);position:relative}

.skip{position:absolute;left:-9999px;top:0;background:var(--aperture);
  color:var(--aperture-ink);font-family:var(--font-mono);font-size:var(--t-13);
  padding:12px 16px;z-index:100}
.skip:focus{left:0}

:where(a,button,input,select,textarea,summary,[tabindex]):focus-visible{
  outline:var(--focus-ring);outline-offset:var(--focus-offset);
}
.aperture :where(a,button,input,select,textarea,summary,[tabindex]):focus-visible{
  outline:2px solid var(--aperture-ink);
}
/* .skip paints ITSELF on aperture stock but lives outside .aperture, so the
   rule above never reached it and it took the sheet ring — var(--ink). On the
   two LIGHT colourways (manila, kraft) --ink is dark, which put a dark ring on
   a near-black chip: the first keyboard stop on every page had no visible
   focus indicator at all. It flips stock like anything else on that stock, and
   the ring is inset so it stays on the chip rather than landing on the sheet
   behind it — where a light ring would fail on a light field instead. */
.skip:focus-visible{outline:2px solid var(--aperture-ink);outline-offset:-2px}

/* ── 1. THE WORDMARK IS THE NAVIGATION ────────────────────────────────
   There is no nav bar. The word `sealed` at 96px in the top-left is
   simultaneously the wordmark and the only navigation; the four links
   sit stacked and right-aligned OUT IN THE MARGIN, the way a margin note
   sits beside a clause. Every other direction has a nav; this one has a
   margin. ------------------------------------------------------------ */
.masthead{
  display:grid;grid-template-columns:minmax(0,1fr) auto;
  align-items:start;column-gap:var(--s-5);
  padding-block:var(--s-6) var(--s-5);
}
.wordmark{
  display:block;
  font-size:var(--t-96);line-height:var(--lh-96);letter-spacing:var(--ls-96);
  color:var(--ink);
  font-stretch:var(--stretch-wide);font-weight:var(--wght-heavy);
  animation:sheet-stamp var(--stamp-dur) var(--stamp-ease) 1 both;
}
.wordmark .tld{color:var(--ink-60)}
/* the stamp: pressed in six discrete increments, once, on load, never again */
@keyframes sheet-stamp{
  from{font-stretch:var(--stretch-narrow);font-weight:var(--wght-heavy)}
  to  {font-stretch:var(--stretch-wide);font-weight:var(--wght-heavy)}
}

/* the margin: nav links + the one all-caps label the page allows itself */
.margin{
  display:flex;flex-direction:column;align-items:flex-end;gap:var(--s-2);
  text-align:right;
  /* pull out of the content column, into the counterseal margin */
  margin-right:calc(-1 * clamp(0px, 8vw, 200px));
  padding-top:var(--s-2);
}
.mlink{
  font-size:var(--t-13);line-height:var(--lh-13);letter-spacing:var(--ls-13);
  text-transform:none;color:var(--ink-86);
  transition:color var(--t-link) linear;
  min-height:24px;display:inline-flex;align-items:center;
}
.mlink:hover,.mlink[aria-current="page"]{color:var(--ink)}
.margin-label{
  font-size:var(--t-13);letter-spacing:var(--ls-13);text-transform:uppercase;
  color:var(--ink-86);margin-top:var(--s-3);max-width:22ch;line-height:var(--lh-13);
}

/* ── 2. THE CLAUSE LIST IS THE PAGE ──────────────────────────────────
   Thirteen-plus rows. Two columns: a 72px number, then the clause. No
   rules between them — the 96px pitch and the number column do all the
   separating. There are no section heads anywhere, by design: the clause
   numbers are the only structural typography on the page. ------------- */
.clauses{padding-bottom:var(--s-7)}

.clause{
  position:relative;
  display:grid;grid-template-columns:var(--col-n) minmax(0,1fr);
  align-items:start;min-height:var(--pitch);padding-block:var(--s-3) var(--s-4);
}
/* THE MARGINAL LABEL. The site's copy carries section labels ("The
   problem", "Listing", "Questions"). This direction has no section heads,
   so the label does not go above the clause — it goes OUT INTO THE
   COUNTERSEAL MARGIN beside it, like an annotation on a legal document.
   Same move as the hero eyebrow: the eyebrow leaves the column. */
.clause__margin{
  position:absolute;top:22px;right:calc(-1 * clamp(8px, 7vw, 180px));
  width:15ch;text-align:right;
  font-size:var(--t-13);line-height:var(--lh-13);letter-spacing:var(--ls-13);
  text-transform:uppercase;color:var(--ink-86);
}
.clause__n{
  font-size:var(--t-17);line-height:var(--lh-17);color:var(--ink);
  font-stretch:var(--stretch-wide);font-weight:var(--wght-heavy);
  font-variant-numeric:tabular-nums;
}
.clause__t{
  font-size:var(--t-17);line-height:var(--lh-17);letter-spacing:var(--ls-17);
  max-width:var(--measure);color:var(--ink-86);
}
.clause__t p+p{margin-top:var(--s-3)}
/* strong run-in: emphasis by WIDTH + WEIGHT + OPACITY. Never by colour. */
.clause__t b,.clause__t strong{
  color:var(--ink);font-weight:400;
  font-stretch:var(--stretch-wide);font-weight:var(--wght-med);
}

/* the callout mechanism, in full: one clause is set at 34px and spans
   both columns. There is no boxed variant, and there never will be. */
.clause--loud{grid-template-columns:1fr;row-gap:var(--s-2)}
.clause--loud .clause__n{display:block} /* the number keeps its place in the
   sequence even when the clause spans both columns — the count must never
   appear to skip, or the manifesto stops being a manifesto */
.clause--loud .clause__t{
  font-size:var(--t-34);line-height:var(--lh-34);letter-spacing:var(--ls-34);
  color:var(--ink);max-width:22ch;
  font-stretch:var(--stretch-text);font-weight:var(--wght-med);
}
/* …and when the frozen copy is too long for 34px, the emphasis is carried
   by the width axis alone. Same mechanism, quieter setting. */
.clause--wide .clause__t{
  max-width:64ch;color:var(--ink);
  font-stretch:var(--stretch-text);font-weight:var(--wght-med);
}

/* A clause may FOLD. This is the direction's answer to the FAQ: there is
   no FAQ, there are objections, and an objection is a clause that opens. */
.clause details{max-width:64ch}
.clause summary{
  list-style:none;cursor:pointer;position:relative;padding-right:var(--s-5);
  color:var(--ink);
  font-stretch:var(--stretch-wide);font-weight:var(--wght-med);
}
.clause summary::-webkit-details-marker{display:none}
.clause summary::marker{content:""}
.clause summary::after{
  content:"+";position:absolute;right:0;top:0;
  font-family:var(--font-mono);font-size:var(--t-17);color:var(--ink-86);
}
.clause details[open] summary::after{content:"–"}
.clause details[open] summary{margin-bottom:var(--s-2)}
.clause details .a{color:var(--ink-86);max-width:60ch}
.clause details .a+.a{margin-top:var(--s-3)}
.clause details>*:not(summary){animation:disclose var(--t-disclose) var(--ease-disclose) both}
@keyframes disclose{from{opacity:0}to{opacity:1}}

/* ── 3. APERTURES — THE ONLY BOXED OBJECTS ON THE PAGE ────────────────
   Not cards placed on the material: CUTS through it. 1px --sheet-deep on
   the top and left, 1px --sheet-lift on the bottom and right, which reads
   as debossed rather than raised. Radii 0. No shadow, ever. ----------- */
/* THE WALL, revised 2026-08-12. A cut through a sheet has thickness, and the
   two lips are not symmetric: the near one is a shadowed 1px lip, the far one
   is a lit wall you can see down. Measured on the page before this change, the
   top edge ran field L* 39.8 -> deep 32.5 -> fill 4.4 — monotonic, so a 7.3
   darkening immediately before a 35.4 darkening integrated into a single soft
   edge and read as the fill being 1px bigger. Only the bottom/right was a true
   local maximum, which is why a cut only looked like a cut along one pair of
   sides. Widening the deltas alone did not fix that; giving the far side real
   depth did. */
.aperture{
  background:var(--aperture);color:var(--aperture-ink);
  border-top:var(--wall-near) solid var(--edge-deep);
  border-left:var(--wall-near) solid var(--edge-deep);
  border-bottom:var(--wall-far) solid var(--edge-lift);
  border-right:var(--wall-far) solid var(--edge-lift);
  border-radius:var(--r-0);
  padding:var(--s-4);
  margin-right:var(--aperture-inset);
  margin-block:var(--s-3) var(--s-6);
  font-family:var(--font-mono);font-size:var(--t-13);line-height:1.6;
  letter-spacing:var(--ls-mono);
}
.aperture__label{
  display:block;font-family:var(--font-mono);font-size:var(--t-13);
  letter-spacing:var(--ls-13);text-transform:uppercase;
  color:var(--aperture-ink-2);margin-bottom:var(--s-3);
}
.aperture p{font-family:var(--font-display);font-size:15px;line-height:1.55;
  color:var(--aperture-ink);max-width:62ch}
.aperture p+p{margin-top:var(--s-3)}
.aperture .a-link{color:var(--aperture-ink);border-bottom:1px solid var(--aperture-ink-2)}
.aperture .a-link:hover{border-bottom-color:var(--aperture-ink)}

/* the receipt: the page's ONE radius exception — two 8px half-circle
   notches punched into the left and right edges. It is a tear-off stub. */
.aperture--receipt{
  -webkit-mask-image:
    radial-gradient(circle var(--r-notch) at 0 50%, transparent var(--r-notch), #000 calc(var(--r-notch) + 0.5px)),
    radial-gradient(circle var(--r-notch) at 100% 50%, transparent var(--r-notch), #000 calc(var(--r-notch) + 0.5px));
  mask-image:
    radial-gradient(circle var(--r-notch) at 0 50%, transparent var(--r-notch), #000 calc(var(--r-notch) + 0.5px)),
    radial-gradient(circle var(--r-notch) at 100% 50%, transparent var(--r-notch), #000 calc(var(--r-notch) + 0.5px));
  -webkit-mask-composite:source-in;mask-composite:intersect;
}
.aperture .receipt__fig{
  font-family:var(--font-display);font-size:var(--t-34);line-height:var(--lh-34);
  letter-spacing:var(--ls-34);color:var(--aperture-ink);
  font-stretch:var(--stretch-text);font-weight:var(--wght-med);
  font-variant-numeric:tabular-nums;max-width:24ch;
}
.receipt__rule{border:0;border-top:1px dashed var(--aperture-rule);margin:var(--s-4) 0}
.receipt__line{display:flex;justify-content:space-between;gap:var(--s-3);
  font-family:var(--font-mono);font-size:var(--t-13);color:var(--aperture-ink-2);
  font-variant-numeric:tabular-nums;padding-block:4px}
.receipt__line b{color:var(--aperture-ink);font-weight:400}
.aperture .receipt__stub{font-family:var(--font-mono);font-size:var(--t-13);
  line-height:1.7;color:var(--aperture-ink-2);margin-top:var(--s-4);max-width:none}

/* the CTA is an aperture: a 64px-tall cut with the label in mono. There
   is exactly one on a page and it is never above the fold. */
/* The CTA cut carries an ink hairline instead of the sheet deboss. A cut in
   the sheet is decoration and 1.4.11 does not govern it; a cut that is the
   page's ONE ACTION is a UI component and does. --aperture against --sheet
   measures 2.94:1, so the debossed edge (1.3:1) could not rescue it. Ink at
   60% is 3.18:1 against the sheet and 6.26:1 against the aperture fill, so
   the boundary is legible from both sides — and it reads as the scored line
   of a cut about to be pressed out, which is the metaphor, not a betrayal
   of it. --aperture itself is untouched, so every other cut keeps reading
   as stock seen through the sheet. */
.aperture--cta{
  padding:0;margin-bottom:var(--s-6);
  border:var(--edge) solid var(--ink-60);
  /* background-clip defaults to border-box, which paints the opaque fill UNDER
     the border — so this 60%-alpha edge was compositing over the fill (#91989E,
     2.23:1 against the field) rather than over the sheet. The comment that used
     to sit here claimed 3.05:1, which was the figure for compositing over the
     sheet. Clipping to padding-box makes the claim true: #9CB9CE, 3.18:1.
     This is the page's one action, so 1.4.11 applies to it — unlike a plain
     .aperture, which is a decorative container and exempt. */
  background-clip:padding-box;
}
.btn{
  display:flex;align-items:center;gap:var(--s-3);
  min-height:64px;padding-inline:var(--s-4);
  background:var(--aperture);color:var(--aperture-ink);
  font-family:var(--font-mono);font-size:var(--t-17);letter-spacing:var(--ls-mono);
  border:0;border-radius:var(--r-0);cursor:pointer;width:100%;
  transition:background var(--t-link) linear;
}
.btn:hover{background:var(--aperture-hi)}
.btn:active{background:#0C0A09}
.btn:disabled,.btn[aria-disabled="true"]{background:var(--aperture-hi);color:var(--aperture-ink-2);cursor:not-allowed}

/* A primary button INSIDE an aperture (a receipt's action, a form's submit)
   would otherwise be --aperture on --aperture: 1.00:1, a control with no
   boundary whatsoever. So it inverts — ink fill, aperture-coloured label.
   That is the stamp pressed INTO the card rather than another hole in it,
   it measures 15.55:1, and it keeps primary visibly distinct from the
   .btn--cut beside it. `.aperture--cta` is excluded: there the cut IS the
   button, and the fill is supposed to be the aperture stock. */
.aperture:not(.aperture--cta) .btn:not(.btn--cut):not(.btn--text){
  background:var(--aperture-ink);color:var(--aperture);
}
.aperture:not(.aperture--cta) .btn:not(.btn--cut):not(.btn--text):hover{background:#FFFFFF}
.aperture:not(.aperture--cta) .btn:not(.btn--cut):not(.btn--text):active{background:var(--aperture-ink-2)}
.aperture:not(.aperture--cta) .btn:not(.btn--cut):not(.btn--text):disabled,
.aperture:not(.aperture--cta) .btn:not(.btn--cut):not(.btn--text)[aria-disabled="true"]{
  background:var(--aperture-ink-2);color:var(--aperture)}

/* secondary: the same cut, UNFILLED — the sheet shows through. Its edge is
   ink at 60% (3.18:1 on the sheet), not the sheet deboss: an unfilled control IS
   its outline, and the deboss pair measures 1.3:1, which would have left
   the secondary button with no visible boundary whatsoever. */
.btn--cut{
  background:transparent;color:var(--ink);
  border:var(--edge) solid var(--ink-60);
  min-height:48px;width:auto;
  transition:border-color var(--t-link) linear;
}
.btn--cut:hover{background:transparent;color:var(--ink);border-color:var(--ink)}
.btn--cut:active{border-color:var(--ink)}
.btn--cut:disabled,.btn--cut[aria-disabled="true"]{color:var(--ink-60);border-color:var(--sheet-deep);cursor:not-allowed}

/* tertiary: text only, 1px underline, no box at all */
.btn--text{
  background:transparent;border:0;color:var(--ink);min-height:44px;width:auto;
  padding-inline:0;border-bottom:1px solid var(--ink-60);
  transition:border-color var(--t-link) linear;
}
.btn--text:hover{background:transparent;border-bottom-color:var(--ink)}
.btn--text:disabled,.btn--text[aria-disabled="true"]{color:var(--ink-60);border-bottom-color:var(--sheet-deep);cursor:not-allowed}

/* ── 4. THE STICKY RULE AND THE COUNTERSEAL ──────────────────────────
   A single 44px bar with ONE link, and it exists only after clause 06 —
   it is placed in the flow there, so a reader at the top never sees it.
   No JavaScript: `position:sticky` on an in-flow element does this. ---- */
.stickyrule{
  position:sticky;top:0;z-index:var(--z-sticky);
  display:flex;align-items:center;justify-content:space-between;gap:var(--s-3);
  height:44px;margin-block:var(--s-4);
  background-color:var(--sheet);background-image:var(--grain);
  border-bottom:1px solid var(--sheet-deep);
}
.stickyrule span{font-family:var(--font-mono);font-size:var(--t-13);
  letter-spacing:var(--ls-mono);color:var(--ink-86)}
.stickyrule a{font-size:var(--t-13);letter-spacing:var(--ls-13);color:var(--ink-86);
  border-bottom:1px solid var(--ink-60);transition:color var(--t-link) linear}
.stickyrule a:hover{color:var(--ink)}

/* the counterseal: a 96px block flush to the bottom-left on --sheet-deep
   rather than --sheet. It is the page's only tonal change, so the sheet
   reads as FOLDED rather than as having a footer. */
.counterseal{
  background:var(--sheet-deep);
  border-top:1px solid var(--sheet-deep);
  padding-block:var(--s-6);
  margin-top:var(--s-7);
}
.counterseal__grid{
  display:grid;grid-template-columns:minmax(0,2fr) minmax(0,1.4fr) minmax(0,1fr);
  gap:var(--s-5);align-items:start;
}
.counterseal .cs-brand{
  font-size:var(--t-17);color:var(--ink);letter-spacing:var(--ls-17);
  font-stretch:var(--stretch-wide);font-weight:var(--wght-heavy);
  margin-bottom:var(--s-2);display:flex;align-items:center;
}
/* no flex `gap` here: the wordmark is a bare text node plus a .tld span, so
   the span is its own flex item and a gap would open between "sealed" and
   ".run" as well as after the icon. The spacing belongs to the icon only. */
.counterseal .cs-brand img{
  width:20px;height:20px;display:block;margin-inline-end:var(--s-2);
}
.counterseal p,.counterseal li,.counterseal div{font-size:var(--t-13);line-height:1.7;color:var(--ink-86)}
.counterseal .cs-head{font-family:var(--font-mono);font-size:var(--t-13);
  letter-spacing:var(--ls-13);text-transform:uppercase;color:var(--ink-86);margin-bottom:var(--s-2)}
/* the counterseal underline is ink at 60% (4.62:1 on --sheet-deep), not
   --sheet-lift (1.73:1). Footer link text is the same --ink-86 as the footer
   prose around it, so the underline is the ONLY thing marking a link — at
   1.73:1 it was invisible and the footer failed 1.4.1 outright. */
.flink{color:var(--ink-86);border-bottom:1px solid var(--ink-60);
  transition:color var(--t-link) linear}
.flink:hover{color:var(--ink);border-bottom-color:var(--ink)}
.counterseal .cs-edition{font-family:var(--font-mono);font-size:var(--t-13);
  color:var(--ink-86);font-variant-numeric:tabular-nums;margin-top:var(--s-3)}

/* ── 5. ROWS, CHIPS, TABLES — everything that looks like software ─────
   and all of it lives inside an aperture. The surrounding sheet is what
   makes a row read as HELD INSIDE rather than merely listed. ---------- */
.rows{display:block;margin-top:var(--s-2)}
.row{
  display:grid;grid-template-columns:minmax(0,1fr) auto;
  align-items:baseline;gap:var(--s-3);
  min-height:36px;padding-block:var(--s-2);
  border-bottom:1px solid var(--aperture-rule);
}
.row:last-child{border-bottom:0}
.row__name{font-family:var(--font-display);font-size:15px;color:var(--aperture-ink);
  font-stretch:var(--stretch-text);font-weight:var(--wght-med)}
.row__by{display:block;font-family:var(--font-display);font-size:var(--t-13);
  color:var(--aperture-ink-2);margin-top:2px}
.row__num{font-family:var(--font-mono);font-size:var(--t-13);color:var(--aperture-ink);
  font-variant-numeric:tabular-nums;text-align:right;white-space:nowrap}
.row__go{font-family:var(--font-mono);font-size:var(--t-13);color:var(--aperture-ink);
  border-bottom:1px solid var(--aperture-ink-2);white-space:nowrap}
.row__go:hover{border-bottom-color:var(--aperture-ink)}

/* the search field + tabs that sit above a row list */
.rowbar{display:flex;flex-wrap:wrap;gap:var(--s-3);align-items:center;
  margin-bottom:var(--s-3)}
.tabs{display:flex;gap:0}
.tab{font-family:var(--font-mono);font-size:var(--t-13);letter-spacing:var(--ls-mono);
  color:var(--aperture-ink-2);background:transparent;border:0;
  border-bottom:1px solid transparent;padding:6px 12px;cursor:pointer;min-height:32px}
.tab[aria-selected="true"]{color:var(--aperture-ink);border-bottom-color:var(--aperture-ink)}
.tab:hover{color:var(--aperture-ink)}

/* input chips — only inside an aperture, mono 13px, 1px underline. */
.chips{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:var(--s-4);
  margin-top:var(--s-2)}
.chip__t{display:block;font-family:var(--font-mono);font-size:var(--t-13);
  letter-spacing:var(--ls-mono);color:var(--aperture-ink);
  border-bottom:1px solid var(--aperture-ink-2);padding-bottom:4px;margin-bottom:var(--s-2)}
.chip__b{font-family:var(--font-mono);font-size:var(--t-13);line-height:1.7;
  color:var(--aperture-ink-2);display:block}

/* THE WITHHELD FIELD. A solid rectangle of --sheet inside the aperture, so
   the material of the sheet is literally what "you cannot see this" looks
   like. It carries no label because it does not need one — that is the
   whole product in one object. */
.withheld{
  display:block;min-height:72px;margin-top:var(--s-3);
  background-color:var(--sheet);background-image:var(--grain);
  border:0;border-radius:var(--r-0);
}
.withheld--thin{min-height:20px}

/* table — figures are tabular everywhere they appear */
.tbl{width:100%;border-collapse:collapse;font-family:var(--font-mono);font-size:var(--t-13)}
.tbl caption{text-align:left;color:var(--aperture-ink-2);padding-bottom:var(--s-2);
  letter-spacing:var(--ls-mono)}
.tbl th{text-align:left;color:var(--aperture-ink-2);font-weight:400;
  padding:6px 12px 6px 0;border-bottom:1px solid var(--aperture-rule)}
.tbl td{color:var(--aperture-ink);padding:8px 12px 8px 0;
  border-bottom:1px solid var(--aperture-rule);font-variant-numeric:tabular-nums}
.tbl .num{text-align:right;padding-right:0}

/* code, inline code, keys, stamps */
.code{display:block;white-space:pre;overflow-x:auto;background:var(--aperture-hi);
  color:var(--aperture-ink);font-family:var(--font-mono);font-size:var(--t-13);
  line-height:1.7;padding:var(--s-3);border-radius:var(--r-0)}
code{font-family:var(--font-mono);font-size:var(--t-13);color:var(--ink);
  border-bottom:1px solid var(--ink-60)}
.aperture code{color:var(--aperture-ink);border-bottom-color:var(--aperture-ink-2)}
.kbd{font-family:var(--font-mono);font-size:var(--t-13);color:var(--aperture-ink);
  border:1px solid var(--aperture-ink-2);padding:1px 6px;border-radius:var(--r-0)}
/* not a pill — a STAMP. Radius 0, mono, 1px edge. */
.stamp{display:inline-flex;align-items:center;gap:6px;font-family:var(--font-mono);
  font-size:var(--t-13);letter-spacing:var(--ls-13);text-transform:uppercase;
  color:var(--aperture-ink);border:1px solid var(--aperture-ink-2);
  padding:2px 8px;border-radius:var(--r-0)}
.stamp--sheet{color:var(--ink);border-color:var(--ink-60)}

/* ── 6. LINKS AND FORMS ──────────────────────────────────────────────
   An inline link is ink at 100% with a 1px underline. There is no link
   colour, because there is no accent. ------------------------------- */
.link{color:var(--ink);border-bottom:1px solid var(--ink-60);
  transition:border-color var(--t-link) linear}
.link:hover{border-bottom-color:var(--ink)}
.muted{color:var(--ink-86)}
.muted .link{color:var(--ink)}

/* Forms exist ONLY inside apertures — a form is a place where something
   is shown or taken, and on this page that is what an aperture is for. */
.field{display:block;margin-bottom:var(--s-4);max-width:44ch}
.field__label{display:block;font-family:var(--font-mono);font-size:var(--t-13);
  letter-spacing:var(--ls-13);text-transform:uppercase;color:var(--aperture-ink-2);
  margin-bottom:var(--s-2)}
.input,.textarea,.select{
  width:100%;min-height:44px;background:var(--aperture-hi);color:var(--aperture-ink);
  border:1px solid var(--aperture-edge);border-radius:var(--r-0);
  font-family:var(--font-mono);font-size:var(--t-13);letter-spacing:var(--ls-mono);
  padding:10px 12px;
}
.textarea{min-height:96px;line-height:1.6;resize:vertical}
.select{appearance:none;background-image:none;padding-right:32px}
.input::placeholder,.textarea::placeholder{color:var(--aperture-ink-2)}
.input:hover,.textarea:hover,.select:hover{border-color:var(--aperture-ink-2)}
.field__help{display:block;font-family:var(--font-mono);font-size:var(--t-13);
  color:var(--aperture-ink-2);margin-top:var(--s-2)}
/* error is never carried by hue alone: a 1px danger edge PLUS a mono
   ERROR label, with the message itself in full-strength ink. */
/* --danger measures 2.96:1 against --aperture-hi, so it cannot be the
   field's whole boundary. It stays as the 2px left accent — the mark that
   says WHICH field — while the other three sides keep the compliant
   --aperture-edge. Hue is supplementary here, exactly as intended. */
.field--error .input,.field--error .textarea,.field--error .select{
  border-color:var(--aperture-edge);
  border-left:2px solid var(--danger)}
.field__err{display:flex;gap:8px;align-items:baseline;margin-top:var(--s-2);
  font-family:var(--font-mono);font-size:var(--t-13);color:var(--aperture-ink)}
.field__err::before{content:"ERROR";color:var(--warn);letter-spacing:var(--ls-13)}

/* radius 0 holds here too: a checkbox is a square that fills; a radio is
   a square with an inset block. They are told apart by their MARK, not
   by their outline — see README §Components. */
.check,.radio{
  appearance:none;width:16px;height:16px;flex:0 0 16px;border-radius:var(--r-0);
  border:1px solid var(--aperture-ink-2);background:var(--aperture-hi);
  display:inline-grid;place-content:center;cursor:pointer;margin-top:2px;
}
.check:checked{background:var(--aperture-ink);border-color:var(--aperture-ink)}
.check:checked::after{content:"✓";font-family:var(--font-mono);font-size:11px;
  color:var(--aperture);line-height:1}
.radio:checked::after{content:"";width:6px;height:6px;background:var(--aperture-ink)}
.choice{display:flex;gap:var(--s-2);align-items:flex-start;margin-bottom:var(--s-2);
  font-family:var(--font-mono);font-size:var(--t-13);color:var(--aperture-ink);cursor:pointer}

/* ── 7. STATES, NOTES, COMPARE ───────────────────────────────────────
   Semantic hue may only appear inside an aperture, and only as an edge.
   The text always stays in --aperture-ink so the pairing clears AA. --- */
.note{border-left:2px solid var(--aperture-ink-2);padding-left:var(--s-3);margin-top:var(--s-3)}
.note--info{border-left-color:var(--info)}
.note--ok{border-left-color:var(--ok)}
.note--warn{border-left-color:var(--warn)}
.note--danger{border-left-color:var(--danger)}
.note__tag{display:block;font-family:var(--font-mono);font-size:var(--t-13);
  letter-spacing:var(--ls-13);text-transform:uppercase;color:var(--aperture-ink-2);margin-bottom:4px}
.note--warn .note__tag{color:var(--warn)}

/* feedback states — deliberately unanimated. The loading state REPORTS,
   it does not spin: nothing on this page loops. */
.state{font-family:var(--font-mono);font-size:var(--t-13);color:var(--aperture-ink-2);
  padding:var(--s-4) 0;text-align:left}
.state b{display:block;color:var(--aperture-ink);font-weight:400;margin-bottom:4px}
.state__meter{color:var(--aperture-ink);letter-spacing:2px}

/* two-column compare: affirmative and negative, told apart by the edge
   they carry and by the direction of their mark, not by two hues. */
.compare{display:grid;grid-template-columns:1fr 1fr;gap:var(--s-4)}
.compare__col{padding-top:var(--s-3);border-top:2px solid var(--ink-60)}
.compare__col--yes{border-top-color:var(--ink)}
.compare__col h4{font-size:var(--t-17);color:var(--ink);margin:var(--s-2) 0;
  font-stretch:var(--stretch-wide);font-weight:var(--wght-med)}
.compare__col p{font-size:var(--t-17);color:var(--ink-86);max-width:40ch}
.compare__tag{font-family:var(--font-mono);font-size:var(--t-13);
  letter-spacing:var(--ls-13);text-transform:uppercase;color:var(--ink-86)}

/* numbered / ruled list — the "why it leaks" bullets. Numbers are in the
   number column, so the list is just a short clause list. */
.ruled{list-style:none}
.ruled li{display:grid;grid-template-columns:var(--col-n) minmax(0,1fr);
  align-items:start;padding-block:var(--s-3);border-top:1px solid var(--sheet-deep)}
.ruled li:last-child{border-bottom:1px solid var(--sheet-deep)}
.ruled .n{font-family:var(--font-mono);font-size:var(--t-13);color:var(--ink-86);
  font-variant-numeric:tabular-nums;letter-spacing:var(--ls-mono)}
.ruled .t{font-size:var(--t-17);color:var(--ink-86);max-width:var(--measure)}

/* ── 8. DIAGRAM ──────────────────────────────────────────────────────
   Every diagram in this direction obeys one rule: it is drawn INSIDE an
   aperture, in 1px strokes, with ink at three opacities and no gradient,
   no filter, no radius — and the only sheet-coloured shape in it is the
   thing being withheld. See README §Diagram rule. --------------------- */
.diagram{display:block;width:100%;height:auto}
.diagram text{font-family:var(--font-mono);font-size:11px;letter-spacing:0}

/* A DENSE diagram wrapped in §1's .scroll-x keeps its drawn width instead of
   scaling down with the cut. width:100% is right for a wide, sparsely
   labelled drawing — the one on /how-it-works has six labels and survives
   any width — but it is wrong for a dense one: .diagram text is a fixed
   11px in the viewBox's own units, so a 640-unit drawing inside a 340px cut
   renders its labels at about 6px, which is a drawing nobody can read.
   Below the fold-point such a diagram holds its width and the cut scrolls,
   which is exactly what a .tbl already does. Opt-in: an unwrapped .diagram
   is untouched, so this cannot change a drawing that was fine. */
@media (max-width:640px){
  .scroll-x .diagram{min-width:560px}
}

/* ── 9. RESPONSIVE ───────────────────────────────────────────────────
   560  number column 48px, right margin 24px, apertures full width
   900  counterseal and compare stack
   1440 right margin caps at 320px (handled by the clamp)
   ------------------------------------------------------------------- */
@media (max-width:900px){
  .counterseal__grid{grid-template-columns:1fr 1fr}
  .compare{grid-template-columns:1fr}
  /* below 900 the counterseal margin is too narrow to hold an annotation
     without crowding the measure, so the label folds above the clause */
  .clause__margin{position:static;width:auto;text-align:left;
    grid-column:2;margin-bottom:var(--s-2)}
}
@media (max-width:560px){
  :root{--col-n:var(--col-n-sm);--margin-r:24px;--aperture-inset:0px;--pitch:auto}
  .masthead{grid-template-columns:1fr;row-gap:var(--s-4);padding-block:var(--s-5) var(--s-4)}
  .margin{align-items:flex-start;text-align:left;margin-right:0;
    flex-direction:row;flex-wrap:wrap;gap:var(--s-3)}
  .margin-label{width:100%;margin-top:0}
  .clause{min-height:0;padding-block:var(--s-3) var(--s-4)}
  .counterseal__grid{grid-template-columns:1fr;gap:var(--s-4)}
  .chips{grid-template-columns:1fr}
  .aperture{margin-right:0}
  .row{grid-template-columns:1fr;gap:var(--s-2)}
  .row__num{text-align:left}
  .spec{grid-template-columns:1fr;gap:var(--s-3)}
  .sg-set{gap:var(--s-3)}
}

/* ── 10. STYLEGUIDE INSTRUMENTS ──────────────────────────────────────
   Used only by styleguide.html. `.is-*` are state PROXIES: they paint the
   hover/active/focus appearance on a static element so every state can be
   seen at once. Never ship them on a product page. ------------------- */
.is-hover.btn{background:var(--aperture-hi)}
.is-active.btn{background:#0C0A09}
.is-hover.btn--cut,.is-hover.btn--text{background:transparent}
.is-hover.btn--cut{border-color:var(--ink)}
.is-active.btn--cut{border-color:var(--ink)}
.is-hover.btn--text{border-bottom-color:var(--ink)}
.is-hover.link,.is-hover.flink{border-bottom-color:var(--ink)}
.is-hover.mlink{color:var(--ink)}
.is-focus{outline:var(--focus-ring);outline-offset:var(--focus-offset)}
.aperture .is-focus{outline:2px solid var(--aperture-ink)}

/* annotation prose stays in Archivo: Departure Mono is confined to
   apertures (plus the two numeric exceptions the direction grants — the
   sticky counter and the counterseal edition line). */
.sg-note{font-family:var(--font-display);font-size:var(--t-13);color:var(--ink-86);
  letter-spacing:0;margin-bottom:var(--s-3);max-width:70ch;line-height:1.7}
.sg-set{display:flex;flex-wrap:wrap;gap:var(--s-4);align-items:flex-start;margin-bottom:var(--s-4)}
.sg-cap{display:block;font-family:var(--font-display);font-size:var(--t-13);
  letter-spacing:var(--ls-13);text-transform:uppercase;color:var(--ink-86);margin-bottom:var(--s-2)}
.aperture .sg-cap{font-family:var(--font-mono);letter-spacing:var(--ls-13);color:var(--aperture-ink-2)}

.swatches{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:var(--s-3)}
.swatch{border-top:1px solid var(--ink-60);padding-top:var(--s-2)}
.swatch__chip{display:block;height:56px;border:1px solid var(--sheet-deep)}
.swatch__meta{font-family:var(--font-mono);font-size:var(--t-13);line-height:1.7;
  color:var(--ink-86);margin-top:var(--s-2);font-variant-numeric:tabular-nums}
.swatch__meta b{display:block;color:var(--ink);font-weight:400}

.spec{display:grid;grid-template-columns:minmax(0,1fr) 22ch;gap:var(--s-4);
  align-items:baseline;border-top:1px solid var(--sheet-deep);padding-block:var(--s-4)}
.spec__meta{font-family:var(--font-mono);font-size:var(--t-13);color:var(--ink-86);
  letter-spacing:var(--ls-mono);font-variant-numeric:tabular-nums}

.scale{display:grid;gap:var(--s-2)}
.scale__row{display:grid;grid-template-columns:10ch 1fr;gap:var(--s-3);align-items:center;
  font-family:var(--font-mono);font-size:var(--t-13);color:var(--ink-86);
  font-variant-numeric:tabular-nums}
.scale__bar{height:12px;background:var(--sheet-deep);border-right:1px solid var(--sheet-lift)}

/* prefers-reduced-motion: the wordmark renders at its final width
   immediately with no stamp. The 120ms link opacity SURVIVES, because a
   colour change carries no vestibular risk. */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  .wordmark{animation:none;font-stretch:var(--stretch-wide);font-weight:var(--wght-heavy)}
  .clause details>*:not(summary){animation:none}
}

/* ═════════════════════════════════════════════════════════════════════
   ── 11. THE CATALOGUE — THE MARKETPLACE BROWSE VIEW ──────────────────
   Used by marketplace.html. EXTENDS §5's .rows / .row; it does not
   replace them and it introduces no second row pattern.

   THE APERTURE DECISION, WRITTEN DOWN SO IT IS NOT RE-LITIGATED.
   The catalogue is ONE CUT, not fifteen. Fifteen cuts would be fifteen
   cards — the exact container this direction deleted — and fifteen
   debossed edges stacked at a 90px pitch turn the sheet into a grille,
   which is a texture, not a composition. An aperture is "the thing Sealed
   actually shows you", and here it is showing you ONE thing: the
   catalogue. So a single long window is cut through the sheet and the
   fifteen listings are RULED inside it on the §5 hairline, the way
   entries are ruled in a ledger. The sheet around the cut is what makes
   them read as HELD INSIDE rather than merely listed, and the ledger
   index in the left gutter is what makes fifteen of them read as a
   record rather than as a feed.

   Nothing in here may carry a hex value: the field colour is unsettled
   and two of the nine candidates are light with dark ink. Everything on
   the sheet goes through --ink/--ink-86/--ink-60, everything in the cut
   goes through --aperture-*.
   ═════════════════════════════════════════════════════════════════════ */

/* the search + tabs bar above the ledger. .rowbar is §5; these two only
   size its two children, because a .field defaults to a 44ch measure. */
.rowbar__search{flex:1 1 260px;margin:0;max-width:none}
.rowbar__tabs{margin-left:auto}

/* THE LEDGER. A .rows variant that opens a third column in front of the
   entry for the running index. 32px holds "01"–"15" in Departure Mono
   13px with room to spare; below 560 it drops to 28px and the price
   falls under the entry rather than being squeezed against it. */
.rows--ledger{margin-top:var(--s-3)}
.rows--ledger .row--entry{
  grid-template-columns:var(--s-5) minmax(0,1fr) auto;
  column-gap:var(--s-3);
  align-items:baseline;
  padding-block:var(--s-3);
  /* the rules and the hover run 8px past the text on both sides, so a row
     reads as a full-width entry in the cut rather than as a paragraph
     that happens to have a line under it */
  margin-inline:calc(-1 * var(--s-2));
  padding-inline:var(--s-2);
  transition:background var(--t-link) linear;
}
.rows--ledger .row--entry:hover{background:var(--aperture-hi)}
/* [hidden] must beat `display:grid`, or a filtered-out row stays visible */
.row[hidden]{display:none}

.row__n{
  grid-column:1;grid-row:1;
  font-family:var(--font-mono);font-size:var(--t-13);letter-spacing:var(--ls-mono);
  color:var(--aperture-ink-2);font-variant-numeric:tabular-nums;
}
.row__entry{grid-column:2;grid-row:1;display:block;min-width:0}
.rows--ledger .row__num{grid-column:3;grid-row:1}
/* the unit is secondary so the FIGURE is what the eye lands on */
.row__unit{color:var(--aperture-ink-2)}

/* the official mark. Same line as the name, but mono against Archivo,
   13px against 15px, and --aperture-ink-2 against --aperture-ink: three
   separate signals that it is a registry mark and not part of the name,
   so it never has to shout. */
.row__seal{
  font-family:var(--font-mono);font-size:var(--t-13);letter-spacing:var(--ls-mono);
  color:var(--aperture-ink-2);border-bottom:1px solid var(--aperture-ink-2);
  margin-left:var(--s-2);white-space:nowrap;
}

/* THE CLASSIFICATION LINE — execution mode, model tier, verification.
   Catalogue metadata only. Nothing here touches the skill body, and
   there is deliberately no "preview" or "see the prompt" affordance:
   a row shows you its label and its price, which is the whole argument. */
.row__meta{
  display:flex;flex-wrap:wrap;column-gap:var(--s-3);row-gap:2px;margin-top:6px;
  font-family:var(--font-mono);font-size:var(--t-13);letter-spacing:var(--ls-mono);
  line-height:1.5;
}
/* a fact never breaks across lines. Left to wrap, the browser takes the
   hyphens in an ISO date as break opportunities and splits "2026-06-11"
   over two lines, which is why the date is its own fact rather than the
   tail of the verification one. */
.row__fact{color:var(--aperture-ink-2);white-space:nowrap}
/* Mode B is the one listing that runs with local hands, so it is the one
   fact that gets a STAMP rather than a line of type — the §5 stamp, 1px
   edge, radius 0. It is told apart by having a border at all, never by a
   hue: semantic colour may not do this job even inside a cut, because
   Mode B is not a success, a warning or an error. */
.row__fact--stamp{
  color:var(--aperture-ink);border:1px solid var(--aperture-ink-2);
  padding:0 6px;border-radius:var(--r-0);
}

/* A ROW THAT HAS NOT LOADED IS A ROW THAT IS STILL SEALED.
   The direction forbids a shimmer, a pulse or a spinner, so the skeleton
   does not animate: the fields are drawn as the sheet's own material showing
   through the cut — the §5 withheld field at row scale. It is the same
   object, and it means the same thing it always means. */
.withheld--bar{display:block;min-height:12px;margin-top:0}
.row__entry .withheld--bar+.withheld--bar{margin-top:8px}
/* a sealed row has no text baseline to align to, so its three columns are
   aligned to the top instead of the shared first baseline */
.rows--ledger .row--sealed{cursor:default;align-items:start}
.rows--ledger .row--sealed:hover{background:transparent}

@media (max-width:560px){
  /* §9 collapses .row to a single column; the ledger keeps its index and
     drops the price onto its own line instead. */
  .rows--ledger .row--entry{
    grid-template-columns:28px minmax(0,1fr);
    row-gap:var(--s-2);
  }
  .rows--ledger .row__num{grid-column:2;grid-row:2;text-align:left}
  .rowbar__tabs{margin-left:0}
  .rowbar__tabs .tab{padding-inline:10px}
}

/* ═════════════════════════════════════════════════════════════════════
   ── 12. THE LISTING — ONE SKILL, AND THE RUN ─────────────────────────
   Used by skill-detail.html. Continues §11: same ledger logic, same
   stamps, same withheld field. Nothing here is a new pattern for its own
   sake — every class below exists because the detail view shows something
   the catalogue does not.

   THE ONE COMPOSITIONAL DECISION, WRITTEN DOWN.
   A run reads down the page as three objects in a fixed order:

        the inputs        form fields, on aperture stock — what you send
        the withheld      a solid rectangle of the sheet's own material
        the output        the ONLY 17px type inside any cut on the page

   The sheet rectangle sits between them in EVERY state — before the run,
   during it, and after the result arrives — and it never changes. That
   invariance is the argument: the inputs went in, the output came out,
   and the thing in the middle was never shown and never will be. It
   carries no caption, because §7's rule for .withheld is that it never
   carries one; the composition is the caption.

   The output is therefore the largest thing in any aperture on this page.
   Elsewhere a cut tops out at 15px (.aperture p, .row__name) with mono
   13px around it, so setting the result at --t-17 makes it the single
   loudest object inside the sheet without introducing a fifth size, a
   second hue, or a box. It is what the buyer paid for, so it is what is
   lit.

   Colour discipline is §11's: everything on the sheet through --ink*,
   everything inside a cut through --aperture-*, no literal anywhere,
   semantic hue only inside a cut and only as an edge plus a word.
   ═════════════════════════════════════════════════════════════════════ */

/* ── 12.1 THE LISTING HEAD, ON THE INTAGLIO ───────────────────────────────
   The skill's classification (mode, tier, category) is not a badge row:
   it is docket marginalia, so it goes out into the counterseal margin on
   §2's .clause__margin, beside the name it classifies. The two marks that
   are CLAIMS rather than classifications — Sealed-official, which links to
   the containment page, and the containment stamp — stay in the column as
   §5 stamps, because a claim has to be where the name is. */
.clause__margin--stack{width:20ch;line-height:1.7}
.skill__marks{display:flex;flex-wrap:wrap;gap:var(--s-2);margin-top:var(--s-2)}
a.stamp--sheet{transition:border-color var(--t-link) linear}
a.stamp--sheet:hover{border-color:var(--ink)}

/* the attestation line. Small, so it takes ink at 86% (4.77:1) and never
   60% — a date a buyer is asked to trust is not decoration. */
.trustline{
  font-size:var(--t-13);line-height:var(--lh-13);letter-spacing:var(--ls-13);
  color:var(--ink-86);font-variant-numeric:tabular-nums;margin-top:var(--s-3);
}

/* ── 12.2 THE DEFINITION LIST — the input schema, and best fit ────────
   Two columns ruled on --sheet-deep, exactly like §7's .ruled: a term and
   what it means. The term is <code>, which the system already allows on
   the sheet, minus its underline — an identifier is not a link, and the
   buyer has to be able to read `draft` as the literal field name they
   will send. This is catalogue metadata and nothing else: the schema
   describes the shape of the inputs, never the method that consumes them. */
.deflist,.deflist__hd{
  display:grid;grid-template-columns:minmax(0,17ch) minmax(0,1fr);
  column-gap:var(--s-4);max-width:64ch;
}
.deflist__hd{
  font-size:var(--t-13);line-height:var(--lh-13);letter-spacing:var(--ls-13);
  text-transform:uppercase;color:var(--ink-86);
  margin-top:var(--s-4);padding-bottom:var(--s-2);
}
.deflist dt,.deflist dd{border-top:1px solid var(--sheet-deep);padding-block:var(--s-3)}
.deflist dt{color:var(--ink)}
.deflist dt code{border-bottom:0;color:var(--ink)}
.deflist dd{font-size:var(--t-17);line-height:var(--lh-17);color:var(--ink-86)}
.deflist__tag{
  display:block;font-size:var(--t-13);line-height:var(--lh-13);
  letter-spacing:var(--ls-13);text-transform:uppercase;color:var(--ink-86);margin-top:4px;
}

/* ── 12.3 TYPE INSIDE A CUT ──────────────────────────────────────────
   §3 gives an aperture a label and a paragraph. The detail view also
   needs a heading and a long mono footnote, and both are used enough
   here to be system objects rather than one-off styles. */
.cut-h{
  font-family:var(--font-display);font-size:var(--t-17);line-height:var(--lh-17);
  color:var(--aperture-ink);margin-bottom:var(--s-2);
  font-stretch:var(--stretch-wide);font-weight:var(--wght-med);
}
/* Scoped to .aperture on purpose. A cut-note is BY DEFINITION inside a cut,
   and .aperture p (0,1,1) outranks a bare .cut-note (0,1,0) — so every
   <p class="cut-note"> was silently rendering as 15px display type at full
   aperture ink instead of the 13px mono footnote specified here. It looked
   deliberate, which is why it survived a build and an audit. (0,2,0) beats
   (0,1,1) on class count, so this now wins wherever it is actually used. */
.aperture .cut-note,
.cut-note{
  font-family:var(--font-mono);font-size:var(--t-13);line-height:1.7;
  letter-spacing:var(--ls-mono);color:var(--aperture-ink-2);
  font-variant-numeric:tabular-nums;margin-top:var(--s-3);
}
.aperture .cut-note a,
.cut-note a{color:var(--aperture-ink);border-bottom:1px solid var(--aperture-ink-2)}
.cut-note a:hover{border-bottom-color:var(--aperture-ink)}
/* run-in emphasis inside a cut is the width axis, as it is on the sheet */
.aperture p b{
  color:var(--aperture-ink);font-weight:400;
  font-stretch:var(--stretch-wide);font-weight:var(--wght-med);
}

/* SECONDARY AND TERTIARY BUTTONS INSIDE A CUT.
   §4 already fixed the primary button inside an aperture (it was
   --aperture on --aperture, 1.00:1). The same argument applies to the
   other two: .btn--cut and .btn--text are drawn in INTAGLIO ink, which is the
   wrong stock once they are inside a cut, and on a light colourway it is
   the wrong POLARITY — dark ink on near-black. They flip to aperture ink,
   with --aperture-edge (3.33:1) carrying the boundary. styleguide.html's
   one in-cut secondary already patched this inline; this generalises it. */
.aperture .btn--cut{color:var(--aperture-ink);border-color:var(--aperture-edge)}
.aperture .btn--cut:hover,.aperture .btn--cut:active{border-color:var(--aperture-ink);color:var(--aperture-ink)}
.aperture .btn--text{color:var(--aperture-ink);border-bottom-color:var(--aperture-ink-2)}
.aperture .btn--text:hover{border-bottom-color:var(--aperture-ink)}
/* a <button> centres its own label by default, which nobody notices until a
   tertiary label is long enough to wrap — at 375px the sample-run offer runs
   to three ragged centred lines. A text button is text: it sets left. */
.btn--text{text-align:left}

/* ── 12.4 THE RUN PANEL ──────────────────────────────────────────────
   Price, then the form, then the withheld field, then the action. */
.runhead{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--s-2) var(--s-3)}
.runhead .receipt__fig{max-width:none}
.runhead__unit{
  font-family:var(--font-mono);font-size:var(--t-13);letter-spacing:var(--ls-mono);
  color:var(--aperture-ink-2);
}
/* the field label carries an IDENTIFIER, so it is not upper-cased: the
   buyer sends `draft`, not `DRAFT`, and a label that rewrites its own data
   is a label that lies. Everything else about §6's label is unchanged. */
.field__label--id{text-transform:none;color:var(--aperture-ink)}
.field__req{color:var(--aperture-ink-2);margin-left:var(--s-2);text-transform:none}
.runform{margin-top:var(--s-5)}
.runform .field:last-of-type{margin-bottom:var(--s-3)}
.run-cta{margin-top:var(--s-4)}

/* ── 12.5 THE RESULT ─────────────────────────────────────────────────
   The head is a receipt line: what happened, and what it cost. Both are
   13px mono, because neither is the point. */
.result__hd{
  display:flex;flex-wrap:wrap;justify-content:space-between;gap:var(--s-2) var(--s-3);
  font-family:var(--font-mono);font-size:var(--t-13);letter-spacing:var(--ls-mono);
  color:var(--aperture-ink-2);font-variant-numeric:tabular-nums;
  padding-bottom:var(--s-3);border-bottom:1px solid var(--aperture-rule);
}
.result__hd b{color:var(--aperture-ink);font-weight:400}

/* THE OUTPUT. The only --t-17 inside any cut on this page, and the only
   thing on it set in the display face — everything around it is 13px mono
   at --aperture-ink-2. It is a <pre>, so it resets to the display family
   and wraps: an email that scrolls sideways is not a result you can read. */
.output{
  display:block;margin:var(--s-4) 0 0;padding:0;
  white-space:pre-wrap;overflow-x:auto;overflow-wrap:break-word;
  font-family:var(--font-display);font-size:var(--t-17);line-height:var(--lh-17);
  letter-spacing:var(--ls-17);color:var(--aperture-ink);max-width:60ch;
  font-stretch:var(--stretch-text);font-weight:var(--wght-text);
}
.acts{display:flex;flex-wrap:wrap;gap:var(--s-3);margin-top:var(--s-4)}
.acts .btn{min-height:44px}

/* ── 12.6 THE TERMINAL PANES ─────────────────────────────────────────
   §5's .code, with a bar naming the surface and a copy control. The
   comment lines drop to --aperture-ink-2 so the command is what reads. */
.codebar{
  display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;
  gap:var(--s-3);font-family:var(--font-mono);font-size:var(--t-13);
  letter-spacing:var(--ls-mono);color:var(--aperture-ink-2);padding-bottom:var(--s-2);
}
.codebar .btn--text{min-height:32px}
.code .c{color:var(--aperture-ink-2)}

/* figures are tabular EVERYWHERE they appear, including inside a line of
   prose that is not otherwise a figure */
.tnum{font-variant-numeric:tabular-nums}

@media (max-width:900px){
  /* §9 folds .clause__margin above the clause by moving it to column 2.
     A .clause--loud has only ONE column, so `grid-column:2` manufactures a
     phantom second column there and the emphasised clause — the h1 on this
     page — gets indented into it. This is a fix to §9's fold, not a local
     patch: it reproduces on index.html's "Listing" clause at any width
     below 900, and correcting it there is the point. */
  .clause--loud .clause__margin{grid-column:1}
}
@media (max-width:560px){
  /* the definition list folds to one column: the term keeps the rule, the
     description gives it up, so a field sits directly under its own name. */
  .deflist,.deflist__hd{grid-template-columns:minmax(0,1fr);column-gap:0}
  .deflist__hd{display:none}
  .deflist dd{border-top:0;padding-top:0}
  .clause__margin--stack{width:auto}
}

/* ═════════════════════════════════════════════════════════════════════
   ── 13. THE ARRIVAL — GETTING INTO SEALED ────────────────────────────
   Used by signin.html. This is an APP-SURFACE page (README §8.2 as
   amended): stock, not flood. The composition is one aperture that fills
   the window, and the only sheet left on the page is the 2px seam that
   surface-app.css paints at the top of the viewport.

   THE ONE COMPOSITIONAL DECISION, WRITTEN DOWN.
   Sign-in is not three screens, it is ONE OBJECT in six positions. So the
   object's head and foot never move, and only its middle changes:

        the stage rule    01 ADDRESS · 02 INBOX · 03 KEY — always all three
        the heading       34px, the one emphasised line on the page
        the lede          15px, one sentence
        ── the middle ──  the form, or the wait, or the refusal
        the key slot      the thing you came for, in a fixed position
        the foot          the two trust links, on every stage

   THE KEY SLOT IS THE ARGUMENT, and it is the reason this page gets a
   withheld field at all. Your API key is a credential: before you ask, it
   does not exist; while it is in your inbox, it exists and is deliberately
   not here; when you arrive it is shown ONCE and never again. So the slot
   holds the sheet's own material in every stage except the two where you have
   actually arrived — the same rectangle, in the same place, meaning the
   same thing it means everywhere else in this system. It carries no label
   while it is sheet (§7's rule for .withheld is absolute); the label arrives
   with the key.

   Nothing here may carry a hex value — the field colour is unsettled and
   two of the nine candidates are LIGHT with dark ink. Everything inside
   the cut goes through --aperture-*; the withheld field and the seam are
   the only sheet, and surface-app.css already keeps them sheet.
   ═════════════════════════════════════════════════════════════════════ */

/* A cut that FILLS THE WINDOW gives up the 96px right inset, because there
   is no sheet left to be inset from — that is what §8.2 means when it says
   the app is what an aperture looks like at full size. */
.aperture--fills{
  margin-right:0;
  padding:var(--s-5);
}

/* ── 13.1 THE STAGE RULE ─────────────────────────────────────────────
   All three stages are present in every state, so the object reads as one
   thing moving rather than as three unrelated screens. It is a POSITION,
   never a measurement: there is no percentage, no elapsed time and no
   count, because the product computes none of those.

   Told apart by the WEIGHT OF THE TOP RULE — §7's .compare mechanism —
   plus a word, never by hue alone. Semantic colour appears only on the two
   states that are genuinely terminal, only as that same 2px edge, and only
   inside the cut: --ok is 3.81:1 and --danger 3.17:1 on --aperture, both
   past the 3:1 a non-text indicator needs and neither used as text. */
.stages{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:var(--s-3);list-style:none;margin-bottom:var(--s-5);
}
.stages__s{
  border-top:2px solid var(--aperture-rule);padding-top:var(--s-2);
  font-family:var(--font-mono);font-size:var(--t-13);letter-spacing:var(--ls-mono);
  line-height:1.5;color:var(--aperture-ink-2);font-variant-numeric:tabular-nums;
}
/* the mark sits UNDER the stage name rather than beside it: at 375px three
   columns of "01 ADDRESS" + "done" wrap raggedly, and a stage rule that
   reflows is a stage rule you stop trusting. */
.stages__mark{display:block;color:var(--aperture-ink-2)}
.stages__s[aria-current="step"]{border-top-color:var(--aperture-ink);color:var(--aperture-ink)}
/* these two come last on purpose: they must beat [aria-current] at equal
   specificity when a stage is both current and finished. */
.stages__s[data-at="done"]{border-top-color:var(--aperture-ink-2)}
.stages__s[data-at="in"]{border-top-color:var(--ok);color:var(--aperture-ink)}
.stages__s[data-at="blocked"]{border-top-color:var(--danger);color:var(--aperture-ink)}

/* ── 13.2 THE HEADING INSIDE THE CUT ─────────────────────────────────
   §12.3's .cut-h at 17px is a heading inside a cut that already has a page
   around it. This page has no clause list — the object IS the page — so
   its heading takes the 34px slot the clause list would otherwise own. It
   is still one of the four sizes, and only one stage exists at a time. */
.cut-h--loud{
  font-size:var(--t-34);line-height:var(--lh-34);letter-spacing:var(--ls-34);
  font-stretch:var(--stretch-text);font-weight:var(--wght-med);
  max-width:22ch;margin-bottom:var(--s-3);
}

/* ── 13.3 THE KEY SLOT ───────────────────────────────────────────────
   Fixed position in every stage, ruled off the middle so the eye can find
   it without reading. While it is sheet it is a bare .withheld and carries
   no caption; when the key lands, the caption lands with it. */
.keyslot{margin-top:var(--s-5);padding-top:var(--s-4);border-top:1px solid var(--aperture-rule)}
.keyslot .withheld{margin-top:0}
.keyslot__hd{
  display:block;font-family:var(--font-mono);font-size:var(--t-13);
  letter-spacing:var(--ls-mono);color:var(--aperture-ink);margin-bottom:var(--s-2);
}
/* the credential itself: a 1px edge at --aperture-edge (3.33:1), radius 0,
   and it WRAPS rather than scrolls — a key you have to scroll to read is a
   key you will copy wrong. */
.keyslot__row{
  display:flex;flex-wrap:wrap;align-items:center;gap:var(--s-3);
  border:var(--edge) solid var(--aperture-edge);border-radius:var(--r-0);
  padding:var(--s-3);
}
.keyslot__val{
  flex:1 1 220px;min-width:0;border-bottom:0;
  font-family:var(--font-mono);font-size:var(--t-13);letter-spacing:var(--ls-mono);
  color:var(--aperture-ink);overflow-wrap:anywhere;
}
.keyslot__row .btn--text{flex:0 0 auto;min-height:32px}
.keyslot__foot{margin-top:var(--s-2)}

/* ── 13.4 THE COLD START ─────────────────────────────────────────────
   Three steps, and they are §5 rows on §11's three-column ledger grid —
   not a new list, not cards. A step that is already finished says so in a
   word; it is not dimmed and it is not ticked in a hue. */
.rows--steps .row{
  grid-template-columns:var(--s-5) minmax(0,1fr) auto;
  column-gap:var(--s-3);align-items:baseline;padding-block:var(--s-3);
  margin-inline:calc(-1 * var(--s-2));padding-inline:var(--s-2);
  transition:background var(--t-link) linear;
}
.rows--steps a.row:hover{background:var(--aperture-hi)}
.rows--steps .row__n{color:var(--aperture-ink-2)}
.rows--steps .row__go{grid-column:3;grid-row:1}
.rows--steps .row__go--done{border-bottom:0;color:var(--aperture-ink-2)}

/* ── 13.5 SMALL PARTS ────────────────────────────────────────────────  */
/* THE OBJECT'S FOOT — the legal line and the two trust links, in the same
   place in every stage.

   This is not §12.3's .cut-note, and the reason is a defect worth writing
   down rather than working around silently: `.aperture p` (0,1,1) outranks
   `.cut-note` (0,1,0), so a <p class="cut-note"> inside a cut silently
   renders as 15px Archivo at full ink — the body voice — instead of the
   13px mono footnote §12.3 specifies. Raising .cut-note's specificity
   would fix it everywhere and is probably the right change, but it reflows
   every footnote on skill-detail.html, including its billing and terms
   lines, and that page is already reviewed. So this page declares its own
   foot and the defect is reported rather than quietly patched. Outside a
   cut .cut-note is unaffected and is still used, once, for the sample-data
   marker at the top of the page. */
.aperture .arrival__foot{
  font-family:var(--font-mono);font-size:var(--t-13);line-height:1.7;
  letter-spacing:var(--ls-mono);color:var(--aperture-ink-2);
  font-variant-numeric:tabular-nums;margin-top:var(--s-3);max-width:62ch;
}
.aperture .arrival__foot a{color:var(--aperture-ink);border-bottom:1px solid var(--aperture-ink-2)}
.aperture .arrival__foot a:hover{border-bottom-color:var(--aperture-ink)}
.aperture .arrival__foot b{color:var(--aperture-ink);font-weight:400}

/* a second heading inside the object (the cold start) needs the same step
   off the block above it that the lede gets; the 34px one does not, because
   the stage rule already carries its own bottom margin. */
.aperture--fills .cut-h:not(.cut-h--loud){margin-top:var(--s-5)}

/* §6's .field__label upper-cases, which is right for a two-word label and
   wrong for a frozen sentence: "Paste your key (or the token) from the
   email page" becomes two lines of all-caps mono. The copy is live product
   copy and does not change, so the label does. §12.4's --id modifier is
   the same mechanism for a different reason — an identifier must never be
   rewritten by its own label — and this is the sentence case of it. */
.field__label--sentence{text-transform:none}

/* a form inside this cut sits one step off the lede. §12.4's .runform is
   the run panel's own form and is not borrowed here, because the two will
   drift apart the moment either page changes. */
.arrival__form{margin-top:var(--s-5)}
.arrival__form .field:last-of-type{margin-bottom:var(--s-3)}
/* the dashed tear rule already exists (§5 .receipt__rule); this is the
   quieter divider between the two ways in — the link, or a key you hold. */
.arrival__or{border:0;border-top:1px solid var(--aperture-rule);margin:var(--s-5) 0 var(--s-4)}

@media (max-width:560px){
  .aperture--fills{padding:var(--s-4)}
  /* §9 collapses .row to one column; the steps keep their number column and
     drop the go word onto its own line, exactly as §11's ledger does. */
  .rows--steps .row{grid-template-columns:28px minmax(0,1fr);row-gap:var(--s-2)}
  /* justify-self, because a grid item stretches by default and .row__go is
     underlined: without it the rule under "fund →" runs the full column. */
  .rows--steps .row__go{grid-column:2;grid-row:2;justify-self:start}
  /* three stage cells at 375px are 105px wide; two rows of two reads, three
     abbreviated columns do not. */
  .stages{grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s-2) var(--s-3)}
}

/* ═════════════════════════════════════════════════════════════════════
   ── 14. THE ACCOUNT — ONE BALANCE, FOUR DIRECTIONS ───────────────────
   Used by account.html. APP SURFACE (README §8.2 as amended): stock, not
   flood. Cuts that fill the window on §13's .aperture--fills; the only
   sheet left is the 2px seam and the withheld field.

   THE ONE IDEA, AND THE CODE DECIDED IT, NOT THE DESIGN.
   src/billing.ts, lines 1-26: "every account has ONE unified, spendable
   balance … a settled skill call is a pure INTERNAL TRANSFER: the buyer's
   balance is debited and the provider's SAME spendable balance is credited
   their 80% … There is no separate 'seller earnings' pot; earnings ARE
   balance."

   So this page has no buyer panel and no seller panel, and no role switch.
   It has ONE figure, and four DIRECTIONS money moves in and out of it:

        in    top-up            BillingEntry kind "credit"
        in    a call you earned BillingEntry kind "transfer"  (your 80%)
        out   a call you paid   BillingEntry kind "debit"
        out   cash-out          BillingEntry kind "cashout"

   Those are the four `kind` values on the account's own ledger rows. A
   direction is therefore a property of the LEDGER, which is why all four
   are drawn even when two of them are at zero: an account that has never
   published still HAS an earnings direction; it has simply never used it.
   That is the whole disclosure argument in one component — nothing has to
   appear or disappear for the seller side to arrive.

   TOLD APART WITHOUT HUE, TWICE OVER. A direction is carried by the WEIGHT
   OF ITS TOP RULE (§7's .compare mechanism: full ink for in, --aperture-ink-2
   for out) PLUS the word "in" / "out", and every figure carries its own
   sign. No semantic colour is used for direction at all — in/out is not
   success/failure, and treating it as such would be the one thing the
   prohibition in §7 is there to stop.

   Nothing here may carry a hex value: the field is unsettled and two of the
   nine candidates are LIGHT with dark ink. Everything inside a cut goes
   through --aperture-*; the withheld field and the seam are the only sheet.
   ═════════════════════════════════════════════════════════════════════ */

/* ── 14.1 IDENTITY AND SESSION ───────────────────────────────────────
   Who is signed in, on what, and the way out. One row, and it wraps
   rather than truncating: an address you cannot read in full is an
   address you cannot check. */
.ident{
  display:grid;grid-template-columns:minmax(0,1fr) auto;
  align-items:start;column-gap:var(--s-4);row-gap:var(--s-3);
  padding-bottom:var(--s-4);border-bottom:1px solid var(--aperture-rule);
}
.ident__who{
  font-family:var(--font-display);font-size:15px;line-height:1.55;
  color:var(--aperture-ink);min-width:0;overflow-wrap:anywhere;
}
.ident__who b{
  font-weight:400;
  font-stretch:var(--stretch-wide);font-weight:var(--wght-med);
}
.ident__meta{
  display:block;font-family:var(--font-mono);font-size:var(--t-13);
  letter-spacing:var(--ls-mono);line-height:1.7;color:var(--aperture-ink-2);
  margin-top:var(--s-2);overflow-wrap:anywhere;
}
.ident .btn--cut{flex:0 0 auto}

/* ── 14.2 THE TALLY — the one figure, and the four directions ────────
   The figure reuses §5's .receipt__fig (34px display, tabular) because it
   is the same object a receipt shows: a settled amount. It is the only
   34px inside these cuts other than the page heading. */
.tally{margin-top:var(--s-4)}
.tally__fig{margin-top:var(--s-1)}
.aperture .tally__sub{
  font-family:var(--font-mono);font-size:var(--t-13);line-height:1.7;
  letter-spacing:var(--ls-mono);color:var(--aperture-ink-2);
  font-variant-numeric:tabular-nums;margin-top:var(--s-2);max-width:62ch;
}
.aperture .tally__sub b{color:var(--aperture-ink);font-weight:400}

.flows{
  display:grid;grid-template-columns:repeat(4,minmax(0,1fr));
  gap:var(--s-4) var(--s-3);list-style:none;margin-top:var(--s-5);
}
/* out is the quieter rule, in is the full-ink one — §7's .compare, applied
   to money instead of to an argument. The word below it says the same
   thing again, so the rule is never the only signal. */
.flow{border-top:2px solid var(--aperture-ink-2);padding-top:var(--s-2)}
.flow[data-dir="in"]{border-top-color:var(--aperture-ink)}
.flow__dir{
  display:block;font-family:var(--font-mono);font-size:var(--t-13);
  letter-spacing:var(--ls-13);text-transform:uppercase;color:var(--aperture-ink-2);
}
.flow__fig{
  display:block;font-family:var(--font-mono);font-size:var(--t-17);
  letter-spacing:var(--ls-mono);color:var(--aperture-ink);
  font-variant-numeric:tabular-nums;margin-top:var(--s-2);
}
.flow__t{
  display:block;font-family:var(--font-display);font-size:var(--t-13);
  line-height:var(--lh-13);color:var(--aperture-ink-2);margin-top:var(--s-1);
}
.flow__t b{
  display:block;color:var(--aperture-ink);font-weight:400;
  font-stretch:var(--stretch-wide);font-weight:var(--wght-med);
}

/* ── 14.3 THE ONE ACTIVITY LIST ──────────────────────────────────────
   Not two lists. A call you PAID FOR and a call you EARNED FROM are the
   same object — one settled CallRecord — read from opposite ends, so they
   are the same row with the direction word flipped and the split spelled
   out on the earning side. Extends §5's .rows on §11's three-column grid;
   there is no second row pattern here either. */
.rows--flow .row{
  grid-template-columns:6ch minmax(0,1fr) auto;
  column-gap:var(--s-3);align-items:baseline;padding-block:var(--s-3);
  margin-inline:calc(-1 * var(--s-2));padding-inline:var(--s-2);
}
.row__dir{
  grid-column:1;grid-row:1;
  font-family:var(--font-mono);font-size:var(--t-13);letter-spacing:var(--ls-13);
  text-transform:uppercase;color:var(--aperture-ink-2);white-space:nowrap;
}
.row--in .row__dir{color:var(--aperture-ink)}
.rows--flow .row__num{grid-column:3;grid-row:1}

/* ── 14.4 A SETTING ──────────────────────────────────────────────────
   The shape every control on this page takes: what it is, what it is set
   to, and the one thing you can do about it. The cap, auto-reload, the
   payout account and the session all use it, so they read as four of one
   kind rather than four inventions. */
.setting{
  display:grid;grid-template-columns:minmax(0,1fr) auto auto;
  align-items:start;column-gap:var(--s-4);row-gap:var(--s-2);
  padding-block:var(--s-4);
}
/* the rule goes BETWEEN settings, never above the first one — :first-of-type
   would be answering a question about element type rather than about
   position, and gets it wrong the moment a <p> is added above the group. */
.setting+.setting{border-top:1px solid var(--aperture-rule)}
.setting__t{min-width:0}
.setting__t b{
  display:block;font-family:var(--font-display);font-size:15px;
  color:var(--aperture-ink);font-weight:400;
  font-stretch:var(--stretch-text);font-weight:var(--wght-med);
}
.setting__t p{margin-top:var(--s-1)}
.aperture .setting__t p{font-size:var(--t-13);line-height:1.6;color:var(--aperture-ink-2);max-width:56ch}
.setting__v{
  font-family:var(--font-mono);font-size:var(--t-13);letter-spacing:var(--ls-mono);
  color:var(--aperture-ink);font-variant-numeric:tabular-nums;white-space:nowrap;
  text-align:right;
}
.setting__v span{display:block;color:var(--aperture-ink-2)}
.setting .btn--cut,.setting .btn--text{min-height:36px;align-self:start}

/* ── 14.5 LISTINGS — AND THE ONE THING THEY DO NOT SHOW ──────────────
   A seller's own listing row carries the name, the price and what it has
   earned. It does not carry the body, and neither does anything else on
   this surface: the body is sealed at rest (src/crypto-at-rest.ts) and is
   reachable only on the execution path. So the row draws the sheet's own
   sheet where a body would be — §7's withheld field, at row scale, meaning
   exactly what it means everywhere else. It spans the full row because it
   is not a column of data; it is the absence of one. */
.rows--listings .row{
  grid-template-columns:minmax(0,1fr) auto auto;
  column-gap:var(--s-4);row-gap:var(--s-2);align-items:baseline;
  padding-block:var(--s-3);
}
/* §11 pins .row__entry to column 2 for the ledger, which is a listing's
   column 1 here — so every cell in this row is placed explicitly rather
   than left half-auto, which is where grid bugs come from. */
.rows--listings .row__entry{grid-column:1;grid-row:1}
.rows--listings .row__num{grid-column:2;grid-row:1;white-space:nowrap}
.rows--listings .row__earn{grid-column:3;grid-row:1}
.rows--listings .withheld--bar{grid-column:1 / -1;grid-row:2;min-height:16px}

/* ── 14.6 THE REVOKE CONFIRMATION ────────────────────────────────────
   Rendered in place on this preview rather than as a dialog, so the copy
   can be read beside the table it belongs to. The destructive control
   takes a 2px --danger LEFT EDGE and keeps its word — the identical
   mechanism §6 uses for .field--error, and for the identical reason: at
   3.17:1 the hue may mark which control it is, never carry the meaning. */
.confirm{
  border:var(--edge) solid var(--aperture-edge);border-radius:var(--r-0);
  padding:var(--s-4);margin-top:var(--s-4);
}
.aperture .confirm__h{
  font-family:var(--font-display);font-size:var(--t-17);line-height:var(--lh-17);
  color:var(--aperture-ink);margin-bottom:var(--s-2);max-width:62ch;
  font-stretch:var(--stretch-wide);font-weight:var(--wght-med);
}
/* §12.3's `.aperture .btn--cut` sets border-color, so the danger edge has to
   match its specificity or it is silently repainted — and it has to survive
   hover, which sets border-color again. */
.aperture .btn--grave{border-left:2px solid var(--danger)}
.aperture .btn--grave:hover,.aperture .btn--grave:active{border-left-color:var(--danger)}

/* ── 14.7 SMALL PARTS ────────────────────────────────────────────────  */
/* A revoked key is told apart by the WORD in its status cell; the row also
   drops to secondary ink so the live keys are what the eye lands on. */
/* `.tbl td` sets colour on the CELL, so dimming the <tr> alone does nothing
   — the row's own cells have to be the thing that drops. */
.tbl .off td{color:var(--aperture-ink-2)}
.tbl .this{color:var(--aperture-ink-2);white-space:nowrap}
/* a .btn is display:flex, so two of them in one cell stack. They are a pair
   of controls, so they get a flex row of their own rather than the §12.5
   .acts, whose 24px top margin is wrong inside a table cell. */
.tbl .kacts{display:flex;flex-wrap:nowrap;gap:var(--s-3)}
.tbl .kacts .btn--text{min-height:32px}
/* §5's .tbl is width:100%, so a table too wide for its cut SQUASHES —
   "2026-06-02" breaks after the first hyphen and "Rotate / Revoke" stacks —
   rather than using the .scroll-x its own page wrapped it in. Refusing the
   breaks lets the table size to its content, which is what makes the
   scroller fire. No magic min-width: the content is the min-width. */
.scroll-x .tbl th,.scroll-x .tbl td{white-space:nowrap}

/* §4's .btn is width:100% because it was written for .aperture--cta, where
   the cut IS the button. Inside a §12.5 .acts row a full-width primary
   forces every sibling onto its own line, so a two-button row can never sit
   side by side. Scoped to .acts so the CTA cut is untouched; the two pages
   that already use .acts put only .btn--cut in it (width:auto already), so
   this changes nothing that exists. */
.acts .btn:not(.btn--cut):not(.btn--text){width:auto}

/* THE FOOTNOTE INSIDE A CUT — and a defect this is the SECOND workaround
   for. §12.3 specifies .cut-note as a 13px mono footnote, but `.aperture p`
   (0,1,1) outranks `.cut-note` (0,1,0), so every <p class="cut-note"> inside
   a cut silently renders as 15px Archivo at full ink. §13.5 declared
   .arrival__foot rather than fix it, because the fix reflows the already
   reviewed skill-detail.html. This page needs the same thing and declares
   .cut-foot for it — which means the one-line fix (raising .cut-note to
   `.aperture .cut-note`) is now owed twice, and when it lands BOTH
   .arrival__foot and .cut-foot collapse into it and both call sites become
   plain .cut-note. Outside a cut .cut-note is unaffected and is still used,
   once, for the sample-data marker at the top of this page. */
.aperture .cut-foot{
  font-family:var(--font-mono);font-size:var(--t-13);line-height:1.7;
  letter-spacing:var(--ls-mono);color:var(--aperture-ink-2);
  font-variant-numeric:tabular-nums;margin-top:var(--s-3);max-width:62ch;
}
.aperture .cut-foot a{color:var(--aperture-ink);border-bottom:1px solid var(--aperture-ink-2)}
.aperture .cut-foot a:hover{border-bottom-color:var(--aperture-ink)}
.aperture .cut-foot b{color:var(--aperture-ink);font-weight:400}

/* a second and third heading inside a filled cut needs the same step off
   the block above it that §13.5 gives the arrival's; this generalises that
   rule to any .cut-h that is not the first child of the cut. */
.aperture--fills .cut-h:not(.cut-h--loud):not(:first-child){margin-top:var(--s-5)}

@media (max-width:900px){
  .flows{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (max-width:560px){
  .ident{grid-template-columns:minmax(0,1fr)}
  .setting{grid-template-columns:minmax(0,1fr)}
  .setting__v{text-align:left}
  .setting .btn--cut,.setting .btn--text{justify-self:start}
  /* §9 collapses .row to one column; the activity list keeps its direction
     column and drops the amount onto its own line, exactly as §11's ledger
     and §13's steps do. */
  .rows--flow .row{grid-template-columns:6ch minmax(0,1fr);row-gap:var(--s-2)}
  .rows--flow .row__num{grid-column:2;grid-row:2;text-align:left}
  /* the listing folds to one column and stacks. Every cell has to be
     RE-PLACED, not just re-flowed: the explicit `grid-column:2/3` above
     would otherwise manufacture two implicit columns inside a one-column
     track list and crush the name to a single character per line. */
  .rows--listings .row{grid-template-columns:minmax(0,1fr);row-gap:var(--s-2)}
  .rows--listings .row__entry{grid-column:1;grid-row:1}
  .rows--listings .row__num{grid-column:1;grid-row:2;text-align:left}
  .rows--listings .row__earn{grid-column:1;grid-row:3}
  .rows--listings .withheld--bar{grid-column:1;grid-row:4}
}

/* ═════════════════════════════════════════════════════════════════════
   ── 15. EARNINGS — THE SELLER'S READ OF THE SAME LEDGER ──────────────
   Used by account-earnings.html. APP SURFACE (README §8.2 as amended):
   your money and your things, so it is stock. Every cut is §13's
   .aperture--fills, and the only sheet left on the page is the 2px seam
   and the withheld field.

   WHY THIS SECTION IS SHORT, AND WHY THAT IS THE POINT.
   §14 argued that a seller is not a role: earning is a DIRECTION on one
   ledger, not a second account. This page is that direction opened up —
   the same rows, read from the provider end. So almost nothing here is
   new. The listings are §14.5's .rows--listings, withheld bar included.
   The run list is §14.3's .rows--flow with the direction word flipped.
   The Connect flow is §13.1's .stages, unchanged, because getting paid is
   genuinely one object in six positions exactly as signing in was. The
   controls are §14.4's .setting and the figure is §5's .receipt__fig.
   Three things were genuinely missing, and all three are about ARITHMETIC
   BEING CHECKABLE.

   THE ARITHMETIC IS THE DESIGN, AND THE CODE MADE IT INTERESTING.
   src/billing.ts settleCall: providerCut = cents(price × 0.8), and
   platformCut = price − providerCut. Both round to the cent PER CALL, so
   the split is exactly 80/20 only when the price is a multiple of five
   cents. At $0.14 the provider keeps $0.11 and the fee lands at $0.03 —
   21.4% on that price, not 20.0%. A seller page that rounds that away is
   a seller page that cannot be audited, so the two components below exist
   to be added up by hand: a receipt-style reconciliation (.split) and a
   per-listing table with four numeric columns and a ruled total
   (.tbl--split). Neither introduces a figure the product does not compute.

   THE WITHHELD FIELD, TWICE, POINTING OPPOSITE WAYS.
   On the seller's OWN page the body is still not shown: §14.5's bar, and
   per §7 it carries no caption, here least of all — a rectangle that has
   to be explained on the page that proves it is a rectangle that failed.
   The cash-out cut then uses the SAME object for the mirror asymmetry:
   Stripe holds the seller's identity and bank details and Sealed never
   sees them (src/stripe.ts keeps a connect id and two booleans, nothing
   else). One rectangle, two directions of the same promise, no label on
   either.

   Nothing here may carry a hex value: the field colour is unsettled and
   two of the nine candidates are LIGHT with dark ink. Everything inside a
   cut goes through --aperture-*; semantic hue stays an edge plus a word.
   ═════════════════════════════════════════════════════════════════════ */

/* ── 15.1 THE RECONCILIATION ─────────────────────────────────────────
   §5's .receipt__line is already "a label and a figure, ruled apart" — it
   is what a receipt shows, and gross → fee → kept is a receipt. The one
   thing it lacks inside a cut that FILLS the window is a measure: at
   1280px a space-between line puts the label and the figure most of a
   metre apart and stops reading as one line. */
.split{max-width:46ch;margin-top:var(--s-4)}
.split .receipt__rule{margin:var(--s-3) 0}

/* ── 15.2 THE PER-LISTING TABLE ──────────────────────────────────────
   §5's .num zeroes the right padding, which is correct for a single
   trailing figure column and wrong for four of them in a row — they lose
   the gutter between them and the columns fuse. And the gutter has to sit on
   the LEFT of a right-aligned cell, not the right: §5 pads cells on the right
   because its columns are left-set, which puts the space on the far side of a
   figure and butts the figure itself against the column before it. */
/* and the table SIZES TO ITS FIGURES rather than to the window. §5's .tbl is
   width:100%, which is right for the two-column key table it was written for
   and wrong here: in a cut that fills a 1280px window it throws six columns
   the width of the page apart, and a sum you have to track your eye across
   is a sum nobody checks. §14.7 already refuses the line breaks, so natural
   width is exact — and the .scroll-x its page wraps it in still fires when
   that natural width is wider than the cut. */
.tbl--split{width:auto;margin-top:var(--s-3)}
.tbl--split .num{text-align:right;padding-left:var(--s-4);padding-right:0}
/* the sum is ruled off ABOVE, the way a column of figures is totalled on
   paper. Not bolded — there is no bold in this system — and not hued: it
   is told apart by the rule and by the word "total" in its first cell. */
.tbl--split .total td{
  border-top:1px solid var(--aperture-ink-2);border-bottom:0;
  color:var(--aperture-ink);
}

/* ── 15.3 THE CASH-OUT CONTROL ───────────────────────────────────────
   An amount and one button, on one line. It is not §12.5's .acts, because
   .acts is a row of actions and this is a field with its action attached;
   putting the field in .acts would give it .acts' 24px top margin and lose
   the baseline the two share. */
.cashout{display:flex;flex-wrap:wrap;align-items:flex-end;gap:var(--s-3);margin-top:var(--s-4)}
.cashout .field{margin-bottom:0;max-width:20ch;flex:0 1 20ch}
/* §4's .btn is width:100%, because it was written for .aperture--cta where
   the cut IS the button. §14.7 scoped a fix to .acts; this is the same
   fix for the one control on this page that sits beside a field instead
   of in an action row. */
.cashout .btn:not(.btn--cut):not(.btn--text){width:auto}

@media (max-width:560px){
  /* the field takes the full width and the button follows it, rather than
     the two sharing a line 160px wide each. */
  .cashout{align-items:stretch}
  .cashout .field{flex:1 1 100%;max-width:none}
}

/* ═════════════════════════════════════════════════════════════════════
   ── 16. THE DEAL — SIX COMMITMENTS AS SIX CLAUSES ────────────────────
   Used by sellers.html. FLOOD surface (README §8.2 as amended: flood for
   pages about the product), so there is no surface-app.css here and no
   data-surface attribute.

   WHY THIS SECTION IS FIVE DECLARATIONS LONG.
   The seller page is the one page that was already written in this
   direction's grammar before the direction existed: six numbered
   commitments, S1–S6, each one a promise the company can be held to. So
   it is carried by §2's clause list unchanged — the clause number is the
   sequence, the S-tag is the marginal docket label (§7's .clause__margin,
   the same slot "The problem" and "Questions" take on the homepage), and
   the terms need no container, no card and no grid of their own. What was
   genuinely missing is below, and nothing else was added.

   THE ONE DECISION WORTH ARGUING WITH: .clause--term, NOT .clause--wide.
   README §10.4 says a clause the frozen copy makes too long for three
   lines takes the --wide treatment. Every one of the six terms is 55–72
   words and qualifies on measure. But --wide does two things at once: it
   opens the measure to 64ch AND lifts the whole paragraph to full ink at
   --wght-med, which is the right trade for a single emphasised passage
   and the wrong one for six consecutive ones. Two reasons it is wrong
   here, and the second is the load-bearing one:

     1. Six paragraphs of full-ink medium in a row is ~400 words with no
        body voice left to fall back to, and the page stops having a
        hierarchy at exactly the point a seller starts reading closely.
     2. EVERY term carries run-in emphasis in the frozen copy — "20%
        platform fee", "prospective only", "your IP", "You can never be
        required to run a skill at a loss", "you are not on the hook for
        failures of our infrastructure". §2's .clause__t b lifts a run-in
        from --ink-86 to --ink AND from 100 to 112 on the width axis. Under
        --wide the paragraph is already at --ink and --wght-med, so the
        run-in degrades to width alone and the strongest sentences on the
        most load-bearing page on the site half-disappear.

   So --term takes §10.4's measure and declines its voice. The emphasis the
   copy asks for is the emphasis it gets. It is used on eight clauses here —
   the six terms plus the hero paragraph and the pitch lede, which carry six
   run-ins between them for the same reason. --wide survives on this page
   exactly once, on the honest note, which is one emphasised block with a
   single opening run-in and is set identically on how-it-works.html.
   ═════════════════════════════════════════════════════════════════════ */

/* The long clause that keeps the body voice. One declaration, and it is
   only a measure — see the argument above. */
.clause--term .clause__t{max-width:64ch}

/* THE HEADING INSIDE A CLAUSE. Six commitments are a head plus a body, and
   so are the pitch and the closing, so the shape is a system object rather
   than nine inline styles. It introduces no size: it inherits 17px from
   .clause__t and is told from the body by the WIDTH AXIS plus opacity,
   which is the whole hierarchy device. This generalises the three
   `<h3 style="font-size:17px;…font-stretch:112%">` inline blocks on
   how-it-works.html; those should collapse onto it next time that page is
   touched, and until then they render identically. */
.clause__h{
  display:block;color:var(--ink);
  font-stretch:var(--stretch-wide);font-weight:var(--wght-med);
  margin-bottom:var(--s-2);
}

/* THE QUIET LINE OF A LOUD CLAUSE. The live h1 sets "One page." at weight
   300 and "The seller deal." at 800 with a gradient fill; the gradient is
   banned here, so the drop is carried the way this direction carries every
   other drop — the lead line falls to --ink-86 and to --wght-text while the
   line that matters keeps .clause--loud's --ink and --wght-med. Same two
   lines, same order, no hue. 34px is large text, so --ink-86 (4.77:1) is
   comfortably past the floor and --ink-60 was not needed. */
.clause__lead{
  display:block;color:var(--ink-86);
  font-stretch:var(--stretch-text);font-weight:var(--wght-text);
}

/* §7's .ruled is a clause list in miniature and is used inside a clause on
   how-it-works, where it is the clause's only child and needs no step off
   anything. Here it follows a sentence that introduces it, so it takes the
   same 16px step §2 gives one paragraph after another. */
.clause__t .ruled{margin-top:var(--s-3)}

/* §12.1's .skill__marks is already "a wrapped row of marks" and is reused
   verbatim for the five headline promises inside the cut. The only thing it
   was never asked to be is a list, and five promises are a list. */
ul.skill__marks{list-style:none}

/* ═════════════════════════════════════════════════════════════════════
   ── 17. THE GUIDES — LONG-FORM PROSE ON THE SHEET ────────────────────
   Used by every guides-*.html. FLOOD surface (README §8.2 as amended:
   flood for pages about the product), so no data-surface attribute and no
   surface-app.css. This section is COMPLETE for the guide template: six
   further guides AND the hub (guides-index.html) are written against it
   and add no CSS of their own. The hub cost §17.7 one refactor and no new
   object — see the note there.

   THE PROBLEM THIS SECTION EXISTS TO SOLVE.
   Every other page in this direction is a set of short claims. A guide is
   1,000 words of running argument, which is the one shape the composition
   has never had to hold. Three questions had to be answered, and all three
   were answered by REFUSING to invent, because the whole risk of a
   long-form page in a system this narrow is that it quietly grows a second
   typography.

   1. DOES THE PROSE SIT ON THE SHEET, OR INSIDE A LONG CUT?
      On the sheet. A cut is "the thing Sealed actually shows you" (README
      §8.4) — a run, a price, a catalogue, an action. An essay is the
      company ARGUING, which is material, not aperture. Setting a guide in
      one long window would make the aperture 90% of the page and destroy
      the removal test that the direction is built on: take the flood away
      and there must be no page left. So a guide is almost entirely sheet,
      and it earns exactly TWO cuts, both at the end: the other guides
      (a catalogue, so §11's argument applies verbatim) and the one action.
      That is the same ending index.html has, which is why a guide reads as
      the same site despite being four times as long.

   2. WHAT IS THE MEASURE?
      64ch. No new number: README §3 already sets clause text at 54ch and
      wide clauses at 64ch, and §16 took 64ch for the seller terms for
      exactly this reason — a paragraph the frozen copy makes too long for
      three lines opens the measure and keeps the body voice. A guide is
      that case, repeated forty times. Body copy stays --ink-86 (4.77:1),
      which is the direction's stated cost (README §9) and is not re-opened
      here.

   3. HOW IS AN h2 MARKED WITHOUT A FIFTH TYPE SIZE?
      By §16's .clause__h — 17px, width axis 112, --wght-med, full ink —
      plus the 96px clause pitch above it, plus A QUIET NUMBER IN THE
      NUMBER COLUMN. And the number is the decision worth arguing with:

      A guide CANNOT be a clause list. A clause is a claim a seller can
      hold the company to, set at 17px/112/800; forty paragraphs of
      running prose are not forty claims, and numbering them at that rank
      would be absurd — README §8.3 says as much. But leaving the number
      column empty for a 1,000-word page throws away the only structural
      device the page has, and the guide stops looking like the site.

      So the column carries a SECTION INDEX rather than a clause number,
      and it is set at a visibly lower rank: 13px Departure Mono at
      --ink-86, which is §7's `.ruled .n` exactly — the system's existing
      "index in the number column" object, already on the sheet on
      how-it-works.html and sellers.html, so this adds no new exception to
      README §10.7. A reader sees at a glance that these are locators, not
      claims. The manifesto voice is not borrowed.

      THE RULE FOR THE SIX AGENTS, AND IT IS MECHANICAL: every <h2> in the
      source becomes one numbered leaf, in document order, 01..0N. The
      section count equals the source's h2 count. Nothing else is numbered.

   4. WHAT DOES A .callout BECOME?
      Not a cut. A callout on these pages is the company raising its voice
      mid-argument ("Honest note. The numbers on this page are
      illustrative…") — an aside, not a thing being shown, so §8.4 refuses
      it an aperture. It becomes .aside: the --wide voice (§2) between two
      1px --sheet-deep rules, in the text column, WITH THE NUMBER COLUMN
      LEFT EMPTY. The empty column is the whole marking: on a page where
      every section is numbered, the block without a number is visibly not
      a section. No box, no radius, no hue, no fifth size.

   5. NO PULL-QUOTE. Not one of the seven source guides contains a
      blockquote, so a pull-quote here would be a component invented for a
      page that does not want it. If a guide ever grows one, it is .aside
      without the run-in, and it should be added here rather than inline.

   Colour discipline is §11's and §16's: everything on the sheet through
   --ink/--ink-86/--ink-60, everything inside a cut through --aperture-*,
   no literal anywhere, no font-variation-settings anywhere.
   ═════════════════════════════════════════════════════════════════════ */

/* ── 17.1 THE TITLE ──────────────────────────────────────────────────
   The h1 is §2's .clause--loud, unchanged, minus the number: a document's
   title is not section 00. The one thing it needs is a wider measure —
   .clause--loud is cut to 22ch for a 40-character manifesto line, and the
   guide h1s are frozen SEO titles of 55–66 characters, which at 22ch fall
   to four ragged lines. 26ch holds the longest of the seven ("Skills vs
   MCP tools vs prompts: how AI capabilities get sold today") in three. */
.clause--title .clause__t{max-width:26ch}

/* ── 17.2 THE STANDFIRST ─────────────────────────────────────────────
   One sentence of orientation under the title, and the source sets it
   larger than body copy. There is no fifth size, so it takes the width
   axis instead: this is §2's --wide voice — 64ch at full ink and
   --wght-med — and it is the one place on a guide that uses it, so the
   emphasis still means something when the prose below stays at --ink-86.
   It carries no number for the same reason the title does not, so the
   grid collapses to the text column alone. */
.clause--stand{grid-template-columns:minmax(0,1fr)}
.clause--stand .clause__t{
  max-width:64ch;color:var(--ink);
  font-stretch:var(--stretch-text);font-weight:var(--wght-med);
}

/* ── 17.3 THE LEAF — ONE h2 AND ITS PROSE ────────────────────────────
   A guide section. It is §2's .clause with two things changed and nothing
   added: the number drops from a claim's rank to a locator's, and the
   measure opens to 64ch. Everything else — the grid, the 96px pitch, the
   marginal label, the 900px and 560px folds — comes from §2 and §9
   untouched, which is precisely why a guide reads as the same document as
   the homepage.

   The index is --ink-86 (4.77:1) and never --ink-60 (3.18:1): it is 13px,
   so it is small text and the 60% step fails outright. Tabular, because
   README §4 says every figure on this site is. */
.clause--leaf .clause__n{
  font-family:var(--font-mono);font-size:var(--t-13);line-height:var(--lh-13);
  letter-spacing:var(--ls-mono);color:var(--ink-86);
  font-stretch:var(--stretch-text);font-weight:var(--wght-text);
  /* 13px mono and 17px Archivo do not share a first baseline: the display
     face sits 17px below the top of its line box, the pixel face 13px.
     4px puts the index on the h2's baseline instead of floating above it. */
  padding-top:4px;
}
.clause--leaf .clause__t{max-width:64ch}
/* §16's .clause__h is a head over ONE paragraph and takes an 8px step. A
   guide head opens three or four, so it takes §2's paragraph step instead. */
.clause--leaf .clause__h{margin-bottom:var(--s-3)}

/* ── 17.4 A LIST INSIDE PROSE ────────────────────────────────────────
   §7's .ruled is already the list object on the sheet — ruled entries, no
   bullet glyph, the rule doing the separating. Guides need it twice over:
   as-is where the copy is genuinely enumerated (i / ii / iii, as on
   sellers.html), and with the number column collapsed where the copy is a
   plain bulleted list. In the second case the item's own run-in <b> is the
   label the bullet would otherwise have been — which every one of the
   source lists already provides ("<b>Trying is cheap.</b> A first call
   costs cents."), so no marker had to be invented for them. */
.ruled--plain li{display:block;max-width:64ch}
/* §16 gives .ruled its step DOWN from the sentence that introduces it;
   this is the step back UP into the paragraph that follows it. */
.clause__t .ruled+p{margin-top:var(--s-3)}

/* ── 17.5 EMPHASIS INSIDE PROSE ──────────────────────────────────────
   §2 already handles the run-in <b>: full ink plus the width axis. <em> is
   the other emphasis the frozen copy uses ("earns more <em>every month</em>
   than…") and it must not become a second <b>, so it keeps its italic —
   synthesised, since the loaded Archivo has no italic axis — and takes the
   opacity step alone. Two emphases, two mechanisms, neither borrowed. */
.clause__t em{font-style:italic;color:var(--ink)}

/* ── 17.6 THE ASIDE — WHAT A .callout BECOMES ────────────────────────
   The --wide voice between two rules, in the text column, with the number
   column deliberately EMPTY. See the banner, §4. The rules are 1px
   --sheet-deep — 1.72:1, a divider rather than an indicator, which is what
   §7's .ruled already uses and what 1.4.11 does not govern. */
.aside{
  display:grid;grid-template-columns:var(--col-n) minmax(0,1fr);
  align-items:start;padding-block:var(--s-3) var(--s-4);
}
.aside__t{
  grid-column:2;max-width:64ch;padding-block:var(--s-4);
  border-top:var(--edge) solid var(--sheet-deep);
  border-bottom:var(--edge) solid var(--sheet-deep);
  font-size:var(--t-17);line-height:var(--lh-17);letter-spacing:var(--ls-17);
  color:var(--ink);
  font-stretch:var(--stretch-text);font-weight:var(--wght-med);
}
.aside__t p+p{margin-top:var(--s-3)}
/* the block is already at --ink and --wght-med, so its opening run-in has
   only the width axis left — the degradation system.css §16 refuses for six
   consecutive terms and accepts for a single emphasised block with one
   run-in. This is that case, set identically to the honest note on
   sellers.html and how-it-works.html. <b> would otherwise compute `bolder`
   against --wght-med and reintroduce a weight the system does not have. */
.aside__t b,.aside__t strong{font-weight:var(--wght-med);font-stretch:var(--stretch-wide)}
.aside__t a{color:var(--ink);border-bottom:var(--edge) solid var(--ink-60)}
.aside__t a:hover{border-bottom-color:var(--ink)}

/* ── 17.7 THE GUIDE CATALOGUE ────────────────────────────────────────
   Links to the rest of the cluster. This is a catalogue, so §11's
   argument applies without restatement: ONE cut with the entries ruled
   inside it, never six cuts, because six cuts are six cards and this
   direction deleted the card. It is §5's .rows on §11's hover.

   The <li> wrapper is why the rules are re-declared. §5 zeroes the last
   row's rule with .row:last-child — with each .row wrapped in its own
   <li>, EVERY row is a last child and the whole list loses its rules. The
   pair below moves that job to the list item, where it belongs. */
.rows--guides{list-style:none}
.rows--guides .row{
  border-bottom:var(--edge) solid var(--aperture-rule);
  align-items:baseline;padding-block:var(--s-3);
  /* the rule and the hover run 8px past the text on both sides, so an
     entry reads as a full-width row in the cut rather than as a line of
     type that happens to have a rule under it — §11's ledger, exactly. */
  margin-inline:calc(-1 * var(--s-2));padding-inline:var(--s-2);
  transition:background var(--t-link) linear;
}
.rows--guides li:last-child .row{border-bottom:0}
.rows--guides a.row:hover{background:var(--aperture-hi)}
/* ONE column on the seven article pages: their source rows carry a title
   and nothing else, and adding a "Read →" affordance would be putting a
   word on the page that the frozen copy does not contain. The hub keeps
   §5's two columns, because ITS source rows do carry a second cell. */
.rows--guides .row--guide{grid-template-columns:minmax(0,1fr)}
/* §9 folds .row to one column at 560, which turns the hub's right-hand cell
   into a full-width grid item — and a .stamp is an inline-flex box, so it
   stretched into a 327px-wide rectangle with two words in it. A stamp is a
   mark pressed onto a thing; it is exactly as wide as what it says. */
.rows--guides .row .stamp{justify-self:start}
/* the entry is the whole row here, so the name is not a link inside a row
   — it IS the row, and .row__name's colour and width already suit it. */
.rows--guides .row__name{display:block}

/* ═════════════════════════════════════════════════════════════════════
   ── 18. THE DOCUMENT — LEGAL, POLICY AND TRUST PAGES ON STOCK ────────
   Used by all ten of web/app/*.html: legal-terms, legal-privacy,
   legal-refunds, prohibited-skills, security, trust-containment,
   trust-verification, trust-report, offer-ad-hooks, contact.

   APP SURFACE (README §8.2 as amended). Every one of these pages is
   "your money and your things" or the commitments that govern them, so
   every one declares <html lang="en" data-surface="app"> in markup and
   carries surface-app.css. The page is stock from the first paint, the
   toggle is locked, and the only sheet left is the 2px seam at the top of
   the viewport and any withheld field the page genuinely earns.

   THE PROBLEM THIS SECTION EXISTS TO SOLVE, AND WHY §17 DOES NOT SOLVE IT.
   §17 answered long-form prose ON THE SHEET, and three of its four answers
   carry over unchanged. What does not carry over is the composition: a
   guide is material with two cuts earned at the end, and that move is
   unavailable here because the page IS the cut. Everything else in §17 —
   the 64ch measure, the h2 mechanism, the aside, the refusal to invent a
   pull-quote — is reused rather than re-derived, and where a §17 object
   needed a declaration to survive the surface flip it got one and nothing
   more. Four decisions, stated so eight agents do not each make their own.

   1. THE PROSE SITS DIRECTLY ON THE STOCK. NO CUT WRAPS AN ARGUMENT.
      §17.1 refused to set a guide inside one long window because an essay
      is the company ARGUING, which is material rather than aperture. That
      argument is unchanged; only the ground moved. On this surface the
      material IS the stock, so a document is set on the page itself and
      the page's own boundary — the seam, and the window edge — is the cut
      it lives in. Wrapping eight numbered sections in eight .aperture
      hairlines would be eight cards, which is the exact container this
      direction deleted, and wrapping the whole document in one is a
      hairline redrawn 2px inside a hairline that is already there.

      SO WHEN DOES A DOC PAGE GET A CUT? The same test §8.4 applies, with
      the line drawn where it is easiest to hold: A CUT HOLDS EVIDENCE,
      PROSE HOLDS ARGUMENT. A record the reader can go and check — the
      four VERIFIED claims and their links to the report, the support
      form, the two support routes — is a cut. A statement of policy, a
      commitment, a definition, an explanation is prose on stock, however
      important it is. legal-terms.html therefore has ZERO cuts and that
      is correct: a terms page shows you nothing, it tells you things.
      trust-containment.html has two. contact.html is almost entirely
      cuts, because almost everything on it is a thing you use.

      A cut on a doc page sits INSIDE the text column, at the prose
      measure, on §13's .aperture--fills. It does not break out to the
      full content width: on stock a cut is not a different material, it
      is a bounded region, and a region that escapes the measure it
      belongs to reads as a card floating over the document.

   2. WHAT MARKS AN h2 WITHOUT A FIFTH TYPE SIZE.
      §16's .clause__h — 17px, wdth 112, --wght-med, full ink — plus the
      96px clause pitch above it, plus a number in the number column.
      Identical to §17.3 in every respect but one, and the exception is
      the decision worth arguing with:

      THE NUMBER IS SET AT THE CLAUSE RANK (§2's .clause__n, unchanged:
      17px, wdth 112, wght 800, full ink), NOT at §17.3's quiet 13px mono
      locator rank. §17 dropped the rank because it had INVENTED the
      index — forty paragraphs of running prose are not forty claims, and
      numbering them as claims would be absurd. Here the numbering is not
      invented: eight of the ten source pages already ship
      `<h2><span class="num">01</span> The service</h2>`, and a numbered
      section of a terms of service, a refund policy or a prohibited-skill
      policy IS a clause in the strict sense — a claim the company can be
      held to, which is the direction's own definition of the object. This
      is the one page type where the manifesto voice is not borrowed; it
      is native. So the number column does the job it was built for.

      A section whose source h2 carries NO number (offer-ad-hooks.html's
      four, and contact.html's zero) simply omits the .clause__n div and
      leaves the column empty. That is the same marking .aside uses, and
      it is legible for the same reason.

      NO h3 EXISTS anywhere in the ten source pages. If one ever appears
      it becomes a run-in <b> at the head of its paragraph — §2's
      .clause__t b, the system's existing sub-head — and NOT a new class.

   3. THE MEASURE IS 64ch. No new number: §3 sets clause text at 54ch and
      wide clauses at 64ch, §16 took 64ch for the seller terms and §17.3
      for the guides, all for the same reason — frozen copy that cannot
      fit three lines opens the measure and keeps the body voice. Body
      copy stays --ink-86, which on this surface is --aperture-ink-86 and
      measures 11.46:1 rather than the flood's 4.77:1. README §9's "no
      headroom" cost simply does not apply on stock; that is a property of
      the surface and is not something these pages had to buy.

   4. WHAT A .callout / .scope BECOMES: §17.6's .aside, unchanged in
      shape. The --wide voice between two 1px rules, in the text column,
      WITH THE NUMBER COLUMN LEFT EMPTY. On a doc page the marking is
      stronger than it was on a guide, because here the numbers beside it
      are full-rank clause numbers, so a block without one is visibly not
      a clause. No box, no left accent, no radius, no hue, no fifth size.

   WHAT WAS DROPPED FROM THE SOURCE, AND WHY IT IS NOT A COPY CHANGE.
   Every source page carries inline SVG iconography — lock glyphs beside
   claims, a 64px animated gradient orb on trust-containment, numbered
   chips beside steps. All of it is dropped. This direction has no
   icons anywhere on any page, gradients are banned outright, and the orb
   additionally loops (§6: nothing loops). An icon is not a sentence; no
   word of frozen copy is lost with it, and redrawing one in ink opacity
   would be inventing decoration this system does not have. It also keeps
   the hard colour rule trivially true: there is no SVG fill to police.

   Colour discipline is §11's and §17's. No literal hex, rgb, hsl or named
   colour anywhere — the only literal permitted on these pages is the
   <meta name="theme-color" content="#246290"> carried from the sibling
   stock pages. The width axis is addressed through font-stretch and
   font-weight only; there is not one font-variation-settings in this
   section and there must never be (tokens.css §3).
   ═════════════════════════════════════════════════════════════════════ */

/* ── 18.1 THE DOCUMENT HEAD ──────────────────────────────────────────
   Three objects, all of them already in the system:

     the eyebrow      the source's <span class="label"> → .margin-label,
                      out in the masthead margin (§7). Same move as every
                      other eyebrow on the site; the words do not change.
     the title        §17.1's .clause--title — .clause--loud at 34px with
                      no number, opened to 26ch. The longest source h1 is
                      43 characters and falls to two lines there.
     the standfirst   §17.2's .clause--stand for the lede, when the source
                      has one.

   The one thing genuinely missing is the provenance line: "Sealed is
   operated by Lispresso AI · Last updated June 15, 2026", and
   trust-containment's strap, "Enforced by the infrastructure, not by
   instructions." Both are 13px mono in the source and both are 13px mono
   here — which is allowed OUTSIDE a cut on this surface for the reason
   README §10.7's exception list never had to cover: THE PAGE IS THE CUT.
   account.html already sets a top-level .cut-note in Departure Mono for
   the same reason. It is used for exactly these two lines and for
   anything inside a nested cut; everything else on a doc page is Archivo.

   Small text, so it takes ink at 86% (11.46:1 on stock) and never 60%.
   Tabular, because the line carries a date and §4 says every figure on
   this site is. */
.doc-meta{
  display:block;
  font-family:var(--font-mono);font-size:var(--t-13);line-height:1.7;
  letter-spacing:var(--ls-mono);color:var(--ink-86);
  font-variant-numeric:tabular-nums;max-width:64ch;
}
.doc-meta+.doc-meta,.doc-meta+p,p+.doc-meta{margin-top:var(--s-3)}
/* the strap is a CLAIM rather than provenance, so it takes full ink. It is
   the same object at a different rank, not a second object: a page may
   carry one of each and they must read as one block. */
.doc-meta--claim{color:var(--ink)}
.doc-meta a{color:var(--ink);border-bottom:var(--edge) solid var(--ink-60)}
.doc-meta a:hover{border-bottom-color:var(--ink)}

/* ── 18.2 THE NUMBERED SECTION ───────────────────────────────────────
   §2's .clause with two declarations and nothing added — the same
   economy §17.3 kept. The number stays at clause rank (see the banner,
   §2); the measure opens to 64ch; the h2 takes §2's paragraph step
   rather than §16's tighter one, because a doc head opens three or four
   paragraphs and not one.

   .clause__t is placed EXPLICITLY in column 2. §2 leaves it to auto
   placement, which is fine while a .clause__n always precedes it and
   silently wrong the moment one does not: an unnumbered section's text
   would be placed in the 72px number column and crushed. Two of the ten
   pages have unnumbered sections, so the placement is declared rather
   than depended on. */
.clause--sec .clause__t{grid-column:2;max-width:64ch}
.clause--sec .clause__h{margin-bottom:var(--s-3)}
/* §7's .ruled cuts its own text cell to --measure (54ch), which is right
   inside a 54ch clause and narrow inside a 64ch one. The parent column is
   already the measure, so the cell gives its own up. */
.clause--sec .ruled .t{max-width:none}

/* ── 18.3 RULES ON STOCK — the one thing §17's objects cannot inherit ──
   THIS IS THE DECLARATION THE WHOLE SECTION TURNS ON, so it is worth
   stating why it is needed rather than leaving it to look like a tweak.

   surface-app.css remaps --sheet-deep to --aperture on this surface,
   which is correct for its intended job: --sheet-deep is the DEBOSSED LIP
   of a cut and the counterseal fold, and on stock there is no sheet left
   to deboss. But three objects borrow it as a HAIRLINE RULE rather than
   as an edge — §7's .ruled, §12.2's .deflist and §17.6's .aside — and on
   stock those rules composite --aperture on --aperture: 1.00:1, i.e. the
   list, the definition list and the aside silently lose every rule they
   have. .aside loses its entire marking, since the rules ARE the aside.

   The fix is the stock's own divider, --aperture-rule (12%), which is
   what every ruled object already inside a cut uses (§5's .row, §14's
   .setting, §15's .split). It is a DIVIDER, which 1.4.11 does not govern,
   and it is the same relationship to its ground that --sheet-deep has to
   the sheet. Scoped to [data-surface="app"] so the seven flood guides and
   sellers.html are untouched; account.html, account-earnings.html and
   signin.html use none of these three objects, so nothing already
   reviewed moves either. */
[data-surface="app"] .ruled li{border-top-color:var(--aperture-rule)}
[data-surface="app"] .ruled li:last-child{border-bottom-color:var(--aperture-rule)}
[data-surface="app"] .aside__t{
  border-top-color:var(--aperture-rule);
  border-bottom-color:var(--aperture-rule);
}
[data-surface="app"] .deflist dt,
[data-surface="app"] .deflist dd{border-top-color:var(--aperture-rule)}

/* ── 18.4 A TERM AND ITS EXPLANATION ─────────────────────────────────
   The single most common shape in the ten sources, and it appears there
   as four different components: 21 policy cards, 4 claim rows, 3 privacy
   rows, 4 numbered steps. Every one of them is the same object in the
   markup — a <b> and a <p> — and every one of them becomes §17.4's
   .ruled--plain, where THE ITEM'S OWN RUN-IN IS THE LABEL THE BULLET
   WOULD OTHERWISE HAVE BEEN. That is not a compromise; it is the reason
   §17.4 exists, and it collapses four card grids into one ruled list
   without touching a word.

   No two-column variant, and the refusal is deliberate: prohibited-skills
   has 21 entries and a 2-up grid of them is a grid of cards again. A
   policy list is a list.

   A NUMBERED list uses the same object as an <ol> and numbers itself, so
   the ordinal is never typed twice and can never drift from the markup.
   The <li> must wrap its content in <div class="t">, because a bare <li>
   with block children would put each child in its own grid cell.

   IT IS A <div>, NOT A <span>. The pattern originally said <span>, and two
   pages were built each way. The content of this wrapper is always a <b>
   AND a <p> — and a <p> is flow content, which is not permitted inside a
   <span>. Both render identically (a grid item is blockified either way),
   so the span version failed nothing visibly and would have sat there
   invalid. <div> is the correct element and is now the only one used. */
ol.ruled--auto{counter-reset:ruled}
ol.ruled--auto>li{counter-increment:ruled}
ol.ruled--auto>li::before{
  content:counter(ruled,decimal-leading-zero);
  font-family:var(--font-mono);font-size:var(--t-13);line-height:var(--lh-13);
  letter-spacing:var(--ls-mono);color:var(--ink-86);
  font-variant-numeric:tabular-nums;
  /* 13px mono and 17px Archivo do not share a first baseline — §17.3's
     4px, for §17.3's reason. */
  padding-top:4px;
}

/* ── 18.5 SMALL PARTS ────────────────────────────────────────────────  */
/* THE BACK-LINK. The source pages carry a .crumb rule in their stylesheet
   and none of the ten actually renders one, so this exists for the page
   that grows one rather than for a page that has one today. It is a
   13px mono link with the system's 1px underline, sitting after the last
   section and before the counterseal — a locator, not an action, so it is
   never a .btn. Use it ONLY where the source has a back or crumb
   affordance; do not invent the words. */
.doc-back{
  display:inline-block;margin-top:var(--s-6);min-height:24px;
  font-family:var(--font-mono);font-size:var(--t-13);letter-spacing:var(--ls-mono);
  color:var(--ink);border-bottom:var(--edge) solid var(--ink-60);
  transition:border-color var(--t-link) linear;
}
.doc-back:hover{border-bottom-color:var(--ink)}

/* THE FOOTER LINK ROW. Every source footer sets its nav as a horizontal
   row rather than the stacked column §4's .counterseal grew for the
   marketing pages, and the copy is frozen, so the row is declared instead
   of the links being re-ordered into a stack. .flink is unchanged.

   The grid takes a two-column variant with it. §4's three-column
   2fr/1.4fr/1fr was sized for the marketing footer's three blocks; a doc
   footer has two, so the third track was dead space AND the link row was
   squeezed to 313px at 1280 and wrapped its last link onto a line of its
   own. Two equal columns fit six links on one line at 1280 and fold to
   one column at 900 on §9's existing rule. */
.cs-links{display:flex;flex-wrap:wrap;gap:var(--s-2) var(--s-4);align-items:baseline}
.counterseal__grid--doc{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
/* …AND IT HAS TO UNDO ITSELF AT 560. §9 folds .counterseal__grid to one
   column there, but that rule and this one are both a single class, a media
   query adds no specificity, and this section is 1500 lines LATER in the
   file — so the two-column doc grid was beating §9's fold and the footer
   stayed two columns at 375px, squeezing the brand line and the link row into
   ~150px each. The fold has to be restated at the same specificity, after.
   (900 needs nothing: §9 sets 1fr 1fr there, which is what this already is.) */
@media (max-width:560px){
  .counterseal__grid--doc{grid-template-columns:minmax(0,1fr)}
}

/* A cut on a doc page is placed inside .clause__t, which sets 17px and the
   sheet's body colour. .aperture already resets the family and size; this
   resets the two margins that assume a cut sits in the content column
   directly rather than inside a paragraph flow. */
.clause__t .aperture{margin-block:var(--s-4) var(--s-3)}
.clause__t .aperture:last-child{margin-bottom:0}

/* ── 18.6 A CLAIM LIST INSIDE A CUT ──────────────────────────────────
   The one place on these ten pages where a list is EVIDENCE rather than
   argument: four containment claims, each carrying a mark that links to
   the report it was verified in. So it is §5's .rows inside a cut, and it
   is two declarations rather than a component — a claim is one column
   (the name with its mark, then the sentence of evidence under it), where
   §5's default is a name against a trailing figure and there is no figure
   here. Everything else — the 12% rule between entries, the 15px name at
   full aperture ink, the 13px note at --aperture-ink-2 — is §5 untouched.

   THE MARK IS §5's .stamp, NOT A NEW CHIP AND NOT A HUE. The source draws
   VERIFIED in green on a green field; semantic colour may only ever be an
   edge plus a word (README §4), and "verified" is not success, warning or
   error in any case. A stamp is mono, upper-case, 1px edge, radius 0 —
   which is what a verification mark on a document physically is. */
.rows--claims .row{grid-template-columns:minmax(0,1fr);row-gap:var(--s-1)}
.rows--claims .row__name{display:block}
/* §12.1 gave a.stamp--sheet a hover; a stamp INSIDE a cut never got one,
   and every stamp on a trust page is a link to the evidence. */
a.stamp{transition:border-color var(--t-link) linear}
a.stamp:hover{border-color:var(--aperture-ink)}

/* ── 18.7 THE DOCUMENT'S OWN ACTION ROW ──────────────────────────────
   The source's .ctarow: the links that close a trust page, which belong
   to the document rather than to its last section. Same grid as .aside
   and for the same reason — it lines up with the prose above it and
   leaves the number column empty, so it is visibly not a clause. It holds
   §12.5's .acts unchanged.

   It is NOT an .aperture--cta. These are two peer links to sibling pages,
   not the page's one action; a 64px cut here would promise a transaction
   the page does not have. A doc page uses .aperture--cta only where the
   source's action really is the one action (offer-ad-hooks.html). */
.doc-acts{
  display:grid;grid-template-columns:var(--col-n) minmax(0,1fr);
  align-items:start;padding-block:var(--s-4) var(--s-6);
}
.doc-acts .acts{grid-column:2;margin-top:0}

@media (max-width:560px){
  /* §9 drops the number column to 48px; .aside and .doc-acts follow it
     automatically because both read --col-n. Nothing else on a doc page
     has a fixed column, so there is no second fold to declare. */
  .clause--sec .clause__t{grid-column:2}
}

/* ═════════════════════════════════════════════════════════════════════
   ── 19. THE WALLET AND THE PUBLISH FORM — THE LAST TWO APP ROUTES ─────
   Used by wallet.html (viewWallet / viewWalletFund) and publish.html
   (viewPublish). APP SURFACE (README §8.2 as amended): your money and
   your things, so both declare <html lang="en" data-surface="app"> in
   markup and carry surface-app.css. Every cut is §13's .aperture--fills;
   the only sheet left is the 2px seam and the withheld field.

   THIS SECTION IS SHORT ON PURPOSE, AND THE SHORTNESS IS THE ARGUMENT.
   Both routes are made almost entirely of objects §13–§15 already own:
   the balance is §5's .receipt__fig in §14.2's .tally, the usage ledger is
   §5's .tbl in a .scroll-x, the cap and auto-reload are §14.4's .setting,
   the money rules are §18.6's .rows--claims, the top-up ledger and the
   80/20 split are §15.1's .split of .receipt__lines, the card marks and
   the seller's three promises are §5 .stamps in §16's ul.skill__marks,
   and the fund flow is §13.1's .stages — because paying for a top-up is
   genuinely one object in a few positions, exactly as signing in and
   getting paid were. Seven objects were missing and all seven are below.

   1. THE TOP-UP AMOUNT PICKER IS §14.2's .flow, NOT A NEW CARD.
      viewWalletFund offers $5 / $20 / $50 / custom as a radiogroup, and a
      chosen amount of money told apart from three unchosen ones is the
      exact problem .flow already solves: a 2px top rule at --aperture-ink-2
      that goes to full ink when it is the one that counts, a mono tabular
      figure under it, and a word under that. So the picker IS .flows with
      a radio in each cell. The radio is left visible rather than replaced
      by a drawn "face": it is the state, it is 16px and square at radius
      0 like everything else, and it means the selection survives on a
      browser without :has(). The run estimate beside each amount is the
      source's own Math.floor(amount / 0.14) and is not a new figure.

   2. THE CUSTOM AMOUNT DISCLOSES IN CSS, NOT IN SCRIPT. The source hides
      the custom field until the custom radio is checked. :has() does that
      with two declarations and no JS, so the preview behaves rather than
      being drawn in two positions — and where :has() is unsupported the
      field is simply always visible, which is the safe failure.

   3. .editline IS §15.3's .cashout, GENERALISED. "A field with its action
      attached, sharing a baseline" is what the daily-cap editor is and
      what the cash-out control was; .cashout named itself after its one
      call site. The two should collapse the next time either page is
      touched — this is the same debt §14.7 recorded for .cut-note, kept
      visible rather than paid quietly on a reviewed page.

   4. THE SCHEMA EDITOR IS §5's .rows. Field, buyer-facing description,
      and the control that removes the pair — three columns of one row,
      ruled on the 12% divider like every other row in a cut. It is not a
      table: a table is a record you read, and this is a form you fill.

   5. THE ATTESTATION IS §6's .choice WITH THE DETAIL LINE §6 LACKS.
      Six checkboxes, each a claim plus the sentence that defines it —
      §14.4's .setting__t voice (15px Archivo label, 13px note under it)
      attached to a checkbox rather than to a value and a button.

   6. THE BODY SLOT — AND IT IS THE WHOLE REASON publish.html EXISTS.
      §13.3's key slot is a fixed position that holds the sheet's own
      material until the credential arrives, and then shows it ONCE. The
      publish form is that mechanism run backwards, which is why it gets
      the same treatment and not a new one: the thing you paste is the one
      thing this system will never show you again. So the body has its own
      cut, and inside it a slot in a fixed position that has exactly TWO
      drawn positions — the empty textarea you type into, and the withheld
      field that replaces it at the same size the moment the skill is
      published. There is no third position, because a filled one cannot be
      drawn: no page in this direction may contain a skill body, a sample
      body, or a body-shaped placeholder, in markup, comments or
      attributes. The rectangle carries no caption (§7 is absolute); the
      cut's foot states the product fact — "No API returns this text — not
      to buyers, not to you" — and never points at the shape.

   7. .field--wide. §6 cuts a field to a 44ch measure, which is right for
      an email and an amount and wrong for a 200-character description and
      for the body. One declaration, no new component.

   Nothing here may carry a hex value: two of the nine colourways are
   LIGHT with dark ink, and the stock is near-black in all nine. Everything
   inside a cut goes through --aperture-*; semantic hue stays an edge plus
   a word. The width axis is addressed through font-stretch and
   font-weight only — there is no font-variation-settings in this section
   and there must never be (tokens.css §3).
   ═════════════════════════════════════════════════════════════════════ */

/* ── 19.1 THE TOP-UP AMOUNT PICKER ───────────────────────────────────
   Three declarations on top of §14.2's .flow. The 2px top rule, the mono
   figure and the label under it are all inherited; only "this is the one
   selected" is new, and it is carried by the rule going to full ink —
   never by a hue, because a chosen amount is not a success. */
.amount{display:block;cursor:pointer}
.amount .radio{margin-top:0}
.amount:has(.radio:checked){border-top-color:var(--aperture-ink)}

/* the custom amount, disclosed by the radio beside it and nothing else */
.fund__custom{display:none}
.amounts:has(.amount--custom .radio:checked)+.fund__custom{display:block}

/* ── 19.2 A FIELD WITH ITS ACTION ATTACHED ───────────────────────────
   §15.3's .cashout under a name that is not one page's noun. See the
   banner, §3: when either page is next touched these collapse into one. */
.editline{display:flex;flex-wrap:wrap;align-items:flex-end;gap:var(--s-3);margin-top:var(--s-3)}
.editline .field{margin-bottom:0;max-width:20ch;flex:0 1 20ch}
.editline .btn:not(.btn--cut):not(.btn--text){width:auto}

/* ── 19.3 THE INPUT SCHEMA EDITOR ────────────────────────────────────
   §5's .rows, three columns. The header row is 13px mono at --aperture-ink-2,
   which is what a column head is everywhere else in a cut (§5's .tbl th). */
.rows--schema .row{
  grid-template-columns:minmax(0,18ch) minmax(0,1fr) auto;
  column-gap:var(--s-3);align-items:center;padding-block:var(--s-2);
}
.rows--schema .row--hd{
  font-family:var(--font-mono);font-size:var(--t-13);letter-spacing:var(--ls-mono);
  color:var(--aperture-ink-2);padding-block:0 var(--s-1);
}
/* §6 cuts an .input to the width of its .field; here the cell is the measure */
.rows--schema .input{max-width:none}
.rows--schema .btn--text{min-height:32px}

/* ── 19.4 THE SELLER ATTESTATION ─────────────────────────────────────
   §6's .choice, plus the definition line §6 has no slot for. The label
   takes §14.4's .setting__t voice so a claim reads as a claim and the
   sentence under it reads as its definition. */
.attest{display:grid;gap:var(--s-4);margin-top:var(--s-3)}
.attest .choice{margin-bottom:0;align-items:flex-start}
.attest__t b{
  display:block;font-family:var(--font-display);font-size:15px;line-height:1.55;
  color:var(--aperture-ink);font-weight:400;
  font-stretch:var(--stretch-wide);font-weight:var(--wght-med);
}
.attest__t span{
  display:block;font-family:var(--font-display);font-size:var(--t-13);line-height:1.6;
  color:var(--aperture-ink-2);margin-top:2px;max-width:64ch;
}

/* ── 19.5 THE BODY SLOT ──────────────────────────────────────────────
   §13.3's key slot, run backwards. Fixed position, ruled off the block
   above it, two drawn positions and no third — see the banner, §6. The
   withheld field takes the height of the textarea it replaces, so the
   rectangle is literally the shape of the box you typed into. */
.bodyslot{margin-top:var(--s-4);padding-top:var(--s-4);border-top:1px solid var(--aperture-rule)}
.bodyslot__hd{
  display:block;font-family:var(--font-mono);font-size:var(--t-13);
  letter-spacing:var(--ls-mono);line-height:1.7;color:var(--aperture-ink);
  margin-bottom:var(--s-3);max-width:62ch;
}
.bodyslot .field{max-width:none;margin-bottom:var(--s-3)}
.bodyslot .withheld{margin-top:0}
.withheld--body{min-height:209px}   /* the box it replaces, measured: 9 rows + padding + edge */

/* ── 19.6 SMALL PARTS ────────────────────────────────────────────────  */
/* a field whose content is not 44ch wide: the 200-character description,
   the body, and the schema rows above. */
.field--wide{max-width:none}
/* §5's .tbl th/td are left-set; a figure column reads right, and §15.2
   already put the gutter on the LEFT of a right-aligned cell for exactly
   this reason. The floors table on publish.html is that table again. */
.tbl--floors{width:auto;margin-top:var(--s-3)}
.tbl--floors .num{text-align:right;padding-left:var(--s-4);padding-right:0}

@media (max-width:560px){
  /* §9 collapses .row to one column; the schema editor follows, and the
     remove control drops under the pair it removes rather than being
     squeezed to a 40px column beside two full-width inputs. */
  .rows--schema .row{grid-template-columns:minmax(0,1fr);row-gap:var(--s-2)}
  .rows--schema .row--hd{display:none}
  .rows--schema .btn--text{justify-self:start}
  /* four amount cells at 375px are 78px wide, which cannot hold "~357 runs". */
  .amounts{grid-template-columns:repeat(2,minmax(0,1fr))}
  /* the field takes the full width and the button follows it — §15.3's
     fold, for the same object under a different name. */
  .editline{align-items:stretch}
  .editline .field{flex:1 1 100%;max-width:none}
}

/* ═════════════════════════════════════════════════════════════════════
   ── 20. THE SETUP CUT AND THE TICKER — THE LANDING'S BUYER DOOR ──────
   Used by index.html only. Two objects.

   20.1 THE SETUP CUT. An aperture whose content is one copyable prompt:
   the line points the buyer's agent at /setup.md and the agent does the
   rest. `.code` already owns the block treatment; `.code--wrap` exists
   because a prompt is read, not scrolled — a one-line pre at 375px is a
   horizontal scrollbar over the exact words we want read whole.

   20.2 THE TICKER. The agent-compatibility roster. THIS IS THE SYSTEM'S
   ONE LOOP. §5 of tokens.css says motion is mechanical and happens once,
   and every other animation still obeys. The exception is deliberate and
   argued here so it cannot spread: the roster is a press ribbon, not an
   attention device — it moves at reading pace (--ticker-dur per cycle),
   pauses under the pointer AND from a real button (2.2.2 wants a mechanism,
   and :hover is not one for a keyboard or a touch screen), and under
   prefers-reduced-motion it stops and WRAPS so every name stays readable;
   never a frozen, half-clipped strip. Names on it are limited to shipped claims or standard-MCP-fair
   ones (see the roster note in index.html). A second loop anywhere on
   the site does not get to cite this one.
   ═════════════════════════════════════════════════════════════════════ */

.code--wrap{white-space:pre-wrap;word-break:break-word}

/* the sheet-ink .link (§6) has no boundary on aperture stock */
.aperture .link{color:var(--aperture-ink);border-bottom-color:var(--aperture-ink-2)}
.aperture .link:hover{border-bottom-color:var(--aperture-ink)}

.promptcut__actions{display:flex;align-items:center;gap:var(--s-3);
  flex-wrap:wrap;margin-top:var(--s-3)}
/* §4's .btn is width:100% for .aperture--cta, where the cut IS the button —
   the same trap §12.5 and the cash-out row already carry this override for.
   Left full-width the button consumes the row, so `align-items:center` and
   the gap are inert and the status can never sit beside it; it also out-shouts
   .aperture--cta, which is meant to be the page's one pressed action. */
.promptcut__actions .btn:not(.btn--cut):not(.btn--text){width:auto}
.promptcut__status{font-family:var(--font-mono);font-size:var(--t-13);
  color:var(--aperture-ink-2)}

.ticker{display:flex;align-items:center;gap:var(--s-3);
  margin-block:var(--s-3) var(--s-6)}
.ticker__lead{flex:none}
.ticker__win{overflow:hidden;flex:1;min-width:0}
.ticker__track{display:flex;width:max-content;
  animation:ticker var(--ticker-dur) linear infinite}
.ticker__set{display:flex;gap:var(--s-3);padding-right:var(--s-3)}
@keyframes ticker{from{transform:translateX(0)}to{transform:translateX(-50%)}}
/* Hover stops it. A visible Pause control was tried and removed by decision
   on 2026-08-23 — the founder judged a second button beside a seven-word
   roster to cost more than it bought. The reduced-motion block below is what
   now carries a reader who cannot hover: it does not merely pause the strip,
   it stops it and wraps every name into a static row. Re-adding a button is a
   product decision, not a repair. */
.ticker:hover .ticker__track{animation-play-state:paused}
/* screen readers get the prose list, not two copies of a moving strip */
.ticker__sr{position:absolute;width:1px;height:1px;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap}
@media (prefers-reduced-motion:reduce){
  /* The wrap has to happen where the STAMPS are. Wrapping .ticker__track
     wraps nothing — with the second set hidden it holds one flex item, and
     .ticker__set is itself a nowrap row, so the names get squeezed and then
     clipped by .ticker__win instead of moving to a second line. The window's
     overflow has to be released for the same reason. */
  .ticker{flex-wrap:wrap;row-gap:var(--s-2)}
  /* full-basis so the lead stops taking ~123px off the top row at 375px:
     the roster gets a whole row to wrap into at every width */
  .ticker__win{overflow:visible;flex-basis:100%}
  .ticker__track{animation:none;width:auto}
  .ticker__set{flex-wrap:wrap;row-gap:var(--s-2);padding-right:0}
  .ticker__set+.ticker__set{display:none}
}

/* ── 21. THE BUYER'S WALLET CARD — A LANDING ILLUSTRATION ────────────
   An aperture illustration of the wallet's money rules. The figures are
   the product's real constants — the $0.10 price floor, the $10.00
   default daily cap — composed into a worked example and LABELLED as
   one in the aperture label. Nothing in it is live data and nothing
   pretends to be; the invented-data landmine in the 2026-08-12 handoff
   is why the label is not optional. One hue throughout: success is full
   ink, no-charge is ink-2, per the no-accent rule. */
.walletcard{max-width:420px}
.walletcard__row{display:flex;justify-content:space-between;align-items:baseline;
  gap:var(--s-3);padding:7px 0;border-top:1px solid var(--aperture-rule);
  font-variant-numeric:tabular-nums}
.walletcard__row--bare{border-top:0;padding-bottom:0}
/* the descendant selector is load-bearing, exactly as on .receipt__fig: this
   is a <p> inside an .aperture, and `.aperture p` (0,1,1) outranks a bare
   class (0,1,0) — left unscoped the balance renders at 15px Archivo, which
   is the same defect §14.7 is the second workaround for. */
.aperture .walletcard__fig{font-family:var(--font-mono);font-size:var(--t-34);line-height:1.2;
  color:var(--aperture-ink);font-variant-numeric:tabular-nums;margin:2px 0 0;max-width:none}
.walletcard__lab{font-size:var(--t-13);color:var(--aperture-ink-2);
  text-transform:uppercase;letter-spacing:var(--ls-13)}
.walletcard__dim{color:var(--aperture-ink-2)}
/* --aperture-edge, not --aperture-rule: this is a bounded gauge, and its
   extent IS the information. The track fill is 1.07:1 on the aperture, so at
   the 12% divider weight the edge composites to ~1.33:1 and the whole track
   disappears — leaving a short white dash floating with nothing to read it
   against. The 40% token is the one tokens.css §aperture sized for a
   component edge (3.33:1); --aperture-rule stays on .walletcard__row, which
   genuinely is a divider. */
.walletcard__meter{height:6px;background:var(--aperture-hi);
  border:1px solid var(--aperture-edge);margin:var(--s-2) 0 4px;position:relative}
.walletcard__meter i{position:absolute;top:0;bottom:0;left:0;width:4%;
  background:var(--aperture-ink)}


/* =====================================================================
   INTAGLIO — THE APP SURFACE  (README §8.2)
   PREVIEW ONLY. This exists to settle one open question by looking at it.

   THE QUESTION
   The Intaglio spec says the flood is for the MARKETING surface only, and that
   the catalogue, docs, account and app "cannot be flood-red" — they run on
   --aperture stock with --aperture-ink type, and sheet survives only as a 1px
   seam at the top of the viewport and as the withheld field. The marketplace
   was built the other way: full flood, one big cut. Both readings are
   defensible, so both are rendered and you pick.

   HOW IT WORKS
   Nothing here restyles a component. Because the whole system is tokenised,
   the inversion is done purely by remapping which stock --sheet and --ink point
   at. Every component inherits the change for free — which is itself evidence
   the token layer is sound.

     manifesto:  --sheet = the field      --ink = light ink on the field
     app:        --sheet = aperture stock --ink = aperture ink

   --sheet-true holds the TRUE sheet colour throughout, so the two places §8.2
   says sheet must still appear — the top seam and the withheld field — keep it.
   ===================================================================== */

[data-surface="app"]{
  /* the sheet becomes the stock. This one line does most of the work. */
  --sheet:var(--aperture);
  --sheet-deep:var(--aperture);
  --sheet-lift:var(--aperture);

  /* type flips to aperture ink at the same three opacities */
  --ink:var(--aperture-ink);
  --ink-86:var(--aperture-ink-86);
  --ink-60:var(--aperture-ink-60);
  --ink-86-flat:var(--aperture-ink-2);
  --ink-60-flat:var(--aperture-ink-2);

  /* THE STOCK IS NEAR-BLACK IN ALL NINE COLOURWAYS, so the app surface is a
     dark page even on the two LIGHT fields. colourways.css sets
     `color-scheme:light` on manila and kraft, which is right for a light
     SHEET and wrong here: on an app page those two rendered a #130E09 ground
     while telling the UA the page was light, so everything CSS does not paint
     itself — scrollbars, the autofill background, select popups, date pickers
     — came back light on near-black. The fields themselves were never wrong
     (the system fills them from --aperture-hi), which is exactly why this is
     easy to miss.

     This block is loaded after colourways.css and matches its specificity, so
     it wins. tokens.css already makes the same declaration for the same
     reason on the flood. */
  color-scheme:dark;
}

/* The grain is a property of the SHEET, not of the stock. On aperture stock the
   flood's texture reads as noise, so it comes off the page and stays only on the
   withheld field, where it is doing semantic work. */
[data-surface="app"] body{
  background-image:none;
}
/* The companion `body::after{content:none}` that used to sit here is gone with
   the overlay it suppressed — system.css no longer paints a second grain layer. */

/* THE SEAM. §8.2: "Intaglio appears in the app only as the 1px seam at the top of
   the viewport and as the withheld field." This is that seam — the edge of
   the sheet the app is cut out of, and the only red left on the page. */
[data-surface="app"] body::before{
  content:"";
  position:fixed;left:0;right:0;top:0;height:2px;
  background-color:var(--sheet-true);
  z-index:var(--z-grain);
  pointer-events:none;
}

/* An aperture is now the same stock as the page, so its debossed/lit edges
   have nothing to describe. It keeps a single hairline so a cut still reads
   as a bounded region rather than dissolving into the page. */
[data-surface="app"] .aperture{
  border:var(--edge) solid var(--aperture-edge);
  background:var(--aperture);
}

/* The one action stays legible as the one action. */
[data-surface="app"] .aperture--cta{
  border-color:var(--aperture-ink-2);
}

/* The withheld field is the second place §8.2 keeps sheet, and the reason is
   semantic rather than decorative: it is the sheet itself, seen through the
   cut. It must NOT invert with the surface. */
[data-surface="app"] .withheld{
  background-color:var(--sheet-true);
  background-image:var(--grain);
}
