/* ==========================================================================
   landing.css — the public front page of simpler.run.

   REBUILT FROM THE GROUND 2026-09-08 (owner, on the 2026-09-06 page: "i see
   it, but it doesnt look good, please do up a new one ground up"). The
   rulings under it are unchanged and this sheet is their second reading:

       THE GROUND IS PAPER. THE SIGN COLOURS ARE THE MARK,
       AND THE MARK IS RATIONED TO WHAT IT MARKS.

   What changed is what the page LEADS with. The 2026-09-06 page put the
   product's map in three flat tones beside the headline — ink, hairline,
   recess — a silhouette that said only whether a corner holds a rent. This
   page puts the app's own island on the app's own plate in the hero: every
   corner that publishes its rent shaded on the red-to-green ramp the app
   paints (app.js RAMP5, cut by the same rank rule), the district-band
   corners hatched in the app's copper, the empty ones in the app's grey, with
   the key beside it. The panel is the one dark object above the fold and it
   is the product, not a decoration.

   The rest is a document: serif headlines, a serif figure on the specimen,
   sans body, and the mono held to what is actually a receipt — instrument
   ids, dates, the stamp. The eyebrows are small sans capitals, not mono.

   The caution identity is whole and still rationed: signal yellow inside
   ISO 3864-4's own tolerance, its contrast black at or under the 0.03 cap,
   the black band, the 45-degree hatch — spent on the wordmark's tile, the
   page's one filled button, the caution blocks, the floor gauges' hatch and
   the withdrawal's tape. tests/test-landing.js recomputes every arm below
   from the hex:

     1. THE GROUND. --paper is the body's ground: a near-neutral (chroma
        0.047, against the band's 0.25 floor) at luminance 0.8963 — over ISO
        3864-4's 0.75 floor for the contrast colour white. Nothing on the
        page is lighter than it. There is no white stock and no second paper.
     2. THE MARK. --sign is hue 40-60deg at luminance 0.45-0.70 (Table 1's
        safety yellow: 0.5754); --hi tops the band at 0.6938 and is spent on
        black only; every black is at or under 0.03. The band — hue 40-60,
        HSL saturation >= 0.60, chroma >= 0.25 — may be painted only by the
        selectors the test grants by name, and the list is short.
     3. THE AXIS. Severity escalates in black and in structure, never in
        hue: caution is a yellow block with a 1px keyline and an open band;
        warning is a 2px keyline and a SOLID black band with the legend
        reversed out in --hi; the withdrawal is hatched tape on the plate.
     4. THE RATION. Black is a legend plate and a keyline, never a ground:
        only an enumerated list of selectors may paint a dark ground, and the
        sign colours are enumerated the same way. The island's plate is on
        that list by review, as the app's map pane is: a data ramp reads
        against a quiet ground and not against paper.
     5. THE RAMP. Five hexes and two greys, the app's own (app.js RAMP5,
        NOVAL_FILL and NOVAL_STROKE composited over the plate, DRAPE_INK),
        spent by the island's tones and its key and by nothing else. They
        are data colours: a band on the drawing is a rank among the own-rent
        corners, and the key says which.

   EVERY RATIO IS ANCHORED TO THE GROUND THE INK ACTUALLY SITS ON, and every
   one was measured before it was typed here. Inks on paper: --ink 16.11,
   --ink-2 10.72, --ink-3 6.57, --rule 3.50. The caution block's ink sits on
   --sign at 10.65, which is why the block may carry body prose.

   Severity is DERIVED in build-landing.js from each fact's own coverage
   against the floor line. It is never assigned here, and never typed.
   ========================================================================== */

:root {
  /* Chrome's Auto Dark Theme repaints a light page that declares no scheme,
     which would repaint the paper every ratio below is measured against.
     "only" is what makes this a refusal and not a preference. */
  color-scheme: only light;

  /* THE GROUND. Warm paper at the sign's own hue (45.0deg against the mark's
     46.6) so the page changes stock and not palette; a near-neutral by both
     of the band's measures (saturation 0.400, chroma 0.047). The one token
     that prints no ratio: it is what the others are measured against. */
  --paper:  #F6F3EA;

  /* THE MARK. The safety yellow, luminance 0.5754 inside Table 1's
     0.45-0.70, spent on the objects that are marks. 10.65:1 under --ink, so
     a caution block can carry a paragraph; 11.04:1 under the plate, which is
     what the hatch and the reversed band are made of. */
  --sign:   #F2C21B;  /*  1.51:1 on --paper — the mark yellow, the favicon's
                         field, the button, the caution block, the hatch */
  /* The brand mark's own yellow, at the top of the band (0.6938), and on
     black only: 1.19:1 on --sign and 1.27:1 on --paper, so on either ground
     it is not a colour at all. The warning band's legend and the tape. */
  --hi:     #FFD60A;  /* 13.13:1 on --plate */

  --ink:    #1C1707;  /* 16.11:1 on --paper — body type; 10.65:1 on --sign */
  --ink-2:  #42360F;  /* 10.72:1 on --paper — secondary; 7.08:1 on --sign */
  --ink-3:  #655526;  /*  6.57:1 on --paper — micro labels, receipts, counts */
  --rule:   #91804E;  /*  3.50:1 on --paper — every hairline, the tiles'
                         keyline, the gauge slot's edge. SC 1.4.11 asks 3:1
                         for a boundary a reader must find. */
  /* A FILM, NOT A SURFACE: the hard cast every object on the paper throws.
     Composited over the ground it prints a ratio against; the law refuses
     any film that names none. */
  --cast: color-mix(in srgb, var(--ink) 14%, transparent);
                      /*  1.34:1 on --paper */

  /* THE PLATE. Two black panels on this page: the island's pane in the
     hero, and the cordon — the withdrawal, taped top and bottom. */
  --plate:  #171308;  /* 16.70:1 on --paper — lum 0.0086, inside the 0.03 cap */
  --p-ink:  #DDD8C9;  /* 13.01:1 on --plate */
  --p-ink-2:#B4AA8A;  /*  7.99:1 on --plate */
  --p-ink-3:#90855C;  /*  5.03:1 on --plate */
  --p-rule: #6A6144;  /*  3.01:1 on --plate */
  --p-sunk: color-mix(in srgb, #000000 28%, transparent);
                      /*  1.04:1 on --plate — the ledger's recess: a hint on
                         top of a 3.01:1 border, recorded and left as it
                         renders */
  --rust:   #E0674A;  /*  5.48:1 on --plate — the struck number */

  /* THE RAMP, the app's own (app.js RAMP5, red to green, dark to light),
     indexed here by RENT BAND: b0 is the cheapest fifth of the own-rent
     corners and b4 the dearest, which is RAMP5 read backwards because rent
     is one of the app's REVERSED metrics (low is the green end). Data
     colours on the plate — never an ink, never a ground for type. Each
     measured against the plate it sits on.
     RE-COPIED 2026-09-10 from app.js:1179, which the concept pass re-derived
     on 2026-09-09. The sheet had held the 2026-09-03 ramp for a week, so the
     hero island — the one dark object above the fold — was shaded in five
     inks the app had stopped painting, and the five key swatches beside it
     decoded a retired ramp. Nothing on this page could tell: clause 400 is
     the only reader that compares the two, and it is the whole reason this
     was found. The ratios below are recomputed against --plate with the
     battery's own lin/lum (tests/test-landing.js:196-202), never carried
     over — the five above them were honest arithmetic about colours the app
     had already retired, which is the failure a stale copy actually looks
     like from the inside. */
  --b0:     #C0EFC8;  /* 14.49:1 on --plate — cheapest */
  --b1:     #A4C47B;  /*  9.50:1 on --plate */
  --b2:     #A4932E;  /*  5.99:1 on --plate */
  --b3:     #A05E00;  /*  3.61:1 on --plate */
  --b4:     #84261C;  /*  2.01:1 on --plate — dearest */
  /* the app's no-value grey and its edge (NOVAL_FILL rgba(61,61,61,.78) and
     NOVAL_STROKE rgba(112,112,112,.9), composited over the plate in sRGB) —
     the app's exact two, so the drawing here and the map behind the door are
     one picture.
     THE DRAPE IS NO LONGER A THIRD (2026-09-10). This block used to say the
     hatch ink was the ramp's own copper, DRAPE_INK = RAMP5[1]. app.js:1200
     deleted DRAPE_INK with the hatch itself on 2026-09-09 ("THE HATCH IS
     GONE, and its ink with it"), and the app now marks a grain-up corner
     with a dashed keyline on the no-value grey (app-map.js:861). So --drape
     is a copy whose source no longer exists, and this page still draws a
     hatch (.island .dl at 459, the 45-degree gradient at 517) for a state
     the map behind the door draws another way. The colour is LEFT where it
     was rather than repointed at the new RAMP5[1]: making the provenance
     true would not make the two pictures agree, and it would hide the
     divergence behind a fresh-looking hex. Whether the landing drops the
     hatch for a dashed edge is an owner call and it is open. No clause in
     tests/ reads --drape, so nothing but this comment is watching it. */
  --noval:  #353431;  /*  1.49:1 on --plate — a corner with no rent to shade */
  --noval-line: #676766;  /*  3.27:1 on --plate — its edge */
  --drape:  #A36400;  /*  3.87:1 on --plate — the district band's hatch, in an
                         ink app.js retired on 2026-09-09; see above */

  --serif: "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua", Georgia, serif;
  /* Only faces whose metrics the ch measures below were taken against. */
  --sans:  "Segoe UI Variable Text", "Segoe UI", system-ui, -apple-system, sans-serif;
  --mono:  "Cascadia Mono", "Cascadia Code", ui-monospace, "SF Mono", "Segoe UI Mono", Menlo, Consolas, monospace;

  /* The sticky bar's floor, declared once: .topbar sets it and html offsets
     every scroll landing by it (SC 2.4.11). 60px is ID-T's --nav-h, and it
     is the 38px badge plus the 11px of air the fleet's rail gives it top and
     bottom; the old 52px was cut for a 20px mark. Still a FLOOR and not a
     height — a stated height on a top-pinned element sends its overflow off
     the top of the screen, where there is no scrollbar (clause 400 S4). */
  --bar: 60px;
  /* The chapter head's floor, as the sum of the tokens it is built from and
     never a px constant; S10 recomputes it from the .hd rule. */
  --sec-h: calc(var(--t-head) * 1.2 + var(--s2) + 2px);

  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px;
  --s5: 22px; --s6: 30px; --s7: 42px; --s8: 64px;
  /* --s9 (96px) went with the four spacing pairs on 2026-09-08: one pair,
     s8 over s8, and nothing on the page reaches for a ninth rung */

  /* The type scale, in the unit the reader controls (SC 1.4.4). It was one
     rung larger than the 2026-09-06 page at every step, because that page was
     set for a sign read at a glance and a document is read. It is one rung
     larger again as of 2026-09-16, for the plainer reason that 11px and 12px
     were too small to read and nobody had said so with a number.

     THE FLOOR MOVED, THE CEILING DID NOT. micro 11 to 12, small 12 to 13,
     body 14 to 16, lede 17 to 18. --t-head and --t-wordmark below are
     UNCHANGED and that is deliberate: --sec-h is derived from --t-head and
     carries every scroll landing in the board through it, and --t-wordmark is
     tied to a 38px badge from another repo, not to any text on this page. A
     raise made for a reader's eyes has no business moving either.

     WHY MICRO STOPPED AT 12 AND NOT 13. The reason below held for one
     afternoon and is now a RECORD rather than a constraint: round three, the
     same day, took the ellipsis off the island key so the ranges wrap instead
     of being cut, and the cell stopped being what caps this rung. See THE
     RANGES WRAP under THE ISLAND. The rung stays at 12 for a plainer reason
     that the cell was hiding — --t-small is 13, and a micro at 13 is not a
     smaller rung, it is the same rung twice. What follows is kept because it
     is the arithmetic that has to be re-taken if the key ever goes back to
     one line, and because the three-digit exposure two paragraphs down is
     still live in the app, which crops the same figures its own way.

     The island key sets five psf ranges in mono in a five-up grid of
     minmax(0, 1fr), and `.island-cap .ramp .rg` USED TO clip them with an
     ellipsis, so a label that outgrew its cell was not a layout fault
     anybody saw — it was published data quietly cut. Rendered and measured
     2026-09-16 by audit-type-boxes.js, which is in this repo precisely so the
     next reader can re-take these rather than believe them: the cell the label
     gets is 79.4px at a 481px viewport, 83.2px at 500, 84.0px at 1001 (the
     narrowest two-column case) and 103.3px from 1280 up.

     The mono advance, read off the rendered box rather than a font table, is
     0.5859em, and the stack resolves to Cascadia Mono here — the same run
     width-probes the whole stack, because document.fonts.check answers true
     for families that are not installed. The en dash the label is built from
     (U+2013, not a hyphen) advances exactly like a digit, which is the only
     reason an eleven-character label can be counted as eleven advances. So
     "14.24–48.98", the widest the register holds today, is 70.9px at 11px,
     77.3px at 12px and 83.8px at 13px. At 12 it clears the worst cell by
     2.1px. At 13 it is 4.4px OVER the 481px cell and clears the 1001px cell by
     two tenths of a pixel, which a scrollbar takes: the media query fires on
     the outer width while the layout gets fifteen pixels less. So the ceiling
     on this rung is not a taste, it is a cell.

     AND THE LABEL IS DATA, NOT A CONSTANT. landing.html rebuilds all five from
     the bands the build derived, so eleven characters is today's register and
     not a bound. A three-digit psf prints "100.00–148.98" — thirteen
     characters, 91.4px at 12px, over every cell below 1280, and over the 481px
     cell at 11px too. That exposure is one the raise INHERITS rather than one
     it creates, but it is written down here because the clearance is 2.1px and
     the register refreshes.

     THE PHONE'S OWN OVERRIDE WAS A SEPARATE, OLDER PROBLEM, and round three
     fixed it the same day this paragraph was written. It is left here as the
     diagnosis that produced the fix. The @media (max-width: 480px) block under
     THE ISLAND held .rg at 0.625rem, and at 340px the cell is 55.2px against a
     64.5px label: the two dearest bands were ALREADY cut before any raise, at
     "9.96–14.1…" and "14.24–48.9…". At 390 the same label got 65.2px and
     cleared by seven tenths of a pixel, which is not clearance, it is a
     coincidence. Worse, the override narrowed the type at the one width where
     the cell is widest: the same block shrinks .island-fig's padding, so at
     480px the label had 83.2px and was set at 10px, and at 481px it had 79.4px
     and was set at 12px. The cell got NARROWER as the viewport widened by a
     pixel. Five mono ranges of eleven characters do not fit a 340px row at any
     size a person can read, so the fix was a different shape for the key and
     not a smaller number — which is what round three built, and the override
     is gone with it. Written down rather than quietly carried. */
  --t-micro: 0.75rem;      /* 12px at a 16px root */
  --t-small: 0.8125rem;    /* 13px */
  --t-body:  1rem;         /* 16px   */
  --t-lede:  1.125rem;     /* 18px   */
  /* the top rung: the board's chapter heads and the register's REACH FIGURE,
     one size (2026-09-08: the chapter head sat at the lede size, the same as
     the tile names under it, and head and tile read as one rank. 2026-09-11,
     the nine item 4: the register's fact names came OFF this rung and the
     figure under them came ON, so the rung is no longer "sub-heading" — it
     carries a heading on one surface and a measurement on the other.)
     --sec-h below is derived from it, and through --sec-h so is every door's
     scroll landing in the board, so an edit made for the FIGURE's sake moves
     the board. Change it for one and re-read the other. */
  --t-head:  1.5rem;       /* 24px   */
  /* The wordmark's own rung, and it is NOT a step of the document scale: it
     is sized to the 38px badge beside it, not to any text on the page. 22px
     is ID-T's figure (web/styles.css --t-xl, used by .sitenav-word) and the
     fleet's two bars are meant to read as the same object. It sits between
     --t-lede and --t-head deliberately; borrowing either would tie the name
     to a rung that moves for a document reason. */
  --t-wordmark: 1.375rem;  /* 22px   */

  /* WHAT THE SCALE ABOVE DOES NOT COVER, named here so a later floor pass
     does not have to rediscover it (2026-09-16):
       - og-card.html, four sizes in literal px: 30 the eyebrow, 96 the
         headline, 27 the lede, 22 the mono stamp. That file is rendered to
         og.png at a FIXED 1200x630 by build-og-card.js, is never served, and
         has no reader whose type setting could apply — it is a picture of
         type, so px is the honest unit and rem would be the bug.
       - app-map.js and basemap/style-dark.json, seven canvas sizes and one
         zoom interpolation. Those are held out on purpose; the reason and
         the cost are written at the head of app-map.js.
       - dist/404.html, generated by build-dist.js, which came ONTO rem on
         2026-09-16 and is therefore covered.
     Everything else that sets type on this surface goes through the rungs
     above, and clause 400 S6 in tests/test-landing.js is what refuses a px
     font-size here — F8 in tests/test-app-facts.js is its app-side twin.
     Neither reads any of the three files listed above, which is exactly why
     they are listed. */

  /* The gauge face: a slot cut into the paper, a keyline that clears 3:1 on
     it so the denominator has a visible end, and an ink fill. */
  --track-h: 8px;
  --track-r: 4px;
  --track-bg: #E8E4D5;                       /* 1.15:1 on --paper — a slot */
  --track-line: var(--rule);                 /* 3.05:1 on --track-bg — the slot's own edge */
  --span-fill:  color-mix(in srgb, var(--ink) 42%, transparent);
                                             /* 2.58:1 on --track-bg — the spread span */
  --track-in: inset 0 0 0 1px var(--track-line);

  --r: 4px;
  --wrap: 1180px;
  --ease: cubic-bezier(.4, 0, .2, 1);
}

/* No night face. A caution mark is the same mark at 3am; the two preferences
   that describe a need rather than a taste — reduced motion and forced
   colours — are honoured at the foot of this file. */

* { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--bar) + var(--s2));
}
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--t-lede);
  line-height: 1.55;
  text-wrap: pretty;
  -webkit-tap-highlight-color: var(--cast);
  -webkit-font-smoothing: antialiased;
}

/* The selection is ink on paper reversed: not the mark yellow, because
   dragging a cursor over a paragraph is not a hazard. */
::selection { background: var(--ink); color: var(--paper); }

.wrap { width: 100%; max-width: var(--wrap); margin: 0 auto; padding: 0 var(--s6); }
@media (max-width: 600px) { .wrap { padding: 0 var(--s4); } }

/* Every section is separated by a hairline, never by a colour block. */
.band { border-top: 1px solid var(--rule); }

/* The small capitals over a block: sans, tracked, third-rung ink. A label,
   never a heading's substitute — the headings are the serif below. */
.eyebrow {
  display: block;
  margin: 0;
  font-family: var(--sans);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-3);
}

a { color: inherit; }

/* One focus ring for every interactive thing on the page (clause 400 S9 holds
   this file to exactly one rule that declares a ring). Ink, not the mark: a
   ring says "you are here", not "danger".

   IT NOW CARRIES ITS OWN GROUND, because on paper it was never the problem.
   Measured 2026-09-16, by walking every focusable thing on the page and
   finding the first opaque ground painted behind each: 184 of them are in the
   tab order, 121 stand on paper where ink is 16.11:1, and 63 stand on --plate
   where it is 1.04:1. Sixty-three and not the five .fam cards the audit named
   — the island's figcaption carries 55 area links and a disclosure summary on
   the same plate, and the close band adds the five fleet cards, the company
   mail link and the credit. A ring at 1.04:1 is not a faint ring, it is no
   ring, and a third of this page's controls had none.

   So the ring keeps its ink and gains a halo: 7px of paper, which fills the
   3px offset gap under the ring and stands 2px clear beyond it. Both edges of
   the ink then sit on paper at 16.11:1, and the paper sits on whatever is
   BEHIND the card, which is the close band's --plate: photographed and counted
   in device pixels on 2026-09-16, the painted run is 4px of paper at 16.70:1,
   4px of ink at 16.11:1 either side, then 6px of paper. The floor if a halo
   ever landed on a card's own lit corner instead is 12.73:1, on --fam-host-h.
   One declaration, two grounds, no new token and no second rule.

   SEVEN AND NOT MORE: .fams sets a 14px gap (the family stamp's own, since
   2026-09-28). At a 7px spread the halo of a focused card stops 7px short of
   its neighbour, so no card can ever wear the light belonging to the one
   beside it.

   WHY THIS SITS HERE AND NOT BESIDE .skip, WHERE IT LIVED UNTIL TODAY. A halo
   costs box-shadow, and box-shadow is one property that several things on this
   page already spend at rest: .go's cast, .jump input's inset, .door,
   .island-fig, .specimen, .dir-sec > .hd. At equal specificity the later rule
   wins, and from its old home below .go this rule would have taken the
   button's cast away for exactly as long as a reader held focus on it.
   Declared up here, above all of them, every resting shadow survives and the
   halo is the thing that yields — and it yields only on paper, where the ink
   ring is already at 16.11:1 and the halo was never the cue. That trade is
   only safe if nothing on the plate spends box-shadow at rest, so the same
   sweep asked: of the 63, not one does. All 63 take the halo.

   THE ISLAND'S MAP IS NOT IN THIS ARGUMENT. The 55 <a> shapes inside the SVG
   each carry tabindex="-1", so they never match :focus-visible at all, and
   box-shadow does not apply to an SVG element in any case. Their ring is
   unchanged. The 55 links in the figcaption BELOW the map are a different set
   and are counted above. */
:focus-visible {
  outline: 2px solid var(--ink); outline-offset: 3px;
  box-shadow: 0 0 0 7px var(--paper);
}

/* --------------------------------------------------------------------------
   Topbar — the name, the mark and the date. Opaque paper, because it is
   sticky and must cover what slides under it; min-height and not height,
   because a fixed height on a sticky element pushes overflow off the top of
   the screen (measured at root 28px on a 390px phone, 2026-08-30).
   -------------------------------------------------------------------------- */
.topbar {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: var(--s4);
  min-height: var(--bar);
  padding: var(--s1) 0;
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
}
.topbar .wrap { display: flex; align-items: center; gap: var(--s4); }
/* THE LOCKUP IS THE FLEET'S, AND THE NUMBERS COME FROM ID-T (2026-09-14).
   simpler.house's global nav is the reference surface — ID-T web/styles.css
   `.sitenav-mark` / `.sitenav-word`, web/landing.tsx `NavRail` — and the
   founder's read of this bar was "unpolished, amateurish, especially the
   space on the top". Three of the four numbers below are copied from there
   rather than chosen here: a 38px badge, a 10px step to the word, and the
   word at the section-heading rung. ID-T's own note on the last one is the
   argument: "a 38px badge beside 16px reads as a caption bolted to a logo;
   22px puts the word's cap-height in the badge's optical range, so the two
   read as one lockup." This page carried a 20px badge beside 17px, which is
   the same mistake one rung smaller.

   THE NAME IS CAPITALISED, on all three surfaces that draw it, because the
   fleet roster spells it that way — ID-T web/family.ts FAMILY: `{ host:
   "simpler.run", name: "Simpler.Run", ground: "#FFD60A", kite: "#000000" }`.
   Clause 414 W1 holds the spelling unbroken and was re-based to match; its
   argument is untouched, since a hand-typed space between </b> and the rest
   is still the one break no stylesheet clause could see.

   WHAT IS NOT COPIED IS THE GROUND. ID-T's rail is #091624 because that IS
   simpler.house's own deepest value; this page is paper, and the ruling here
   is paper ground with yellow as the mark rationed. So the bar stays paper
   and the badge, at 38px, becomes the one piece of colour in it — which is
   the ration spent where it says the most. */
.wordmark {
  display: inline-flex; align-items: center;
  font-size: var(--t-wordmark); letter-spacing: -.012em; color: var(--ink-2);
  font-weight: 600;
}
.wordmark b { color: var(--ink); font-weight: 600; }
/* The mark is favicon.svg — the yellow tile. Its margin, NEVER the row's gap:
   the wordmark is a flex container and ".Run" is an anonymous item in it, so
   a gap would fall between every pair and split the product's name in two.
   That is clause 414 W2, and it is measured rather than trusted.

   NO border-radius HERE. The rule that stood between 2026-09-14 and the same
   afternoon set 9px, reasoning that the file's own rx 24 in a 168 box is only
   5.4px at 38 and so reads as a plain square. Rendered at eight times size and
   put beside the unclipped file, that reasoning was simply wrong twice over:
   5.4px is plainly a rounded tile, and a 9px CSS clip is a 42.6 unit corner
   laid over the file's 24 unit one, so it cuts INSIDE the artwork and shaves
   the tile's own black keyline thin at all four corners. The keyline is the
   only thing separating #FFD60A from paper at 1.19:1, so thinning it at the
   corners is the one edit this mark cannot afford.

   The deeper error was a magnitude copied where a ratio was meant. ID-T's
   FamilyMark paints its rect at rx 38 of 168, which IS 8.6px at a 38px badge,
   so 9px is that file restated. This file paints rx 24 of 168. Same pixel
   number, different drawing, wrong answer. The file rounds itself at every
   size on every surface, so nothing here has to. */
.wordmark .brand {
  display: block; flex: none; width: 38px; height: 38px;
  margin-right: 10px;
}
.topbar .spacer { flex: 1; }
.topbar .stamp {
  font-family: var(--mono); font-size: var(--t-micro);
  letter-spacing: .08em; text-transform: uppercase; color: var(--ink-3);
}
/* The wordmark is fixed and the stamp is what yields; the date inside it may
   not break. A 480px rule broke the date off on every phone, so the threshold
   is 21.25em — 340px at a 16px root — and it is in em so a larger root font,
   which widens the wordmark, moves it with it; --bar grows in the same :root,
   so the scroll offset moves by the amount the bar did.

   RE-MEASURED 2026-09-16 (audit-type-boxes.js for the named widths, a bisect
   by hand for the ones between). The 2026-09-08 note that stood here said the
   wordmark and the date "fit a 390px row with a third to spare". They do not,
   and at 12px micro they are further from it than they were: the row is 366px
   inside its padding, the wordmark 165.8, the gap 12 and the stamp 159.8,
   which leaves 28.2px. Under eight per cent, not a third.

   AND THE SECOND ROW IS NOT WHERE THIS COMMENT SAID IT WAS. The bar does take
   two rows at 340 and under, as written. But the stamp is flex: 0 1 auto, so
   from 341 to 379 it is squeezed and its own text takes a SECOND LINE inside
   the one-row bar — 37.2px tall against 18.6 at 380 and up. Nothing clips:
   the bar is 60 and the date is nowrap, so the break lands on a space outside
   it, which is exactly why neither a gate nor an eye ever caught it. The
   honest statement is that the stamp yields in two stages — it wraps its own
   text first and takes the bar's second row second — and the media query only
   governs the second stage. */
.wordmark { white-space: nowrap; }
.topbar .wordmark { flex: none; }
.topbar .stamp { flex: 0 1 auto; min-width: 0; }
.topbar .stamp .v { white-space: nowrap; }
@media (max-width: 480px) {
  .topbar .wrap { padding: 0 var(--s3); gap: var(--s3); }
}
/* 76px until 2026-09-16, when --t-micro went 11 to 12 and the stamp's line
   box went 17.05 to 18.6. The bar then rendered 77.6px against a 76px floor,
   so the floor stopped being the floor: min-height lets the bar grow and
   nothing clips, but --bar is read as a constant by four other rules — html
   scroll-padding-top, .skip:focus-visible's top, the board's sticky chapter
   head and every .dir-grid entry's scroll-margin-top — and all four would
   have cleared 1.6px short, which is a chapter head tucked under the bar and
   every scroll landing stopping high. 78 is the rendered 77.6 rounded up,
   measured at 340px on 2026-09-16, not the sum of the parts: the parts are
   38px of badge, 12px of row gap, 18.6px of stamp and 8px of padding, which
   comes to 76.6, and the 1px between that and the truth is the thing a hand
   sum does not have. It is a px constant on purpose. Spelled as a calc the
   sign law's loose reader adds the lengths and ignores the multiplication —
   it would answer 66 and go on printing green about the wrong number. */
@media (max-width: 21.25em) {
  :root { --bar: 78px; }
  .topbar .wrap { flex-wrap: wrap; align-content: center; }
  .topbar .stamp { flex: 0 0 100%; order: 1; }
}

/* --------------------------------------------------------------------------
   The one filled button. It is the mark yellow, and it is the only control
   that is: the page has one primary action — find the corner for an address
   — and the yellow is what says so. Ink keyline, hard cast, rises under the
   pointer and goes flat under the finger; the states are geometry, so they
   survive forced colours (L8b).
   -------------------------------------------------------------------------- */
.go {
  display: inline-flex; align-items: center; gap: var(--s2);
  padding: var(--s3) var(--s4);
  background: var(--sign); color: var(--ink);
  border: 1px solid var(--ink); border-radius: var(--r);
  font-family: var(--sans); font-size: var(--t-body); font-weight: 600;
  letter-spacing: .01em; text-decoration: none; cursor: pointer;
  box-shadow: 2px 2px 0 var(--cast);
  transition: transform .15s var(--ease), box-shadow .15s var(--ease);
}
.go:hover { transform: translateY(-1px); box-shadow: 3px 3px 0 var(--cast); }
.go:active { transform: translate(2px, 2px); box-shadow: none; }
.go .arr { font-family: var(--mono); }

/* The quiet link: ink on a hairline, the keyline stepping up under the
   pointer (and doubling under forced colours, at the foot of the file). */
.ghost {
  color: var(--ink-2); text-decoration: none;
  font-size: var(--t-body);
  border-bottom: 1px solid var(--rule); padding-bottom: 2px;
  transition: color .15s var(--ease), border-color .15s var(--ease);
}
.ghost:hover { color: var(--ink); border-bottom-color: var(--ink); }
.ghost:active { color: var(--ink); border-bottom-color: var(--ink); }

/* The bypass. Off-screen rather than display:none; on focus it is a black
   plate with the mark yellow on it, under the bar's height so the bar
   cannot cover it. */
.skip {
  position: absolute; left: -9999px; top: auto;
  width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%);
}
.skip:focus-visible {
  position: fixed; left: var(--s5); top: calc(var(--bar) + var(--s2));
  width: auto; height: auto; overflow: visible; clip-path: none;
  z-index: 20;
  background: var(--plate); color: var(--hi);
  font-family: var(--mono); font-size: var(--t-small);
  letter-spacing: .08em; text-transform: uppercase;
  padding: var(--s3) var(--s4);
  border-radius: var(--r);
}
/* A skip target is a place to land, not a control, so it wears no focus
   decoration. The shadow has to go with the ring now that the ring carries a
   halo: a section is full-bleed paper on paper, so the halo would paint
   nothing anyone can see, but it would still paint. */
.band[tabindex]:focus { outline: none; box-shadow: none; }

/* ==========================================================================
   HERO — the question, the box that answers it, and the island on its plate.
   Two tracks on a wide screen: the words left, the pane right, sized so the
   pane is the larger object; one track under 1000px, words first. The
   specimen spans both tracks underneath.
   ========================================================================== */
/* The top padding is one rung down from the section pair so the yellow button
   clears a 768-tall first screen at 1366 and at 1280.

   RE-MEASURED 2026-09-16, audit-type-boxes.js: .jump .go runs 610 to 657 in
   document space at 1280, 1366 and 1440 alike, so it clears a 768 screen by
   111px and a 720 screen by 63. The type raise moved it 20.5px down (636.5
   before) and the fold is nowhere near binding either way.

   The figure that stood here, "button bottom y=799, below both folds", could
   not have been true when it was written: 799 is BELOW 768, so the sentence
   refuted itself in its own parenthesis. It is left named rather than quietly
   swapped, because a number that contradicts its own claim and survives eight
   days is the shape worth recognising next time. */
.hero { padding: var(--s6) 0 var(--s8); }
/* THE EYEBROW SPANS THE HERO above both tracks: inside the copy track it
   broke after its last number at every desktop width (measured 2026-09-08,
   "... · 55" / "PLANNING AREAS"). Each dot-separated segment is one
   unbreakable span, so a break can only fall on a middle dot. */
.hero-eyebrow { margin-bottom: var(--s4); }
.nb { white-space: nowrap; }
/* The two tracks share a top edge: the plate's top sits at the headline's,
   not at the middle of a column of copy that is taller than it. */
.hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 6fr) minmax(0, 7fr);
  gap: var(--s7) var(--s8);
  align-items: start;
}
/* minmax(0, ...) on both tracks and on the stacked one: a bare 1fr has an
   auto floor of max-content and the page grows sideways at 265px (S8). */
@media (max-width: 1000px) { .hero-grid { grid-template-columns: minmax(0, 1fr); gap: var(--s7); } }
.hero-copy { min-width: 0; }

.hero h1 {
  margin: 0;
  font-family: var(--serif);
  font-size: clamp(2.375rem, 4.6vw, 3.625rem);   /* 38px .. 58px at a 16px root */
  text-wrap: balance;
  line-height: 1.04;
  letter-spacing: -.022em;
  font-weight: 400;
  max-width: 15ch;
  color: var(--ink);
}
/* The gloss defines the page's two nouns UNDER the lede (2026-09-08: between
   the headline and the lede it was a footnote standing where the pitch
   belongs, and the lede leans on neither noun). A step down from the lede
   because it is the headline's footnote, not a second pitch; 428 holds it
   above the first use of either noun after the headline. */
.hero .gloss {
  margin: var(--s3) 0 0;
  max-width: 52ch;
  font-size: var(--t-body);
  color: var(--ink-3);
}
.hero .gloss dfn { font-style: normal; color: var(--ink); font-weight: 600; }
.hero .lede {
  margin: var(--s5) 0 0;
  max-width: 52ch;
  font-size: var(--t-lede);
  line-height: 1.5;
  color: var(--ink-2);
}
/* (2026-09-08: the lede is one sentence with nothing bold in it — three
   emphasised phrases under a headline were a second headline.) */

/* THE ADDRESS BOX IS THE PRIMARY ACTION. A founder arrives holding an
   address; the box is where that address goes, and its button is the page's
   one yellow control. The form submits to the app in the app's own hash
   grammar with a script, and as a plain GET without one. */
.jump { margin-top: var(--s5); max-width: 52ch; font-size: var(--t-body); }
.jump .lbl { display: block; margin-bottom: var(--s2); font-weight: 600; color: var(--ink); }
.jump .row { display: flex; gap: var(--s3); flex-wrap: wrap; }
/* The input's basis is what decides whether the button shares its row: at
   220px the input, the gap and the button came to 393px inside a 52ch box of
   392, so the button wrapped under the input at EVERY width (measured
   2026-09-08). 200px left the row 30px to spare and the input still grows to
   the rest.

   RE-MEASURED 2026-09-16 after the body rung went 14 to 16, audit-type-boxes:
   the 52ch box is now 448.5px, the button 164.4 and the gap 12, so the basis
   sum is 376.4 and the row has 72.1px to spare — the input then grows to
   272.1 and the three fill the box exactly. The margin more than doubled
   because the box grew with the rung while the button grew with its own
   label, which is the answer to the obvious question: 220 would fit again
   today (396.4 of 448.5). It is staying at 200. The number here was never
   about the button's comfort, it was about the ROW not breaking, and a basis
   that fits by 52px is a basis that stops fitting the first time the button's
   word gets longer. Written down so the next reader does not re-derive it. */
.jump input {
  flex: 1 1 min(200px, 100%); min-width: 0;
  padding: var(--s3) var(--s4);
  font: 400 var(--t-body)/1.3 var(--sans);
  color: var(--ink); background: var(--paper);
  border: 1px solid var(--ink); border-radius: var(--r);
  box-shadow: inset 2px 2px 0 var(--cast);
}
.jump input::placeholder { color: var(--ink-3); opacity: 1; }
/* The hint under the row. --ink-2 and not --ink-3: this sentence is the only
   place the page says what the box takes, so it is quiet furniture, not the
   greyed-out register a placeholder is. It sits INSIDE the form so a reader
   tabbing out of the input does not leave it behind. */
.jump-hint { margin: var(--s2) 0 0; font-size: var(--t-small); color: var(--ink-2); }
.jump .go { flex: none; }
/* On a phone both take the whole row: an address is long, and a button
   alone on a second row at its own width read as a stub. */
@media (max-width: 480px) { .jump .go { flex: 1 1 100%; justify-content: center; } }
/* The two secondary routes, as quiet links after the box: the island for a
   reader without an address, the board for one who came knowing their trade.
   The price line rides the same row at caption size; the colophon argues it. */
.hero .cta { margin-top: var(--s5); display: flex; align-items: baseline; gap: var(--s5); flex-wrap: wrap; }
/* the price line on its own row under the two routes: on the links' row it
   read as a third link (768, 2026-09-08) */
.hero .cta .cta-note { flex-basis: 100%; font-size: var(--t-small); color: var(--ink-3); }
.hero noscript .lede { font-size: var(--t-body); }

/* ==========================================================================
   THE ISLAND, on its plate. The product, drawn by the build out of the app's
   own geometry and shaded by the rent at the head of each card on the app's
   own ramp, cut by the app's own rank rule. The pane is the plate — the
   one dark object above the fold, granted by review the way the app's map
   pane is: a red-to-green data ramp reads against a quiet ground, not
   against paper. Every planning area is a link into the app at its own
   grain, out of the tab order; the caption's disclosure carries the same
   doors by name, which is the keyboard route.

   AND THE THUMB ROUTE, which is the same list and was not written down until
   2026-09-16. A shape here is as big as the place it draws: hit-tested at 390,
   26 of the 55 links have a side under 24px and at 340 it is 38 of 55. That
   is the one case both target-size criteria carve out by name — a target
   whose presentation is essential to what it conveys — and the carve-out
   holds only while the list under the caption reaches every one of the same
   55 doors at a size a thumb can take. See THIS LIST IS WHAT EXCUSES THE MAP
   at .island-cap .areas a, and clause 436, which holds the two sets equal.
   ========================================================================== */
.island-fig {
  margin: 0; min-width: 0;
  background: var(--plate); color: var(--p-ink);
  border-radius: calc(var(--r) * 2);
  padding: var(--s5) var(--s5) var(--s4);
  box-shadow: 4px 4px 0 var(--cast);
}
.island { display: block; max-width: 100%; }
.island .isvg { display: block; width: 100%; height: auto; }
/* the seams are the plate showing through, as on the app's map */
.island .z { stroke: var(--plate); stroke-width: .6; stroke-linejoin: round; }
/* the ramp: one fill per band, the token's own name saying which fifth */
.island .z.own[data-b="0"] { fill: var(--b0); }
.island .z.own[data-b="1"] { fill: var(--b1); }
.island .z.own[data-b="2"] { fill: var(--b2); }
.island .z.own[data-b="3"] { fill: var(--b3); }
.island .z.own[data-b="4"] { fill: var(--b4); }
/* a district band stands in: the no-value grey under the copper hatch the
   drawing's own <pattern> draws; the pattern's two rects take their colour
   here, so the drawing carries none of its own */
.island .z.band { fill: url(#drape); stroke: var(--noval-line); }
/* a rent for another market stands in its own right: the same grey, the same
   copper, dotted rather than hatched (2026-09-16). The ink is shared on
   purpose — copper on this drawing means "a reading that is not this corner's
   own shopfront rent", and both tones are that. The texture is what says
   which: the hatch is one grain up, the district's; the dot is sideways, the
   corner's own number for industrial or office space. Neither is on the ramp,
   because the ramp is labelled in psf of shop.

   THE APP DRAWS ONE MARK WHERE THIS PAGE DRAWS TWO, and that is a decision,
   not a drift. app.js's concept pass of 2026-09-09 deleted its hatch and gave
   both states one dashed keyline, on the argument that they are the same thing
   to a reader: a number exists and it is not the number this map is about. On
   the app that argument holds because the mark only has to say "not this" —
   the hover readout and the card then say WHICH, in words, on the corner
   itself. This drawing has no readout, no hover text and no card. Here the
   mark is the whole message, and a reader who cannot tell the two apart has
   nowhere else to look. One rule, two surfaces, two answers.

   The older question is still open and is still the owner's: whether this page
   should follow the app off the hatch and onto a dashed edge at all (see the
   note at --drape). It now has two occupants rather than one. */
.island .z.other { fill: url(#otherclass); stroke: var(--noval-line); }
.island .dg { fill: var(--noval); }
.island .dl { fill: var(--drape); }
/* neither: the grey alone, with its edge, so the coast still reads */
.island .z.none { fill: var(--noval); stroke: var(--noval-line); }
.island a { cursor: pointer; }
/* The hover is a width AND a colour, and for a year the comment here said the
   width was enough on its own to survive forced colours (L8b). Measured
   2026-09-16, it is not: with the stroke held at the reader's own ink the
   0.4px of growth paints 28 device pixels on Singapore River and 48 on Bishan,
   against 9,390 when the colour moves too. A claim about what survives a mode
   is a claim about a rendering. The forced-colors block now moves the colour
   there as well, and this rule is unchanged on paper. */
.island a:hover .z, .island a:focus-visible .z { stroke: var(--p-ink); stroke-width: 1.4; }

/* THE KEY, on the plate under the drawing. A ramp of five cells labelled
   with the least and greatest psf the drawing actually paints in each, the
   count of corners in the cell under that; then the two tones off the ramp,
   each with its swatch and its count; then the click line and the list of
   areas under one disclosure. */
.island-cap {
  margin: var(--s4) 0 0;
  font-size: var(--t-small); color: var(--p-ink-2); line-height: 1.55;
}
.island-cap b { color: var(--p-ink); font-weight: 600; }
.island-cap .key { display: block; }
.island-cap .key .lbl {
  display: flex; justify-content: space-between; gap: var(--s3); flex-wrap: wrap;
  margin-bottom: var(--s2);
  font-size: var(--t-micro); letter-spacing: .1em; text-transform: uppercase; color: var(--p-ink-3);
}
/* THE RANGES WRAP, THEY DO NOT CLIP (round three, 2026-09-16). This block
   carried `white-space: nowrap; overflow: hidden; text-overflow: ellipsis`,
   which is a decision to cut published data rather than to find room for it,
   and it was cutting: rendered at 340px the fourth band lost 4px of its
   figure and the fifth lost 9, so the two DEAREST ranges — the two a reader
   came here for — were the two showing an ellipsis where a digit belonged.
   Nothing could see it. No clause reads this text, the ellipsis is drawn by
   the browser rather than written into the string, and a truncated figure
   looks exactly like a short one.

   The 480px override underneath used to answer this by setting 10px type,
   and the measurement is what shows how wrong that was: the cell is 83.2px
   at a 480px viewport and 79.4px at 481, so the override narrowed the type
   at the one width where the cell was WIDEST. It is gone. The ranges sit at
   --t-micro at every width, which is the floor both sheets took today.

   AND A WRAP AND NOT A SMALLER NUMBER, because the label is DATA. landing.html
   builds these five from the bands the build derived, so "14.24–48.98" is
   today's register and not a bound; a three-digit psf prints thirteen
   characters, which is over the cell at 12px at every viewport below 1280. A
   shrink chases a number that moves and a clip hides the day it moves. An en
   dash is a break opportunity (UAX #14 class BA), so the range breaks after
   it into halves of six and five characters, and at 340px — the narrowest
   row this page is built for — the cell holds either half with room to
   spare, for the three-digit register as well as this one.

   SUBGRID IS WHAT KEEPS THE COUNTS IN A ROW. Once one range may take two
   lines and its neighbour one, the count under it sits a line lower than the
   count beside it and the key reads as five unequal things. The cells share
   the parent's three rows, so swatches align with swatches, ranges with
   ranges and counts with counts however any one of them wraps. Where subgrid
   is missing the base rule still stands and the counts merely sit at their
   own heights: every figure is still on the page, which is the part that
   cannot be allowed to depend on a feature query. */
.island-cap .ramp {
  display: grid; grid-template-columns: repeat(5, minmax(0, 1fr));
  grid-template-rows: auto auto auto;
  column-gap: 2px; row-gap: 0;
  margin: 0; padding: 0; list-style: none;
}
.island-cap .ramp .cell { min-width: 0; }
@supports (grid-template-rows: subgrid) {
  .island-cap .ramp .cell { display: grid; grid-row: span 3; grid-template-rows: subgrid; }
}
/* THE HAIRLINE IS WHAT RESCUES THE DEAREST BAND. --b4 is 2.01:1 on the plate,
   the only fill in this key under the 3:1 a meaningful graphic owes, and it
   is the band carrying the highest rents — so the one step a reader is most
   likely to be hunting for was the one hardest to see against the ground. The
   edge is --p-rule, the plate's own hairline at 3.01:1, and it goes on ALL
   FIVE: an edge on one swatch would say that swatch is different, and the
   whole claim of a ramp is that they are five equal steps of one scale. The
   two swatches OFF the ramp keep --noval-line, because that one is a copy of
   the app's own stroke and clause 400 holds it to the app; this one is legend
   furniture and takes the plate's rule. */
.island-cap .ramp .sw {
  display: block; width: 100%; height: var(--s3);
  border-radius: 2px; border: 1px solid var(--p-rule);
}
.island-cap .ramp .rg {
  display: block; margin-top: var(--s1);
  font-family: var(--mono); font-size: var(--t-micro); color: var(--p-ink);
  font-variant-numeric: tabular-nums;
}
/* the counts one step lighter than the caps line: at the third rung they
   were the darkest text on the plate under the brightest (2026-09-08) */
.island-cap .ramp .ct { display: block; font-size: var(--t-micro); color: var(--p-ink-2); }
/* the right-hand cap stays right when the label row wraps (1024 and 390):
   an auto margin survives the wrap where space-between does not */
.island-cap .key .lbl > span:last-child { margin-left: auto; }
.island-cap .sw.b0 { background: var(--b0); }
.island-cap .sw.b1 { background: var(--b1); }
.island-cap .sw.b2 { background: var(--b2); }
.island-cap .sw.b3 { background: var(--b3); }
.island-cap .sw.b4 { background: var(--b4); }
.island-cap .off {
  display: flex; flex-wrap: wrap; gap: var(--s2) var(--s5);
  margin-top: var(--s3);
}
.island-cap .off > span { display: inline-flex; align-items: center; gap: var(--s2); }
.island-cap .off .sw {
  display: inline-block; width: var(--s4); height: var(--s3); flex: none;
  border-radius: 2px; border: 1px solid var(--noval-line);
}
/* TWO PIECES OF THE KEY THAT ONLY FORCED COLORS DRAWS, and they ship in the
   markup at every width rather than being written by a script that reads the
   mode: the third entry in the off-ramp row, which decodes the one tone the
   ramp collapses into, and the line of words that says the shading is not
   drawn. Both are wrong on paper — there the 249 are five tones, not one —
   so the resting page hides them, and the forced-colors block at the foot
   shows them. Same idea as .v-click / .v-tap, same prefix.

   The hide rule is THREE classes and an element because the rule it has to
   beat, `.island-cap .off > span`, is two and an element. A display that
   loses its specificity fight does not fail quietly: it ships the sentence
   "high contrast draws all 249 in one tone" onto a page drawing five. */
.island-cap .off > span.v-hc, .island-cap .hcnote { display: none; }
.island-cap .hcnote {
  margin-bottom: var(--s2); max-width: 60ch;
  font-size: var(--t-micro); line-height: 1.5;
}
/* the three swatches off the ramp: the grey, the grey under the copper hatch
   at the drawing's own angle, and the grey under the copper dot (2026-09-16).
   A swatch is 24x12 at the base step, so a 4px radial tile lands three rows
   of dots in it and reads as texture rather than as one smudge — the hatch
   beside it gets six stripes in the same box, which is the distinction this
   pair has to carry at this size. The dot's stop is at 42% of a 4px tile to
   put the same quantity of copper in the swatch as the stripe does, so the
   two entries do not read as light and dark of one thing. */
.island-cap .sw.none { background: var(--noval); }
.island-cap .sw.band {
  background: var(--noval) repeating-linear-gradient(-45deg, transparent 0 2px, var(--drape) 2px 4px);
}
/* background-size takes ONE value here and it took two for a render. The
   shorthand above sets a background-COLOR and a single background-IMAGE, so
   a two-value size lists a layer that does not exist: `auto` landed on the
   gradient, which drew the tile at the swatch's full 24x12 and put one dot
   in the key beside a map covered in them. A list is as long as the layers,
   not as long as the declaration it is copied from. */
.island-cap .sw.other {
  background: var(--noval) radial-gradient(circle at 50% 50%, var(--drape) 0 42%, transparent 42%);
  background-size: 4px 4px;
}
/* the two prose lines under the key, ruled off from it in the plate's own
   hairline, the click sentence in the legend's tone: the affordance is
   stated once, by the by-name entry under it, which is set as a link and
   opens from the page's one disclosure ring (2026-09-08: it was bare bold
   text on the plate, and on a phone it is the plate's only usable door) */
/* display: block, AND IT IS THE WHOLE RULE (found by render, 2026-09-16).
   This is a <span>, and it carried margin-top, padding-top and a border-top
   with no display, so it was INLINE: an inline box's vertical margin and
   padding reserve no space and its top border is painted at the top of its
   own line box. The hairline meant to rule the key off from the prose was
   therefore drawn THROUGH the line above it — straight across "36 carry
   their district's band" and "47 carry neither" — at every width from 340 to
   1440, a strike through two published counts. Every other span in this
   figcaption was given a display (.key block, .lbl flex, .ramp grid, .off
   flex); this one was missed, and nothing could see it, because the sheet
   reads exactly right and only the paint is wrong. */
.island-cap .how {
  display: block;
  margin-top: var(--s3); padding-top: var(--s3);
  border-top: 1px solid var(--p-rule); color: var(--p-ink-3);
}
.island-cap .areas { margin-top: var(--s2); }
.island-cap .areas summary {
  cursor: pointer; display: inline-flex; align-items: center; gap: var(--s2);
  font-size: var(--t-small); color: var(--p-ink);
  text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px;
  text-decoration-color: var(--p-rule);
}
.island-cap .areas summary:hover, .island-cap .areas summary:focus-visible { text-decoration-color: var(--p-ink); text-decoration-thickness: 2px; }
.island-cap .areas ul {
  list-style: none; margin: var(--s2) 0 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: var(--s1) var(--s3);
}
/* THIS LIST IS WHAT EXCUSES THE MAP, so it is the one control on the plate
   that may not be under the floor (2026-09-16). The island is 55 links drawn
   as the planning areas themselves, and a planning area is as big as it is:
   measured at 390, 26 of the 55 have a side under 24px, and at 340 it is 38
   of 55 — Museum is 7.8 by 8.3, Singapore River 13.7 by 7.2. No size policy
   reaches that, because the SHAPE IS THE DATA. Both target-size criteria
   carve out exactly this case, where the presentation of the target is
   essential to the information it conveys, and the carve-out is only honest
   while there is another way to the same 55 places. That other way is this
   list, and it was set at 17px of link inside a 20.1px row at every width —
   the escape hatch was under the floor the map was being excused from.

   min-height AND NOT the ::after pad the page uses elsewhere: a pad drawn
   10px above and below the text is right for a link in a sentence, where the
   box may not grow without moving the line; these are flex items in a cloud
   with a 4px row gap, so the box may simply BE 24px and the rows then sit
   24px tall, 4px apart, with nothing overlapping anything. Not bracketed by
   width either, unlike the TAP HEIGHTS block at the foot of this sheet: a
   mouse at 1440 is held to the same 24px by the same criterion, and the duty
   this list is discharging does not get smaller on a bigger screen.

   24 AND NOT 44, on the same reasoning the ledger's rows were given: fifty
   five names at 44px is a 2,400px wall inside a disclosure, and the AA figure
   is the one the page spends everywhere except its two card summaries. */
.island-cap .areas a {
  display: inline-flex; align-items: center; min-height: 24px;
  color: var(--p-ink);
  text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 2px;
  text-decoration-color: var(--p-rule);
}
.island-cap .areas a:hover, .island-cap .areas a:focus-visible {
  text-decoration-color: var(--p-ink); text-decoration-thickness: 2px;
}
@media (max-width: 480px) {
  .island-fig { padding: var(--s4) var(--s3) var(--s3); border-radius: var(--r); }
  /* the 10px range override lived here and is gone; see THE RANGES WRAP above */
}

/* The verb follows the pointer: both ship in the markup, the sheet shows the
   one the device's primary pointer answers to. */
.v-tap { display: none; }
@media (pointer: coarse) {
  .v-click { display: none; }
  .v-tap { display: inline; }
}

/* ONE DISCLOSURE GRAMMAR (2026-09-08: the receipts opened from the (i), the
   census from the browser's solid triangle, the plate's list from bare
   text — one verb, three constructions). No native marker anywhere; the
   summaries that carry no (i) open from a ring of the (i)'s own weight
   holding a plus, and a minus once open. The folds (.rest: the rest of a
   mark's limit, the board note's definitions; 2026-09-08) open from the
   same ring. */
summary { list-style: none; }
summary::-webkit-details-marker { display: none; }
.fact .census summary::before, .island-cap .areas summary::before, .rest summary::before {
  content: '+';
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.3em; height: 1.3em; flex: none;
  border: 1px solid currentColor; border-radius: 50%;
  font-family: var(--mono); font-size: .9em; line-height: 1;
}
.fact .census[open] > summary::before, .island-cap .areas[open] > summary::before, .rest[open] > summary::before { content: '\2212'; }

/* The (i) glyph the summaries share: a ring with an i in it, in the ink. */
.i {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.3em; height: 1.3em; flex: none;
  border: 1px solid currentColor; border-radius: 50%;
  font-family: var(--serif); font-style: italic; font-size: .9em; line-height: 1;
  text-wrap: nowrap;
}

/* ==========================================================================
   THE SPECIMEN — one real published cell, carried onto the page whole, and
   read in plain words on its face. The instrument id, the pooling sentence
   and the span's older end are one disclosure away (owner ruling 2026-09-06:
   "behind the (i), plain words on the face"); nothing is removed. Spans both
   hero tracks; on a wide screen the reading and the strip of what else the
   corner publishes sit side by side inside one card.
   ========================================================================== */
.spec-fig { grid-column: 1 / -1; margin: var(--s7) 0 0; }
.specimen {
  border: 1px solid var(--ink);
  border-radius: calc(var(--r) * 2);
  background: var(--paper);
  box-shadow: 4px 4px 0 var(--cast);
}
.spec-head {
  display: flex; align-items: baseline; gap: var(--s3); flex-wrap: wrap;
  padding: var(--s4) var(--s6);
  border-bottom: 1px solid var(--ink);
}
.spec-head .who { font-size: var(--t-body); color: var(--ink-2); }
.spec-head .who b { color: var(--ink); font-weight: 600; }
.spec-head .spacer { flex: 1; }
.grade {
  font-family: var(--mono); font-size: var(--t-micro);
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink);
  border: 1px solid var(--ink); border-radius: var(--r);
  padding: 3px var(--s2);
}
/* an auto margin survives the wrap where a flex spacer does not */
.spec-head .grade { margin-left: auto; }
.spec-body { padding: var(--s6) var(--s6) var(--s7); }
@media (max-width: 600px) {
  .spec-head { padding: var(--s3) var(--s4); }
  .spec-body { padding: var(--s5) var(--s4) var(--s6); }
}

.readout { display: flex; align-items: baseline; gap: var(--s4); flex-wrap: wrap; }
/* The figure is a serif numeral, not a terminal readout: it is a number a
   person reads, and the arithmetic behind it is in the receipt. Lining and
   tabular so the cent columns hold. */
.readout .fig {
  font-family: var(--serif);
  font-size: clamp(2.75rem, 5.2vw, 3.75rem);
  line-height: .95;
  letter-spacing: -.025em;
  color: var(--ink);
  font-variant-numeric: lining-nums tabular-nums;
  text-wrap: nowrap;   /* a figure never breaks inside itself */
}
/* The qualifier beside the figure, on the figure's baseline. One short line,
   so it carries no reading measure: the 40ch cap folded it in two beside a
   60px numeral (2026-09-08), and a cap is for prose. */
.readout .per { font-size: var(--t-body); color: var(--ink-2); }

/* The spread: the median is a tick on the published range, never a point. */
.spread { margin-top: var(--s5); }
.spread .track {
  position: relative; height: var(--track-h);
  background: var(--track-bg); border-radius: var(--track-r); box-shadow: var(--track-in);
}
.spread .span {
  position: absolute; top: 0; bottom: 0;
  background: var(--span-fill);
  border-radius: var(--track-r);
  transform-origin: left center;
}
.spread .tick {
  position: absolute; top: -5px; bottom: -5px; width: 2px;
  background: var(--ink);
}
.spread .ends {
  display: flex; justify-content: space-between; gap: var(--s4); flex-wrap: wrap;
  margin-top: var(--s2);
  font-family: var(--mono); font-size: var(--t-small); color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.spread .ends .q { color: var(--ink-3); }
/* each end is one unbreakable label and the row wraps only when the two do
   not fit it: a deliberate stack under 430 read as a wrap fault on a phone
   where both fit with a third of the row to spare (2026-09-08) */
.spread .ends > span { white-space: nowrap; }
@media (max-width: 430px) {
  .spread .ends { row-gap: var(--s1); }
  .readout { display: block; }
  .readout .per { display: block; padding: var(--s2) 0 0; }
}

/* Two plain cells on the face: what the figure is measured per, and the
   quarter it runs to. The instrument moved into the receipt below. */
.spec-meta {
  margin-top: var(--s5); padding-top: var(--s4);
  border-top: 1px dashed var(--rule);
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr)); gap: var(--s4);
}
.spec-meta div { min-width: 0; }
.spec-meta .v {
  margin-top: 3px; font-size: var(--t-body); color: var(--ink);
  font-family: var(--serif); line-height: 1.3; text-wrap: pretty; overflow-wrap: anywhere;
}
/* the one plain qualifier on the face: the span's older end, in the app's
   receipt words, under the date; an empty cell takes no room */
.spec-meta .from { margin-top: var(--s1); font-size: var(--t-small); }
.spec-meta .from:empty { display: none; }
@media (max-width: 430px) {
  .spec-meta { grid-template-columns: minmax(0, 1fr); gap: var(--s2); }
  .spec-meta > div { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s3); flex-wrap: wrap; }
  .spec-meta .v { margin-top: 0; }
  .spec-meta .from { flex: 1 0 100%; margin-top: 0; }
}

/* THE RECEIPT. A native <details>: the summary is the (i), the body holds
   the instrument id verbatim and what the two ends of the range are in the
   app's own words. The id is one token held whole (.tok); a token wider
   than the card scrolls inside its own cell rather than breaking at its
   hyphen. The ends' sentence is prose and wraps. */
.receipt { margin-top: var(--s4); font-size: var(--t-small); color: var(--ink-2); line-height: 1.6; }
.receipt summary {
  cursor: pointer; display: inline-flex; align-items: center; gap: var(--s2);
  font-family: var(--sans); font-size: var(--t-small); color: var(--ink);
}
.receipt summary:hover, .receipt summary:focus-visible { text-decoration: underline; text-underline-offset: 3px; }
.receipt .r { margin-top: var(--s2); display: grid; gap: var(--s3); }
.receipt .r > div { min-width: 0; }
.receipt .r .v { margin-top: 2px; font-family: var(--mono); color: var(--ink); }
.receipt .r .v.tok { white-space: nowrap; overflow-x: auto; }
.receipt .r .v.why { font-family: var(--sans); color: var(--ink-2); }
.spec-main { min-width: 0; }

/* ==========================================================================
   THE SIGNATURE — the caution mark. Wherever a number appears, this block
   appears under it carrying the sentence that number cannot answer, verbatim
   from the surface, at the same size as the claim above it (S2). It is built
   the way a sign is built: a banded label naming the severity, the message
   beneath. On CAUTION the keyline is 1px ink and the BAND is the hazard
   marking, black on yellow, over a body on paper. On WARNING the keyline
   doubles, the band goes solid black and the legend reverses out of it in
   --hi. Both rungs now share a body, so the ladder is read where a sign is
   read: the band, and the weight of the line around it.

   THE MARK WAS A FIELD AND IS NOW A STRIPE (2026-09-11, the nine, item 3).
   The caution rung filled its whole box with --sign, and the defect that
   makes plain is not area, it is RANK: on the register a caution slab
   out-shouted the warning card two rows below it, because warning was
   already a paper body with a black band and caution was a solid field. The
   lower rung was the louder object. Now they differ the way rungs should,
   on the band and the keyline, and the ladder runs the right way up.

   MEASURED ON THE PAGE THAT SHIPS, not on the one that argued for it. The
   register crop at 390, DPR 1, the whole of #facts and nothing else, counted
   with audit-sign-area.js's own classifier bands: sign field 256,757px before
   and 74,844px after, down 70.9 percent, and 179,993px of it became paper.
   Taken AFTER item 4 landed, because item 4 moves the fact-side mass and a
   ratio measured on the old row would be describing a page that no longer
   exists. Nothing is removed: the band keeps black on yellow at
   full strength, every caveat word is unchanged in size and position, and
   the caveat prose gains ground, ink on paper at 16.11:1 where it read ink
   on sign at 10.65:1. It is rationed, which is the ruling the mark has
   always been under.
   ========================================================================== */
.mark {
  margin-top: var(--s4);
  border-radius: var(--r);
  overflow: hidden;
  font-size: var(--t-body);
  max-width: 62ch;
}
#spec-mark .mark { max-width: 100%; }
#spec-mark .mark .in p {
  font-size: var(--t-body);
  max-width: 54ch;
}
.mark .band {
  display: flex; align-items: center;
  flex-wrap: wrap; column-gap: var(--s2); row-gap: 2px;
  padding: 6px var(--s3);
  font-family: var(--sans); font-size: var(--t-micro); font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase;
}
.mark .band > span:not(.sub) { flex: none; }
.mark .band .sub {
  min-width: 0; font-weight: 400;
  letter-spacing: .06em;
  overflow: hidden; text-overflow: ellipsis;
}
.mark .in { padding: var(--s3) var(--s4) var(--s4); }
.mark p { margin: 0; font-size: inherit; color: var(--ink); }
/* The rest of the limit, folded under its first sentence (2026-09-08: the
   register's eight marks printed four to seven sentences each on the face,
   and the column read as a wall of caution). The summary is one word in the
   mark's own ink behind the page's one disclosure ring; the fold's text is
   set exactly as the face's. */
.mark .rest { margin-top: var(--s2); }
.mark .rest summary {
  display: inline-flex; align-items: center; gap: var(--s2);
  cursor: pointer; font-size: var(--t-small); color: var(--ink);
}
.mark .rest summary:hover, .mark .rest summary:focus-visible { text-decoration: underline; text-underline-offset: 3px; }
.mark .rest p { margin-top: var(--s2); }
.tri { width: 1.25em; height: 1.15em; flex: none; }

.mark.caution { border: 1px solid var(--ink); background: var(--paper); }
.mark.caution .band { background: var(--sign); color: var(--ink); border-bottom: 1px solid var(--ink); }
/* The body is --paper and so is the page, so without this the card is held by
   one hairline and the mark is a stripe with nothing under it. The rule carries
   the sign down the full height, which is what keeps the block an OBJECT in the
   worlds where the band's own hue is gone: it sits 1.51:1 off its body in
   normal sight, 1.44 to 1.64:1 under all three CVD sims, and reads #FFB0A6, a
   pale pink, under tritanopia — the one clause 400 L3 names by name. */
.mark.caution .in { border-left: 2px solid var(--sign); }

.mark.warning { border: 2px solid var(--ink); background: var(--paper); }
.mark.warning .band { background: var(--plate); color: var(--hi); font-weight: 600; }
.mark.warning .band .sub { color: var(--p-ink-2); font-weight: 400; }

/* The strip of what else the same corner publishes: keys in the third ink,
   values in full ink, hairline separators, and each pair's receipt one (i)
   away. */
.also { margin-top: var(--s5); border-top: 1px solid var(--rule); padding-top: var(--s4); }
.also .eyebrow { display: block; margin-bottom: var(--s3); }
.also dl { margin: 0; display: grid; gap: 1px; background: var(--rule); }
.also .pair {
  background: var(--paper);
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: flex-end;
  gap: var(--s4); padding: var(--s2) 0;
  min-width: 0;
}
.also dt {
  margin-right: auto;
  font: 400 var(--t-small)/1.4 var(--sans);
  color: var(--ink-3); letter-spacing: 0;
  text-wrap: balance;
}
.also dd {
  margin: 0; text-align: right;
  font: 400 var(--t-body)/1.4 var(--serif);
  color: var(--ink); font-variant-numeric: lining-nums tabular-nums;
}
.also dd.rcpt {
  flex: 1 0 100%; text-align: left;
  font: 400 var(--t-micro)/1.5 var(--mono);
  color: var(--ink-3);
}
.also dd.rcpt summary { cursor: pointer; display: inline-flex; align-items: center; gap: var(--s1); color: var(--ink-3); font-family: var(--sans); }
.also dd.rcpt summary:hover, .also dd.rcpt summary:focus-visible { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
.also dd.rcpt .r { margin-top: var(--s1); overflow-x: auto; }
.also dd.rcpt .tok { white-space: nowrap; }
/* a value longer than the label column (three stations and their distances)
   takes the whole row under its label, left-set, instead of a narrow
   right-set column beside it; the build marks it (2026-09-08) */
.also dd.long { flex: 1 0 100%; text-align: left; }
@media (max-width: 430px) {
  .also .pair { flex-direction: column; flex-wrap: nowrap; align-items: flex-start; gap: 2px; }
  .also dt { margin-right: 0; }
  .also dd { text-align: left; }
  /* the long value too: in a column flex the base rule flex-basis 100%
     resolves against the pair height once the grid has stretched it, and
     the value stood as tall as its pair and overlapped the row above
     (390px full-page render, 2026-09-08) */
  .also dd.rcpt, .also dd.long { flex: 0 0 auto; align-self: stretch; }
}
/* Side by side inside the card on a wide screen; written AFTER every base
   rule it overrides, because a media query adds no specificity (S11). */
@media (min-width: 1000px) {
  .spec-body { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--s8); align-items: start; }
  .also { margin-top: 0; border-top: 0; padding-top: 0; border-left: 1px solid var(--rule); padding-left: var(--s7); }
}

/* ==========================================================================
   THE REGISTER — every published fact with its real coverage. One row per
   fact: name and gauge on the left, the plain claim and its mark on the
   right; the instruments and the coverage census fold under one disclosure.
   ========================================================================== */
/* ONE SPACING PAIR for every full-bleed rule: each section pads s8 above and
   below, so the paper either side of a rule is the same two rungs (measured
   2026-09-08: four different pairs, 43/105 to 97/52). Halved on a phone at
   the foot of the file. */
.register { padding: var(--s8) 0; }
.sec-head { display: flex; align-items: baseline; gap: var(--s4); flex-wrap: wrap; }
/* the heading's block (eyebrow and h2) takes the whole row, so the deck
   under it is under it. The block, not the h2: both heads wrap the h2 in a
   div, and a flex rule on the h2 landed on nothing (probe, 2026-09-08 —
   the register's deck was under its long heading by width alone, the
   board's beside its short one). */
.sec-head > div { flex: 1 0 100%; }
.sec-head h2 {
  margin: var(--s3) 0 0;
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(1.75rem, 3.2vw, 2.375rem); line-height: 1.1; letter-spacing: -.018em; text-wrap: balance;
  color: var(--ink);
}
/* the deck sits UNDER the heading at every width, on the next row at the
   reading measure. (2026-09-08: with the heading at its own width the
   aside's 100% basis was clamped by its 62ch cap and it rode BESIDE the
   heading at 1440, a caption on the wrong side, while the comment here
   claimed the opposite — a sheet comment is a claim to verify against the
   render.) Its length is the build's, not the designer's */
.sec-head .aside {
  flex: 1 0 100%;
  max-width: 62ch;
  font-size: var(--t-body); color: var(--ink-2);
}

/* The second track is the reading measure and the first takes the slack, so
   every row ends on its own rule. font-size stated because the 62ch track
   resolves against it (S3). Two tracks from 701px up: the one-column stack
   is a phone's (2026-09-08: at 768 the rows stacked though two tracks fit),
   and there is NO third arrangement above it — the 1200px rule that split
   the right cell into two 223px halves stood every caveat up as a yellow
   tower beside 360-420px of empty paper, at the widths most readers have. */
.fact {
  display: grid; grid-template-columns: minmax(min(260px, 100%), 1fr) minmax(0, 62ch); gap: var(--s7);
  padding: var(--s6) 0;
  font-size: var(--t-body);
  border-top: 1px solid var(--rule);
}
.fact:first-of-type { margin-top: var(--s7); }
@media (max-width: 700px) { .fact { grid-template-columns: minmax(0, 1fr); gap: var(--s4); } }
/* THE ROW'S RUNGS, SWAPPED (2026-09-11, the nine, item 4). The section head
   asks "7 facts, and how far each one actually reaches", and the thing that
   answered it was the smallest of the row's three serif ranks. Name 24, figure
   18, grain 11. The two swap, on tokens the sheet already carries — no new
   size — and the hardcoded 1.125rem goes with them.

   NEITHER SIZE WAS EVER RULED, which is why this is a swap and not a revert.
   337ce20 moved the name 1.375rem to 1.5rem inside a ground-up redraw and gave
   the figure its first size ever, hardcoded, in the same hunk; 1488f94 then
   tokenised the name's literal. No commit body rules on either. The dated note
   in --t-head is the BOARD's chapter head, a different element.

   AND THE OTHER DIRECTION WAS MEASURED AND FAILED. research/the-nine-
   2026-09-10.md injected the name at 24, 37 and 58px: rent's caveat still out-
   massed it 158.7x, 77.1x, 29.4x, and band dominance moved 1.39 to 1.40. You
   cannot win this row by making the subject louder, because mass follows the
   string and "Rent" is four letters. So the figure comes up instead.

   THE INDEX IS NOT WHAT MOVED. No markup changes here. .fact .name stays an
   <h3>, so a screen reader's heading list still reads Rent / Footfall / and
   the rest in order, and the pagination rule at the foot of this sheet still
   groups .fact .name with the chapter heads. What was demoted is one visual
   rank on one surface, not the register's structure. */
.fact .name {
  margin: 0; font-weight: 400;
  font-family: var(--serif); font-size: var(--t-lede); line-height: 1.15; letter-spacing: -.012em; color: var(--ink); text-wrap: balance;
}
.fact .grain {
  font-family: var(--sans); font-size: var(--t-micro); font-weight: 600; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-3); margin-top: var(--s1);
}
.fact .cover { margin-top: var(--s4); }
.fact .cover .n {
  font-family: var(--sans); font-size: var(--t-body); color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.fact .cover .n em {
  color: var(--ink); font-style: normal; font-weight: 600;
  font-family: var(--serif); font-size: var(--t-head); line-height: 1; text-wrap: nowrap;
}
.fact .cover .track {
  margin-top: var(--s2); height: var(--track-h);
  background: var(--track-bg); border-radius: var(--track-r); box-shadow: var(--track-in);
  overflow: hidden;
}
.fact .cover .fill {
  height: 100%; background: var(--ink-2); border-radius: var(--track-r);
  transform-origin: left center;
}
/* The gauge is the warning and it joins the ladder: the slot's keyline
   doubles to 2px ink, and the measured part is struck with the mark yellow
   at the tape's own 45 degrees — the page's one hazard marking, on the one
   quantity that is a hazard to read straight. Both axes are achromatic. */
.fact.warning .cover .track { box-shadow: inset 0 0 0 2px var(--ink); background: var(--track-bg); }
.fact.warning .cover .fill {
  background: var(--ink)
    repeating-linear-gradient(-45deg, transparent 0 3px, var(--sign) 3px 5px);
}
.fact.warning .cover .n em { color: var(--ink); }
.fact .plain { margin: 0; font-size: var(--t-body); color: var(--ink); max-width: 62ch; }
/* The fold: instruments by name and where the corners outside the bar
   stand, at the small rung, under a summary that says what it holds. */
.fact .more {
  margin: var(--s3) 0 0; max-width: 62ch;
  font-family: var(--sans); font-size: var(--t-small);
  color: var(--ink-2); line-height: 1.65;
}
.fact .more summary { cursor: pointer; color: var(--ink); display: inline-flex; align-items: center; gap: var(--s2); }
.fact .more summary:hover, .fact .more summary:focus-visible { text-decoration: underline; text-underline-offset: 3px; }
.fact .inst { margin-top: var(--s2); }
.fact .inst .v {
  margin-top: var(--s1);
  font-family: var(--mono); font-size: var(--t-micro); line-height: 1.6;
  color: var(--ink-3); overflow-x: auto;
}
.fact .inst .v .tok { white-space: nowrap; }
.fact .census { margin-top: var(--s2); }
.fact .census summary { cursor: pointer; color: var(--ink); display: inline-flex; align-items: center; gap: var(--s2); }
.fact .census summary:hover, .fact .census summary:focus-visible { text-decoration: underline; text-underline-offset: 3px; }
.fact .census p { margin: var(--s1) 0 0; }

/* The register's closing line: one grid item, so the single measured track
   measures a paragraph and not a row per bold (423). */
.register .rule {
  margin: var(--s6) 0 0; padding-top: var(--s4);
  border-top: 1px solid var(--rule);
  display: grid; grid-template-columns: minmax(0, 62ch);
  font-size: var(--t-small); color: var(--ink-2); line-height: 1.7;
}
.register .rule b { color: var(--ink); font-weight: 600; }
.register .rule .m { display: block; min-width: 0; }

/* ==========================================================================
   THE BOARD — a tenant directory. Every trade a link into the app, each a
   paper tile with its own pictogram, in chapters whose heads stick under
   the bar. The keyline is the hairline, not ink; the pictogram and the lift
   under the pointer carry the affordance.
   ========================================================================== */
.board { padding: var(--s8) 0; }
/* THE CHAPTER STRIP is the board's own row, ruled above and below, between
   the heading and the census (2026-09-08: at the smallest link size on the
   page, under the note and 23px over chapter 01's rule, it read as chapter
   01's furniture). The links are the hero's quiet links: body size,
   regular weight, the hairline underline. */
.chapters {
  display: flex; flex-wrap: wrap; gap: var(--s2) var(--s5);
  margin: var(--s5) 0 0; padding: var(--s4) 0;
  border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule);
}
.chapters a {
  font-family: var(--sans); font-size: var(--t-body); font-weight: 400; letter-spacing: 0;
  color: var(--ink-2); text-decoration: none;
  border-bottom: 1px solid var(--rule); padding-bottom: 2px;
}
.chapters a:hover, .chapters a:focus-visible { color: var(--ink); border-bottom-color: var(--ink); }
.chapters a:active { color: var(--ink); border-bottom-color: var(--ink); }
.board .note {
  margin: var(--s4) 0 0; max-width: 62ch;
  font-size: var(--t-body); color: var(--ink-2);
}
.board .note p { margin: 0; }
.board .note b { color: var(--ink); font-weight: 600; }
/* What the lines mean, folded under the count (2026-09-08: the census ran
   31 lines in one column, then 13 in two; the face is now five sentences
   in one column, and the definitions and the unread registers open from
   the same ring the census and the plate's list use). */
.board .note .rest { margin-top: var(--s3); }
.board .note .rest summary {
  display: inline-flex; align-items: center; gap: var(--s2);
  cursor: pointer; color: var(--ink);
}
.board .note .rest summary:hover, .board .note .rest summary:focus-visible { text-decoration: underline; text-underline-offset: 3px; }
.board .note .rest p { margin-top: var(--s2); }
.dir { margin-top: var(--s6); }
.dir-sec + .dir-sec { margin-top: var(--s7); }

/* The chapter head sticks under the bar (top is the bar's token, S10),
   opaque paper so names slide under it, a 2px ink rule and the cast as the
   depth cue. min-height is a floor: the row may wrap at a large root font. */
.dir-sec > .hd {
  position: sticky; top: var(--bar); z-index: 10;
  display: flex; align-items: baseline; gap: var(--s3);
  flex-wrap: wrap;
  min-height: var(--sec-h);
  padding-bottom: var(--s2); margin-bottom: var(--s3);
  background: var(--paper);
  border-bottom: 2px solid var(--ink);
  box-shadow: 0 3px 0 var(--cast);
}
.dir-sec > .hd .ord {
  flex: none;
  font-family: var(--mono); font-size: var(--t-micro);
  letter-spacing: .14em; color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.dir-sec > .hd .t {
  margin: 0; font-weight: 400;
  font-family: var(--serif); font-size: var(--t-head);
  line-height: 1.2; letter-spacing: 0; text-transform: none; color: var(--ink);
  text-wrap: balance;
}
.dir-sec > .hd .c {
  margin-left: auto;
  font-family: var(--mono); font-size: var(--t-micro); letter-spacing: .08em; color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.dir-sec > .hd .up, .dir-sec > .hd .open {
  flex: none;
  font-family: var(--sans); font-size: var(--t-micro); font-weight: 600; letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink-2); text-decoration: none;
  border-bottom: 1px solid var(--rule); padding-bottom: 2px;
}
.dir-sec > .hd .up:hover, .dir-sec > .hd .up:focus-visible, .dir-sec > .hd .up:active,
.dir-sec > .hd .open:hover, .dir-sec > .hd .open:focus-visible, .dir-sec > .hd .open:active { color: var(--ink); border-bottom-color: var(--ink); }
/* On a phone the head's five parts do not fit one row, and left to wrap
   the last link dangled alone on a second line (measured at 390, 2026-09-08).
   The break is placed: ordinal, title and count on the first row, the two
   links together on the second, by a full-width flex item between them.

   CHECKED AGAIN 2026-09-16, because a type raise moves a wrap threshold and
   this one is a hand-placed break sitting on a hand-chosen width. All eight
   heads render 40.6px — one row — at 601, 620, 640, 660, 680, 700, 740, 780,
   820, 880, 1001 and 1280, and 84.4px — the placed two — at 600 and 560. The
   600 still lands where the natural wrap does, so it stays. */
@media (max-width: 600px) {
  .dir-sec > .hd .open, .dir-sec > .hd .up { order: 1; }
  .dir-sec > .hd::after { content: ''; flex: 1 0 100%; order: 0; height: 0; }
}

.dir-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(min(190px, 100%), 1fr));
  gap: var(--s4);
  list-style: none; margin: 0; padding: 0;
}
/* four to a row from 880 up and at every width above it: 62 tiles in eight
   chapters of 2..14 fall on four with no lone last tile in any chapter that
   five left one in (2026-09-08), and the sub-lines stop breaking after
   their dot */
@media (min-width: 880px) { .dir-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
/* every entry offsets its scroll landing by the bar and the head under it */
.dir-grid > li {
  display: flex;
  scroll-margin-top: calc(var(--bar) + var(--sec-h) + var(--s2));
}
.dir-grid > li > .door { flex: 1; }

.door {
  display: grid;
  grid-template-columns: minmax(0, auto) minmax(0, 1fr);
  column-gap: var(--s3);
  align-items: start;
  align-content: start;
  padding: var(--s4);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  background: var(--paper);
  color: var(--ink);
  text-decoration: none;
  box-shadow: 2px 2px 0 var(--cast);
  transition: transform .14s var(--ease), box-shadow .14s var(--ease), border-color .14s var(--ease);
}
/* the phone's run of 62 one-per-row tiles is a quarter shorter with the
   tile's vertical padding and the gap one rung down each (2026-09-08:
   62 tiles at 89px, 5,490px of tiles)

   RE-MEASURED 2026-09-16 after the raise, audit-type-boxes: still 62 tiles in
   8 sections, and they run 3,955.7px at 390 and 4,026.3 at 340, where one
   name takes a second line. The tallest tile is 85.7px. The "quarter shorter"
   above is the 2026-09-08 comparison against the un-overridden tile and has
   NOT been re-taken — it would need the override switched off in a render,
   which is a different run than this one. Today's totals are measured; that
   ratio is inherited. */
@media (max-width: 480px) {
  .door { padding: var(--s2) var(--s3); }
  .dir-grid { gap: var(--s2); }
}
.door .pic {
  grid-column: 1; grid-row: 1 / span 3;
  align-self: center;
  width: 2rem; height: 2rem;
}
.door .nm, .door .ins { grid-column: 2; }
.door .nm {
  display: block;
  font-family: var(--serif); font-size: var(--t-lede); line-height: 1.25;
  min-width: 0; overflow-wrap: break-word; hyphens: auto;
  text-wrap: balance;
}
/* visited rides the tile's own ink, one rung down; declared before hover */
.door:visited { color: var(--ink-2); }
.door .ins {
  display: block; margin-top: var(--s1);
  font-family: var(--sans); font-size: var(--t-micro); letter-spacing: 0;
  color: var(--ink-3); font-variant-numeric: tabular-nums;
}
/* hover lifts and inks the keyline; press sets flat — geometry, so both
   survive forced colours */
.door:hover { transform: translateY(-1px); box-shadow: 3px 3px 0 var(--cast); border-color: var(--ink); }
.door:active { transform: translate(2px, 2px); box-shadow: none; }

/* ==========================================================================
   THE WITHDRAWAL, taped off. The page's argument ends on the number we
   deleted, and it is the cordon: hazard tape above and below, the ledger
   on the plate. This is where the sign colours are spent at full strength,
   because this is the one place the page is a sign.
   ========================================================================== */
.withdrawn { padding: var(--s8) 0; }
.taped { border-radius: var(--r); overflow: hidden; }
/* ISO 3864-1 clause 11: bands of equal width at 45 degrees (L7). */
.hazard {
  height: 12px;
  background: repeating-linear-gradient(-45deg, var(--hi) 0 11px, var(--plate) 11px 22px);
}
.taped-in {
  background: var(--plate);
  padding: var(--s7) var(--s7);
}
.taped-in .grid {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 440px); gap: var(--s8);
  align-items: start;
}
@media (max-width: 900px) { .taped-in .grid { grid-template-columns: minmax(0, 1fr); gap: var(--s6); } }
@media (max-width: 480px) { .taped-in { padding: var(--s6) var(--s4); } }
.taped-in h2 {
  margin: var(--s3) 0 var(--s4);
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(1.75rem, 3.2vw, 2.375rem); line-height: 1.1; letter-spacing: -.018em; text-wrap: balance;
  max-width: 20ch;
  color: var(--p-ink);
}
.taped-in .eyebrow { color: var(--p-ink-3); }
/* a stamp is machine-readable and sets in the mono, like the bar's: the
   withdrawal date was the one stamp in the eyebrow's sans (2026-09-08) */
.stamp-w { font-family: var(--mono); letter-spacing: .08em; }
.taped-in p { font-size: var(--t-body); color: var(--p-ink-2); max-width: 62ch; }
.taped-in p b { color: var(--p-ink); font-weight: 600; }

.ledger {
  border: 1px solid var(--p-rule); border-radius: var(--r);
  background: var(--p-sunk);
  padding: var(--s4) var(--s5) var(--s5);
}
.ledger .cap {
  display: block; padding-bottom: var(--s3); margin-bottom: var(--s3);
  border-bottom: 1px solid var(--p-rule);
  color: var(--p-ink-3);
}
.ledger .row {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--s4);
  padding: 7px 0;
  font-family: var(--mono); font-size: var(--t-body);
  font-variant-numeric: tabular-nums;
}
.ledger .row .in { color: var(--p-ink); }
.ledger .row .out { color: var(--rust); text-decoration: line-through; text-decoration-thickness: 1px; }
.ledger .note {
  margin-top: var(--s3); padding-top: var(--s3); border-top: 1px dashed var(--p-rule);
  font-size: var(--t-small); color: var(--p-ink-2); line-height: 1.65;
}
.ledger .stamp-out {
  margin-top: var(--s4);
  font-family: var(--mono); font-size: var(--t-micro);
  letter-spacing: .12em; text-transform: uppercase; color: var(--rust);
  border: 1px solid var(--rust); border-radius: var(--r);
  padding: 5px 9px; display: inline-block;
}

/* --------------------------------------------------------------------------
   Footer — the colophon, on the same paper under a 2px ink rule.
   -------------------------------------------------------------------------- */
/* TOP PADDING ONLY. The close is the last child of this footer and it is a
   plate that runs to the bottom of the page; a bottom pad here would leave a
   band of paper under it and turn a close into a floating panel. The air
   below the colophon is the close's own top margin, so the two numbers stay
   one number. */
.foot {
  border-top: 2px solid var(--ink);
  padding: var(--s8) 0 0;
}
.foot .cols {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); gap: var(--s6);
}
/* two columns between 601 and 1000px with the third block across both
   (2026-09-08: at 768 it sat under the first with the cell beside it
   empty), one column under that */
@media (max-width: 1000px) {
  .foot .cols { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .foot .cols > div:last-child { grid-column: 1 / -1; }
}
@media (max-width: 600px) { .foot .cols { grid-template-columns: minmax(0, 1fr); } }
/* A MEASURE ON THE COLOPHON, ADDED 2026-09-16, because it was the longest
   line on the page and no clause could see it. The third block spans both
   columns from 601 to 1000px (the rule above, written 2026-09-08 because at
   768 it sat under the first with the cell beside it empty) — a good fix that
   bought a 124-character line. Measured on the running page at 768 and at
   880: 124.3 characters, against the 45..75 this page holds its own prose to.
   The other two blocks never reach the cap; at 1440 they set 62 characters in
   a three-column grid, which is 51ch, so this binds on the wide block alone
   and leaves paper to its right, which is what a measure looks like.

   WHY NO GATE CAUGHT IT. Clause 400 S3 audits every ch cap on the page and
   resolves it at the size its text is set at — but a rule with NO cap has no
   cap to audit, so prose with no measure at all is the one shape that clause
   cannot see. The hole is in the question, not the reader. 60ch and not 62:
   S3 converts a ch to characters at this page's own 0.5391/0.446, so 62ch
   scores 74.94 and rounds to exactly the 75 it refuses to exceed, and a
   measure should not sit on the boundary of the law that measures it. */
.foot p { margin: var(--s2) 0 0; max-width: 60ch; font-size: var(--t-small); color: var(--ink-2); line-height: 1.7; }
/* the attribution runs the width of the colophon: a list of publishers, a
   filename and a date, not prose; the filename is held whole */
.foot .attrib {
  margin-top: var(--s6); padding-top: var(--s4); border-top: 1px solid var(--rule);
  /* mono, so 75 characters: it ran 150 a line at 1440 before this cap.
     Re-measured 2026-09-16 at 12px micro: the cap is 527.3px, it binds from
     600 up, and the credit sets 317 characters over 5 lines at 1440 — 63.4 a
     line, inside the 45..75 band clause 400 S3 holds prose to. */
  max-width: 75ch;
  font-family: var(--mono); font-size: var(--t-micro); color: var(--ink-3); line-height: 1.7;
}
.foot .attrib .f { white-space: nowrap; }
.dim { color: var(--ink-3); }

/* ==========================================================================
   THE CLOSE: the family, and then the company. Both on the plate.

   THE ROW IS THE FAMILY, READ FROM ONE FILE. simpler.capital publishes
   family.json, and every card in the row is one live property out of it,
   in the file's own order. Simpler.Run is not among them: the site you are
   standing on does not sell itself to you.

   ONE CARD FOR THE WHOLE FLEET (owner, 2026-09-28): the eight Simpler
   sites' strips are one style, and simpler.legal is the reference. The card
   rules at the end of this block are stamp-family.mjs --css as it printed
   them, unchanged. What this sheet adds is the page's side of that contract.
   The stamp reads --sheet (the ground the cards stand on), --text-2 (the
   second ink) and --line (the hairline); the close is a plate, so those are
   the plate, the plate's second ink and the plate's rule. The names take the
   plate's first ink, and the row is set at the body size rather than the lede.

   THE FIRST CARD SPANS THE ROW (owner, 2026-09-28: "the largest full widths
   one will be simpler.host", at the top). family.json's order minus this
   site puts Simpler.Host first, so no card moves; the six under it sit two
   to a row, and at or below 760px it is all one column. The lone-last-card
   rule that stood here is gone on purpose: seven cards leave the seventh an
   odd last child, and it would span as well.

   Each card's ground, --fam-g, is written into the markup from family.json,
   and the stamp mixes it into the plate: an 8% wash, a 20% corner, a 26%
   edge. The 34px mark beside the name is the property's favicon, drawn on
   its own ground, so it reads the same in every palette.
   ========================================================================== */
.close {
  margin-top: var(--s8);
  padding: var(--s7) 0;
  background: var(--plate);
  color: var(--p-ink-2);
}
.close .eyebrow { color: var(--p-ink-3); }

.family { --sheet: var(--plate); --text-2: var(--p-ink-2); --line: var(--p-rule); color: var(--p-ink); font-size: var(--t-body); }
.fams>.fam:first-child{grid-column:1/-1}
.fams{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;margin:22px 0 0}
.fam{position:relative;display:flex;flex-direction:column;gap:9px;padding:16px 44px 16px 18px;border-radius:6px;text-decoration:none;color:inherit;
  background-color:color-mix(in srgb,var(--fam-g) 8%,var(--sheet,#fff));
  background-image:linear-gradient(155deg,color-mix(in srgb,var(--fam-g) 20%,transparent) 0%,transparent 58%);
  border:1px solid color-mix(in srgb,var(--fam-g) 26%,var(--line,rgb(0 0 0 / .12)))}
.fam:hover{background-color:color-mix(in srgb,var(--fam-g) 14%,var(--sheet,#fff));border-color:color-mix(in srgb,var(--fam-g) 55%,var(--line,rgb(0 0 0 / .22)))}
.fam-side{display:flex;flex-direction:column;gap:9px;min-width:0}
.fam-head{display:flex;align-items:center;gap:11px}
.fam-mk{width:34px;height:34px;flex:none;border-radius:5px}
.fam-head b{font-weight:620;letter-spacing:-.01em}
.fam-what{color:var(--text-2,#5c5750)}
.fam-out{position:absolute;top:14px;right:16px;color:var(--text-2,#5c5750);font-size:.76rem}
.fam:hover .fam-out{color:inherit}
@media (max-width:760px){.fams{grid-template-columns:1fr}}

/* --------------------------------------------------------------------------
   The corporate line. A masthead, in the mono the page uses for anything a
   machine also reads, and the one credit this page carries.
   -------------------------------------------------------------------------- */
.corp {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--s3) var(--s5);
  margin-top: var(--s7); padding-top: var(--s4);
  border-top: 1px solid var(--p-rule);
  font-family: var(--mono); font-size: var(--t-micro);
  letter-spacing: .04em; color: var(--p-ink-3);
}
.corp-mail { color: var(--p-ink-2); text-decoration-thickness: 1px; text-underline-offset: 3px; }
/* ELESSAR'S ART IS ELESSAR'S. #EFF0F1 is their reversed-lockup colour, the
   one their spec allows on a dark ground, and it is deliberately NOT a token
   here: a token is a colour this page owns and may re-derive, and this is a
   colour we are only allowed to reproduce. The wordmark is outlines rather
   than live text for the same reason the rest of this page carries no web
   font — set as text it would fall to Arial on a Windows machine and be the
   one thing on the page rendered in the wrong face. The only thing done to it
   is opacity, so it sits at the brightness of the line it is in. */
/* min-height is the tap floor and nothing else: the credit is a link whose
   ink is 18.6px tall (hit-tested at 390 on 2026-09-16, 20px of target), and
   it is the one link in this row that is NOT inside a sentence — the mail
   address beside it sits in the company line and takes the same exemption a
   target in a sentence takes everywhere else on this page. The mark's own
   height is set below in em and is untouched by this. */
.cred { display: inline-flex; align-items: center; min-height: 24px; gap: var(--s2); text-decoration: none; }
/* 17px until 2026-09-16, and the 17 was never a size — it was a COINCIDENCE
   with a line box. .corp is set in --t-micro and takes body's 1.55 leading,
   which was 11 x 1.55 = 17.05px, so the artwork matched the type beside it to
   within a twentieth of a pixel and the masthead row read as one object. At
   --t-micro 12px the line box is 18.6 and a 17px mark sits 1.6px short, with
   the row's height set by the text instead of by the mark. 1.55em is the same
   number said as a relation, so it tracks the token instead of shadowing it:
   18.6px today, and right at whatever the rung becomes next. The fills and
   the .62 are untouched — the comment below is explicit that the colour is
   reproduced under licence and is not this page's to tokenise. */
.cred-mk { height: 1.55em; opacity: .62; }
.cred-gem { stroke: #EFF0F1; }
.cred-wd { fill: #EFF0F1; }
.cred:hover .cred-mk, .cred:focus-visible .cred-mk { opacity: 1; }
/* THE PHONE'S SPACING PAIR: every section's pair halves, the hero's with it,
   so a break between sections is not a fifth of the screen (measured
   2026-09-08 at 390: about 150px between the specimen and the register). */
@media (max-width: 480px) {
  .hero { padding: var(--s4) 0 var(--s6); }
  .register, .board, .withdrawn { padding: var(--s6) 0; }
  .foot { padding: var(--s6) 0 0; }   /* the close carries the bottom, as above */
  .close { margin-top: var(--s6); padding: var(--s6) 0; }
}
/* TAP HEIGHTS. At and under 1000px the two card summaries reach 44px of hit
   area (SC 2.5.5, the AAA figure) through a floor on their own box; the
   receipt's, the ledger's, the plate's and the folds' summaries reach 24px
   (SC 2.5.8, the AA figure) so a ledger of five short rows sits tight
   (2026-09-08: at 44px each the phone ledger read as a form); the underlined
   links through a hit box drawn round the text so the hairline stays under
   the letters. Type unchanged.

   AND THE BRACKET WAS DOING MORE THAN IT SAID (hit-tested 2026-09-16, at
   340, 390, 480, 768 and 1440, by asking the page where a tap still lands on
   the control rather than by reading rects — a ::after pad is in no
   element's getBoundingClientRect, so a sweep that read rects would report
   the four padded controls as failing a floor they already have). Under
   1000px the page came out clean: everything clears 24px on the glass except
   .skip, which is 1x1 until it takes focus and which a pointer never sees,
   and three links inside sentences — the licence line, the facts-file link
   and the support address — the case both criteria carve out inline, and the
   one the app's clause 433 already exempts in the same words for .attrib a.
   ABOVE 1000px it came out at forty: twenty-two summaries at 18 to 21.4px
   and sixteen chapter and directory links at 21.6px, all of them under the
   floor because this block, and only this block, was lifting them.

   2.5.8 IS NOT A RULE ABOUT PHONES. So the AA figure now stands on its own
   below, unbracketed, and what stays in here is what genuinely belongs to a
   thumb: the AAA 44px on the two card summaries, and the pads. The plate's
   by-name list and the Elessar credit carry their own 24px at their own
   rules, with the argument written beside each.

   AFTER, re-hit-tested the same day: under 1000px nothing is left but .skip
   and the sentence links; above 1000px the twenty-two summaries are lifted
   and SIXTEEN REMAIN — eight "chapters up" and eight "open in the app", at
   22 to 23px of hit area, one to two pixels short. They are left short on
   purpose. The only mechanism that reaches them is the pad, and a pad is the
   one grant that can take a neighbour's ground: 21.6px of link inside a
   41.6px box, in a directory where the next control is a row away. Under
   1000px that trade is worth making, because a thumb is 8mm wide and misses.
   Above it the pointer is a mouse, which does not miss by two pixels, and
   the cost of being wrong is a reader sent to the wrong chapter. If the
   directory layout is ever measured for overlap at desk widths, this is the
   paragraph to come back to. */
/* The AA floor, applied through :where() so it carries no specificity and any
   rule that needs a bigger target simply takes it. A summary that sits INSIDE
   a sentence is an inline box and min-height does nothing to it, which is the
   right answer twice over: those are the inline carve-out. */
:where(summary) { min-height: 24px; }
@media (max-width: 1000px) {
  .fact .more summary, .fact .census summary { min-height: 44px; }
  /* the 24px line for the receipt's, the ledger's, the plate's and the folds'
     summaries stood here from 2026-09-08 until 2026-09-16, when it became
     :where(summary) above and stopped being a phone rule. Its reasoning is
     unchanged and is kept in the comment at the head of this block; what
     changed is the set it covers, which is now every disclosure on the page
     at every width, and it is written here because a reader looking for that
     line should find out where it went rather than that it is gone. */
  .ghost, .chapters a, .dir-sec > .hd .up, .dir-sec > .hd .open { position: relative; }
  .ghost::after, .chapters a::after, .dir-sec > .hd .up::after, .dir-sec > .hd .open::after {
    content: ''; position: absolute; left: 0; right: 0; top: -10px; bottom: -10px;
  }
  .hero .cta { row-gap: var(--s4); }
}

/* --------------------------------------------------------------------------
   Motion — the gauges draw themselves once, and nothing waits on a script to
   be allowed to exist.
   -------------------------------------------------------------------------- */
@keyframes draw { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes rise { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.spread .span, .fact .cover .fill { animation: draw .9s var(--ease) both; }
.spread .tick { animation: rise .5s var(--ease) .5s both; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .spread .span, .fact .cover .fill, .spread .tick { animation: none; }
  .go:hover, .door:hover, .door:active { transform: none; }
}

/* FORCED COLORS. The user's palette replaces ours, so the two structural
   axes of the ladder are restated in system colours, every gauge keeps two
   visible ends, and every state that was only a colour gets a width. The
   ramp cannot survive a two-colour palette: the island falls back to the
   three tones it had before the ramp — text ink for a corner with its own
   rent, GrayText for a district band, Canvas for neither — and the key's
   swatches say the same.

   MEASURED 2026-09-16, and the measuring is the point: node
   audit-forced-colors.js walks every element in this mode, compares every
   painted colour against the palette the page is asked for, and then
   photographs the page and counts the pixels. Six of our colours were on the
   glass in a palette a reader had chosen. What the run established, because
   none of it can be read off a spec:

     - Chrome forces color, background-color and border-color, and an
       author's SYSTEM colour survives forcing untouched. So most of this
       block would work without forced-color-adjust: none at all.
     - it does NOT force fill or stroke on anything inside an <svg>, which
       take the UA's preserve-parent-color. Every SVG paint in this mode has
       to be restated here or it keeps our ink.
     - it does NOT remove a background-color from an <svg> either: the four
       family tiles kept their brand grounds.
     - it DOES drop a gradient (background-image: none), which is why .hazard
       and the warning track opt out: a hatch is the one thing here that
       cannot be said in flat system colours.
     - text-decoration-color reads back as ours from getComputedStyle and
       paints as the reader's. The underlines were never leaking; the walk
       over-reported them and the photograph cleared them. Nothing is written
       here for underlines for that reason.

   AND THE TRAP THIS BLOCK IS IN, which is the whole reason six colours were
   on the glass: every rule here is written against the SHAPE of the rule it
   overrides, and the sheet above it keeps growing more specific ones. On
   2026-09-16 `.island-cap .sw { border: 1px solid CanvasText }` was beaten by
   `.island-cap .ramp .sw`, added that morning, and the key's five swatches
   were edged in the paper's own hairline — 688 pixels of rgb(106, 97, 68) in
   a palette the reader chose, under a rule whose comment said CanvasText. The
   same trap had `.island .z { stroke: CanvasText }` beaten by
   `.island .z.none`, and `.mark.warning .band`'s own border beaten by the
   generic `.band` rule. Every override below therefore names the SAME
   selector the sheet above uses, or a more specific one, and clause 437
   holds that: a colour property this block cannot reach is a colour that
   ships to the reader wearing our brand. */
@media (forced-colors: active) {
  /* THE FOCUS RING FIRST, BECAUSE AN OPT-OUT KEEPS ITS OUTLINE TOO. Every
     forced-color-adjust: none in this block is a promise that the element's
     colours are handled here, and an outline is one of its colours: the UA
     stops repainting the ring the moment we stop it repainting the box. The
     one focusable element under an opt-out today is .cred, the credit link,
     and its ring was --ink, #1C1707 — our near-black, on the black ground of
     the theme a reader most often turns this mode on to get. Invisible focus
     on a link is the worst thing on this list, and it was reachable by
     Tab from the moment the chip below was written. (Found by clause 437 on
     its first run, 2026-09-16.) This is written universally rather than at
     .cred so the next opt-out cannot reintroduce it.

     The halo goes with it. `box-shadow: 0 0 0 7px var(--paper)` exists to
     hold the ring off a busy ground; in this mode the ground is one flat
     system colour with nothing to hold off, and a 7px band of #F7F4EC around
     a focused control is simply our paper drawn on the reader's page. A
     shadow is not layout, so removing it moves nothing. */
  :focus-visible { outline-color: CanvasText; box-shadow: none; }
  .mark.caution { border: 1px solid CanvasText; }
  /* The sign left rule goes here. It exists to carry the mark's HUE down the
     block, and in this world there is no hue to carry: the UA repaints it
     CanvasText, which would give the caution rung a 3px left edge to stand
     against the warning rung's 3px border and muddle the one axis this world
     still has. The keyline carries the ladder here, alone and on purpose. */
  .mark.caution .in { border-left: 0; }
  .mark.warning { border: 3px solid CanvasText; }
  /* border-color AND NOT just the background: `.band` (the generic one, the
     section rule) sets a border-top in --rule, and `.mark.warning .band` had
     no border of its own here to beat it. Measured: 352 pixels of
     rgb(145, 128, 78) drawn across the top of the black band. On a band that
     is CanvasText from edge to edge the rule has no work left to do, so it
     goes to CanvasText and disappears into the band rather than being
     removed: a border-width is a layout, and THIS declaration would be moving
     the band to hide a colour, which is the wrong tool reached for the wrong
     reason.

     That is a rule about this declaration, not a law about this block, and it
     was written as a law once and was not one: the block moves the page in
     eight places on purpose — the caution rung's left rule to 0, the ramp's
     swatches to display: none, the .hcnote and the third .off entry to shown,
     two border widths on hover, the .cred chip's new edge. Each is its own
     argument, made where it is spent. Re-based 2026-09-16 after a reviewer
     read the sentence as the promise it was phrased as. */
  .mark.warning .band { background: CanvasText; color: Canvas; border-color: CanvasText; forced-color-adjust: none; }
  /* AND THE SUB-LABEL ON IT. forced-color-adjust INHERITS, so the band's
     opt-out reaches every span inside it, and `.mark.warning .band .sub`
     sets --p-ink-2: 99 pixels of rgb(180, 170, 138) reading "THIS IS A
     FLOOR: IT UNDERSTATES BY CONSTRUCTION" in our olive on the reader's
     black. Canvas is what the band already gives its own text. */
  .mark.warning .band .sub { color: Canvas; }
  .hazard {
    forced-color-adjust: none;
    background: repeating-linear-gradient(-45deg, CanvasText 0 11px, Canvas 11px 22px);
    border-top: 1px solid CanvasText; border-bottom: 1px solid CanvasText;
  }
  .spread .track, .fact .cover .track {
    background: Canvas; box-shadow: none; border: 1px solid CanvasText;
  }
  .spread .span, .fact .cover .fill, .fact.warning .cover .fill {
    background: CanvasText; forced-color-adjust: none;
  }
  .spread .tick { background: CanvasText; forced-color-adjust: none; }
  .fact.warning .cover .track {
    forced-color-adjust: none;
    border: 2px solid CanvasText; box-shadow: none;
    background: repeating-linear-gradient(-45deg, CanvasText 0 2px, Canvas 2px 5px);
  }
  .go { border: 1px solid CanvasText; }
  .ghost:hover { border-bottom-width: 2px; }
  .ghost:active { border-bottom-width: 2px; }
  .dir-sec > .hd { background: Canvas; border-bottom: 2px solid CanvasText; }
  .door { border: 1px solid CanvasText; }
  .door:hover { background: Highlight; }
  .door:hover .nm, .door:hover .ins { color: HighlightText; }
  .door:active { background: Highlight; }
  .door:active .nm, .door:active .ins { color: HighlightText; }
  .chapters a:hover, .chapters a:focus-visible, .chapters a:active { border-bottom-width: 2px; }
  .island-fig { border: 1px solid CanvasText; }
  .island .z { fill: Canvas; stroke: CanvasText; forced-color-adjust: none; }
  .island .z.own, .island .z.own[data-b="0"], .island .z.own[data-b="1"], .island .z.own[data-b="2"], .island .z.own[data-b="3"], .island .z.own[data-b="4"] { fill: CanvasText; }
  /* stroke on BOTH, because `.island .z` above is one class short of these
     two and lost: 83 of the 332 corners were outlined in --noval-line, our
     grey, in the reader's palette */
  .island .z.band { fill: GrayText; stroke: CanvasText; }
  .island .z.none { fill: Canvas; stroke: CanvasText; }
  /* THE FOURTH TONE IS THE ONE THIS MODE HAS NO KEYWORD LEFT FOR (2026-09-16).
     The palette hands out four values and the drawing had already spent three:
     CanvasText for a shopfront rent, GrayText for a district band, Canvas for
     nothing. Highlight is the fourth and it is not free — this block spends it
     on "the one you are on", eleven lines down — and a tone that borrows the
     selection colour is a corner that looks permanently hovered.

     So the fourth state is made out of the two it sits between, as texture
     rather than as a fifth colour: the band's GrayText ground carrying the
     own-rent CanvasText as dots. It cannot be read as `none`, which is Canvas
     and empty; it cannot be read as `band`, which is the same grey with
     nothing on it; and it cannot be read as `own`, which is solid ink. The
     drawing's own <pattern> does the work, so this is the one place in the
     sheet where .dg and .dl are painted in the reader's palette.

     .z.band is filled SOLID above and never reaches the hatch, so these two
     declarations today paint exactly one tone. That is a coupling, not a
     coincidence: drop the solid band override and the hatch starts drawing in
     these colours the same day. Named here so it is a decision when it
     happens. */
  .island .dg { fill: GrayText; }
  .island .dl { fill: CanvasText; }
  .island .z.other { fill: url(#otherclass); stroke: CanvasText; }
  /* AND THE CORNER'S HOVER, WHICH TOOK TWO CUTS AND A MEASUREMENT.
     .island .z opted the path out of forcing, so --p-ink shipped as #DDD8C9 on
     all 332 corners the moment a pointer reached one. The first cut sent the
     stroke to CanvasText on the reasoning the rule above used to carry: that
     the indicator is really the WIDTH, 0.6 to 1.4, and the colour is decoration
     on top. That reasoning was never rendered, and it is wrong. The resting
     stroke in this mode is ALREADY CanvasText on all three corner classes, so a
     CanvasText hover stroke changes nothing at all and leaves 0.4px of outward
     growth drawn in the shape's own colour: 28 changed device pixels on
     Singapore River, 48 on Bishan, 66 on Geylang, and at the island's real
     rendered size even a good case like Bedok moves 344 of 730,752 — rest and
     hover indistinguishable, where paper draws a complete outline.

     THE SECOND CUT WAS `stroke: Highlight`, AND THE NUMBER THAT SOLD IT WAS
     THE WRONG NUMBER. It moved 9,390 device pixels on Bishan where CanvasText
     moved 48, and a pixel diff answers "did anything change", never "can
     anyone see it". Highlight is rgb(55, 0, 110) in the light palette and the
     corner under it is filled CanvasText: 1.41:1, a stroke that changes
     thousands of pixels and is invisible in every one of them.

     There is no single stroke colour that can work. The three fills in this
     mode are CanvasText, GrayText and Canvas, and the only keyword guaranteed
     to read on CanvasText is Canvas, which is the very thing .z.none is filled
     with. A pair only promises to contrast with ITS OWN other half.

     So take a whole pair. Highlight with HighlightText is the one the page
     already spends on "this is the one you are on" — .door:hover has used it
     since this block was written — and the guarantee travels with it: the
     hovered area fills Highlight and keeps its edge in HighlightText, which
     contrasts with that fill by definition, on any theme, without this file
     having to know which end of anything it is standing on. The area's own
     resting tone is hidden for as long as a pointer sits on it, which is what
     a selection is. (The :focus-visible half is dead here and in the rule
     above: all 55 island links carry tabindex="-1". It is kept so this
     override names the same selector the sheet does, which is clause 437.)

     AND THE SELECTOR IS LONGER THAN THE ONE IT OVERRIDES, which is this
     block's oldest lesson arriving from inside the block itself. The sheet's
     hover rule is `.island a:hover .z`, three classes and an element. It is
     enough on paper. It is not enough HERE, because the tone rules this hover
     has to beat are in this block too, and one of them is
     `.island .z.own[data-b="0"]` at four: all 249 own corners carry a data-b,
     so a fill written at .island a:hover .z would have lost to the resting
     tone on three quarters of the map and read correctly while doing it.
     Naming the three tone classes puts this at four and an element. Clause 437
     does not catch this one — it holds the block against the SHEET, and this
     was the block against itself. Clause 438 was written the same day for
     exactly that, and carries this rule flattened back to three classes as its
     red arm, so the next state written one class short fails on the bench
     instead of on a reader's machine. */
  .island a:hover .z.own, .island a:hover .z.other, .island a:hover .z.band, .island a:hover .z.none,
  .island a:focus-visible .z.own, .island a:focus-visible .z.other, .island a:focus-visible .z.band, .island a:focus-visible .z.none {
    fill: Highlight; stroke: HighlightText;
  }
  .island-cap .sw { forced-color-adjust: none; border: 1px solid CanvasText; }
  .island-cap .sw.b0, .island-cap .sw.b1, .island-cap .sw.b2, .island-cap .sw.b3, .island-cap .sw.b4 { background: CanvasText; }
  .island-cap .sw.band { background: GrayText; }
  .island-cap .sw.none { background: Canvas; }
  /* the swatch says the same thing the corner does, in the same two colours:
     the band's grey carrying the own-rent ink as dots. `background` is
     written whole so the paper rule's two-layer shorthand and its
     background-size cannot survive into this mode half-overridden. */
  .island-cap .sw.other {
    background: GrayText radial-gradient(circle at 50% 50%, CanvasText 0 42%, transparent 42%);
    background-size: 4px 4px;
  }
  /* the tone the drawing gives a corner that publishes its own rent, shown
     once here and drawn nowhere else: on paper those 249 are the ramp */
  .island-cap .sw.own { background: CanvasText; }
  /* THE BORDERS, AT THE SPECIFICITY THE SHEET ABOVE USES. `.island-cap .sw`
     is two classes and both of the rules it is meant to override are three:
     the ramp's hairline (--p-rule, 2026-09-16) and the off-ramp pair's
     (--noval-line, older). This is the 688-pixel leak named in the essay at
     the head of this block. */
  .island-cap .ramp .sw, .island-cap .off .sw { border-color: CanvasText; }
  /* THE KEY STOPS DRAWING A RAMP IT IS NOT DRAWING. All five swatches are
     CanvasText here — correctly, because all 249 corners are — and five
     identical blocks under a cap reading CHEAPEST → DEAREST is a figure
     claiming a distinction the drawing does not make. A reader cannot tell
     whether the shading is absent by design or broken on their machine.
     Patterning the five would be worse: the key would then claim five steps
     the map genuinely cannot draw at the size of a planning area.

     So the blocks go and the DATA stays. Every range and every count is
     still printed, in the same five columns and the same order, which is
     what the cap now labels — five figures running cheapest to dearest, and
     true. The tone itself is decoded once, beside the other two, in the row
     that decodes tones. And a line of words says which of the two it is,
     because the one thing the page must not do is leave that to be guessed.
     (2026-09-16. Nothing is deleted: .hcnote and the third .off entry ship
     in the markup at every width and are shown here.) */
  .island-cap .ramp .sw { display: none; }
  .island-cap .hcnote { display: block; }
  .island-cap .off > span.v-hc { display: inline-flex; }
  .dir-sec > .hd .up:hover, .dir-sec > .hd .up:focus-visible, .dir-sec > .hd .up:active,
  .dir-sec > .hd .open:hover, .dir-sec > .hd .open:focus-visible, .dir-sec > .hd .open:active { border-bottom-width: 2px; }
  .jump input { border: 1px solid CanvasText; }
  .also dd.rcpt summary:hover, .also dd.rcpt summary:focus-visible { text-decoration: underline; }
  /* THE FAMILY CARDS KEEP THEIR EDGE. A card's wash is a background on an
     <a> and its type is `color`, and the UA forces both, so the border is
     what keeps a card reading as a card once its colour is gone; the stamp's
     tinted corner is a background-image, and it goes with the wash. The 34px
     mark is the property's own favicon, whose fills are attributes on its
     <svg> and are not forced: it keeps its colours on the ground it carries
     inside itself, the way a picture would, and needs nothing here. The
     stamp's hover is a colour change and nothing else, which the UA would
     flatten to no hover at all (L8b), so it is restated in the reader's
     Highlight: the edge and the arrow. */
  .fam { border: 1px solid CanvasText; background-image: none; }
  .fam:hover { border-color: Highlight; }
  .fam:hover .fam-out { color: Highlight; }
  /* AND ELESSAR'S MARK KEEPS ITS COLOUR AND IS GIVEN ITS GROUND. #EFF0F1 is
     their reversed lockup, the version their spec allows on a dark ground,
     and the note at .cred-gem says it is a colour we may reproduce and not a
     token we may re-derive — so repainting it to CanvasText is not ours to
     do, in this mode or any other. On paper it sits on a dark footer. Here
     the footer is Canvas, and the credit rendered as "Powered by" followed by
     nothing at all: near-white artwork at .62 opacity on white, landing on
     rgb(245, 246, 246), which is 1.02:1 against the page.

     The fix is the ground, not the artwork. The link becomes the dark chip
     their lockup was drawn for, its words take the chip's own ink, and the
     opacity that tunes the mark to a light footer goes to 1 where the ground
     is black. forced-color-adjust: none is on the mark so that a browser
     which starts forcing SVG paint cannot repaint someone else's trademark
     on our behalf. The underline is put back by hand because a link that has
     lost LinkText has lost the one thing saying it is a link.

     AND THE OPT-OUT ON THE CHIP ITSELF IS LOAD-BEARING, which the first cut
     of this rule found out by rendering: forced colors paints a BACKPLATE
     behind text that sits on an author's background, in Canvas, so "Powered
     by" in Canvas on a CanvasText chip came out as a solid white rectangle —
     white ink on the white plate drawn to protect it. An element that sets
     both its ground and its ink has to opt out of the adjustment or the
     adjustment protects it from itself. .mark.warning .band, the other
     inverted block on this page, has said so since it was written.

     AND THE GROUND IS A LITERAL BLACK, WHICH IS THE SECOND CUT AND THE POINT.
     The first wrote `background: CanvasText`, and CanvasText is not a colour,
     it is a POSITION: the ink end of the reader's pair. In a light theme that
     is black and the chip was right. In a dark theme — the one this comment
     four lines up calls "the black ground of the theme a reader most often
     turns this mode on to get" — CanvasText is WHITE, so the chip came out
     white and #EFF0F1 landed on it at 1.141:1. That is the same defect this
     rule was written to fix, rebuilt by the rule that fixed it, and it shipped
     because the rig pinned prefers-color-scheme to light and could only ever
     render the half where the bug is not.

     AND THE RIG STILL CANNOT SEE IT, which is worth more than the fix. That
     pin is gone — audit-forced-colors.js walks both palettes now and prints
     which end each keyword resolved to — and the page-wide count it returns
     for this second cut is 1151/1285 light and 1405/1382 dark, the same
     numbers it gave for the first. It counts pixels that fall OUTSIDE the
     reader's palette, and black and white are IN both default palettes, so a
     chip painted the wrong end of the pair is never off-palette. It is only
     illegible, and those are different questions. Clause 439 asks the second
     one, statically, on the pairing rather than on the pixels.

     No system keyword can say "the dark end of the pair", because there is no
     keyword for an end — that is what a pair means. So the ground stops asking.
     A mark we may not repaint is a mark we owe a ground to, and we owe it in
     every palette, not in the one that happened to be convenient: the chip is
     #000 and its words are #FFF, and both of those are already exempt from the
     forcing this rule turns off on the line above. The border is what a black
     chip needs on a black Canvas, and it is the reader's, because an edge is
     ours to draw. (2026-09-16, second cut, found by review and measured in
     both palettes before and after.) */
  .cred {
    background: #000; color: #FFF; forced-color-adjust: none;
    border: 1px solid CanvasText;
    padding-inline: var(--s2); border-radius: 3px;
    text-decoration: underline; text-decoration-color: currentColor;
  }
  .cred-mk { opacity: 1; forced-color-adjust: none; }
}

/* PRINT. The body paints nothing; the marks keep their colour by the
   inherited rule that already keeps them; the plates come off and their
   inks re-base onto the page's own; objects that mean nothing in halves do
   not break; screen furniture is off.

   AND THIS BLOCK SETS NO FONT-SIZE, WHICH IS A DECISION AND NOT AN OMISSION.
   Added 2026-09-16, the day the floor pass went through app.css, because that
   sheet's print block does the OPPOSITE — it pins three sizes to literal px
   with the reason written beside them, "a sheet of A4 is a sheet of A4, a
   browser's type setting does not make the page wider" — and two sheets in
   one repo answering the same question two ways will read as one of them
   having been missed.

   Neither is wrong, because the two sizes are doing different jobs. The
   app's three are .attrib, a fixed-position credit that sits ON the map in a
   corner it has to fit; its size is geometry, so it is pinned. Everything on
   this page is a DOCUMENT, set in rem, and a reader who has told their
   browser they want 20px type has said something about reading, not about
   screens. Honouring that on paper is the whole point of rem. So the landing
   prints larger for a reader who asked for larger, and the map's credit does
   not, and both of those are the right answer to their own question. */
@media print {
  body { background: transparent; print-color-adjust: exact; -webkit-print-color-adjust: exact; }
  .taped-in {
    background: transparent; border: 1px solid var(--ink);
    --p-ink: var(--ink); --p-ink-2: var(--ink-2); --p-ink-3: var(--ink-3); --p-rule: var(--rule);
  }
  .island-fig {
    background: transparent; border: 1px solid var(--ink); box-shadow: none;
    --p-ink: var(--ink); --p-ink-2: var(--ink-2); --p-ink-3: var(--ink-3); --p-rule: var(--rule);
  }
  .mark, .fact, .ledger, .taped, .specimen, .also .pair, .door, .island-fig { break-inside: avoid; }
  .sec-head, .dir-sec > .hd, .fact .name { break-after: avoid; }
  .topbar, .skip, .jump, .island-cap .areas { display: none; }
}
