/* ═══════════════════════════════════════════════════════════════════════════
   THE SYSTEM — th-system.css · Law 100, 3 Sep 2026
   "ONE SYSTEM, EVERYWHERE, MISSING NOTHING." The owner's words on The Rebuild:
   "its the clean i expect on the whole platform all window all software,
   absolutely everything and missing nothing, it is to be a permanent law."
   One theme (light). One stylesheet. No page carries its own styling.
   Reference points: Stripe's tables and figure strips, Xero's calm header
   grammar, Mercury's one-number-first, Polaris' 4px scale, Anthropic's restraint.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── 1 · TOKENS ────────────────────────────────────────────────────────── */
/* TWO THEMES, ONE SYSTEM — defined 4 Sep 2026 on the owner's words: "please define the light and dark themes,
   in light it can have shades of navy in the tiles but never fully darkened out, i feel you need to still define
   the difference between the two."
   LIGHT (the default). The room is white and the sheets are white. Ink is Poseidon. Hairlines and shadows are
     Poseidon tinted. The accent is deep teal. A TILE MAY WEAR NAVY AS A WASH — the light steps of the Poseidon
     ramp, #F4F9FD down to #ABD1ED, with Poseidon ink on it — where a surface wants weight or where the emblems
     sit (the case). Deep navy stays ink and band; the night steps never appear (Sean, 4 Sep 2026, on a navy band
     in light: "the ink cant be read and it out off place in the light theme"). In light, navy is a tint you look at.
   DARK (a choice, or the device's when asked). The night is the room: Poseidon 960 #08203A, sheets a step above
     it at #0E2C48, hairlines white at 10–17%, ink #EAF4FB, muted #7FA6C4, the accent lifted to #2DB5B8 so it
     still reads, money and every signal lifted as cd-signature.css defines. The case sinks below the room to
     #051423–#071520 so the emblems glow. Never pure black: in dark, the night is the room you are in.
   THE DIFFERENCE IS THE ROOM. Same furniture, same geometry, same components, same words; only these tokens
   change (Law 100). A page that wants the other theme's look on one surface is wrong; it asks for a tile. */
:root{
  --shadow-c:18,57,85; --scrim:rgba(18,57,85,.55); --well2:#EEF1F4; --bz-w:#F4EFE3;
  /* LAW 106, 7 Sep 2026 — THE INK IS THE PILLAR'S, not the platform's. cd-signature's
     [data-skin] blocks set --skin-ink; a page that declares no skin is a defect, and the
     fallback here is Trade Handy's so that defect never renders as a black page. */
  --th-ink:var(--skin-ink,#142459); --th-ink2:var(--skin-ink-2,#1B4A8A);
  --th-mut:var(--skin-mut,#5A6E92); --bed:var(--field,#F7F9FB); --sheet:#FFFFFF;   /* 12 Sep 2026: the fallback moved with --field */
  --line:#E3E8EE; --th-line2:#CBD5DF; --well:rgba(18,57,85,.04);
  /* THE ACCENT IS THE MEMBER'S CHOICE (Sean, 4 Sep 2026: "I said a light and dark version, and 12 colours change
     switches"). cd-signature.css solves the twelve palettes at matched luminance in light, dark and sun; the system
     READS them here and paints with nothing else. Poseidon, the default, IS the deep teal #0B7A7D he approved, so a
     member who never touches the switch sees exactly what he signed off. --acc is a FILL (buttons, active rows); --acc-t
     is the same accent as TEXT on the room (the palette's contrast-safe step); --acc-on is the label on the fill. */
  /* LAW 106, 7 Sep 2026 — these fallbacks are NOT decoration. index.html loads this
     sheet WITHOUT cd-signature.css, so the homepage runs on the values below and
     nothing else. While they named the retired deep teal, the front door of the
     platform wore a colour the platform had stopped using. They are Trade Handy's
     cool ramp now — the right answer for any page that has not declared a skin. */
  --acc:var(--accent,#176BA0); --acc-h:var(--accent-hover,#12547D); --acc-w:var(--accent-wash,#176BA017);
  /* THE BUTTON'S DEFAULT IS A TOKEN, NOT A RULE — 22 Sep 2026. It was hardcoded to the
     accent below, so a button was LOUD unless it opted out, and 51% of the platform's
     1,072 buttons ended up in the accent with nobody deciding that. These three are what
     the theme control software will set. */
  --btn-bg:var(--well2); --btn-ink:var(--th-ink); --btn-line:var(--th-line2);
  --btn-bg-h:var(--well); --btn-line-h:var(--th-ink2);
  --acc-t:var(--accent-text,#176BA0); --acc-on:var(--accent-on,#FFFFFF);
  /* LAW 108 rule 1, 7 Sep 2026 — THE ROOM IS NEVER WHITE. --bed keeps its name so all
     202 pages keep working; it now resolves to §F's field in cd-signature.css, which is
     the ONE place any of this is changed. The blooms ride on the body rule below. */
  --bz:#9C7E41;
  --house:#176BA0;   /* LAW 106: there is no house teal any more — the PILLAR owns the colour.
                        Kept as a token because six rules in this sheet read it; it is Trade
                        Handy's press step, and a GeoBidder or GeoMundra page overrides it
                        through --accent like everything else. */
  /* the serious palette — one meaning each, used small */
  --c-money:#1F6B4A;  --c-money-w:#E7F3ED;
  --c-site:#2B5C8A;   --c-site-w:#E8EFF7;
  --c-watch:#7A5D18;  --c-watch-w:#F6F0DF;
  --c-risk:#7A2E2E;   --c-risk-w:#F6E8E8;
  --c-people:#5B3A6E; --c-people-w:#EFE9F3;
  --s1:4px;--s2:8px;--s3:12px;--s4:16px;--s5:20px;--s6:24px;--s8:32px;--s10:40px;
  --th-r:8px;--th-rsm:6px;--th-h:36px;
  --sans:'Instrument Sans',system-ui,-apple-system,sans-serif;
  --disp:'Bricolage Grotesque',var(--sans);
  --mono:'JetBrains Mono',ui-monospace,Menlo,monospace;
  /* the legacy token names every page already reads — all point INTO the system */
  /* --text, --text-body, --text-muted, --canvas, --surface*, --line-strong, --accent*, --ok/--warn/--danger/--info and --money
     stay declared once, in cd-signature.css, whose light values ARE the system's (aligned 3 Sep 2026) */
  --font-b:var(--sans);--mute:var(--th-mut);--mute-2:var(--th-mut);--hdr:var(--sheet);--hub-gap:var(--s4);
  /* --tx, --panel, --line2, --teal, --grad and the rest of the legacy names are th-core.css's aliases into cd-signature's tokens; the system declares none of them */
}

/* DARK — the night is the room. Values follow cd-signature.css §5 so both sheets agree to the step. */
html.th-on[data-theme="dark"]{
  /* LAW 106 — the night belongs to the pillar: --skin-bed and --skin-sheet come from
     cd-signature's per-skin dark blocks, so GeoBidder at night is warm-black and
     GeoMundra violet-black. --canvas/--surface stay as the fallback for anything
     that has not declared a skin yet. */
  /* 12 Sep 2026: the FALLBACKS moved with the ocean night too. They only fire when
     no skin is declared, which is a defect in itself — but a fallback that is two
     shades out of step is how a page ends up almost right and nobody can say why. */
  --th-ink:var(--skin-ink,#F2F7FA); --th-ink2:var(--skin-ink-2,#DCE6EE);
  --th-mut:var(--skin-mut,#A9BACA);
  /* LAW 108 §F — the FIELD is the room at night too, and it was not reaching here: this line
     put --skin-bed first, so dark resolved #070E1E while the field said #060B18 and the blooms
     sat on a ground that was not theirs. Field first, --skin-bed behind it, then --canvas. */
  --bed:var(--field,var(--skin-bed,var(--canvas,#060B18))); --sheet:var(--skin-sheet,var(--surface,#101B2D));   /* the night steps are cd-signature's own dark tokens (§5): Poseidon 960 and 925 */
  --line:rgba(255,255,255,.12); --th-line2:rgba(255,255,255,.22); --well:rgba(255,255,255,.06); --well2:rgba(255,255,255,.08);
  /* --acc, --acc-h, --acc-w, --acc-t, --acc-on follow the palette's own dark step (cd-signature.css §5) */
  --bz:#D4C098; --bz-w:rgba(212,192,152,.14);
  --house:var(--g-cyan-hi);
  --c-money:var(--g-green-hi); --c-money-w:var(--g-green-hi-w);
  --c-site:var(--g-azure);  --c-site-w:var(--g-azure-w);
  --c-watch:var(--g-gold-hi); --c-watch-w:var(--g-gold-hi-w);
  --c-risk:var(--g-coral);  --c-risk-w:var(--g-coral-w);
  --c-people:var(--g-lilac);--c-people-w:rgba(123,92,255,.16);
  --shadow-c:0,0,0; --scrim:rgba(0,0,0,.62);
}

/* SUNLIGHT — Sean's fourth switch (4 Sep 2026: "oh and a direct sunlight switch"). cd-theme.js sets data-mode="sun" on the
   root; cd-signature.css already answers it on its own tokens and per palette; the system answered nothing, so a member on
   a roof got the ordinary room. Here the ink and the hairlines go to full strength, every wash and shadow goes flat, and
   the accent takes the palette's sun step. It sits AFTER the dark set at the same specificity on purpose: in the sun,
   the sun wins over the room. Values are cd-signature.css's own sun values, not new ones. */
html.th-on[data-mode="sun"]{
  --th-ink:#070E1E; --th-ink2:#142459; --th-mut:#1B4A8A; --bed:#FFFFFF; --sheet:#FFFFFF;
  --line:#142459; --th-line2:#070E1E; --well:#FFFFFF; --well2:#F4F9FD;
  --acc:var(--accent,#176BA0); --acc-h:var(--accent-hover,#142459); --acc-w:#FFFFFF; --acc-t:var(--accent-text,#0E4260); --acc-on:var(--accent-on,#FFFFFF);
  /* THE BUTTON'S DEFAULT IS A TOKEN, NOT A RULE — 22 Sep 2026. It was hardcoded to the
     accent below, so a button was LOUD unless it opted out, and 51% of the platform's
     1,072 buttons ended up in the accent with nobody deciding that. These three are what
     the theme control software will set. */
  --btn-bg:var(--well2); --btn-ink:var(--th-ink); --btn-line:var(--th-line2);
  --btn-bg-h:var(--well); --btn-line-h:var(--th-ink2);
  --bz:#7A5D18; --bz-w:#FFFFFF;
  --c-money:#0E5B43; --c-money-w:#FFFFFF; --c-site:#123955; --c-site-w:#FFFFFF; --c-watch:#6E5400; --c-watch-w:#FFFFFF;
  --c-risk:#8C3A2E; --c-risk-w:#FFFFFF; --c-people:#5B3A6E; --c-people-w:#FFFFFF;
  --shadow-c:0,0,0; --scrim:rgba(0,0,0,.72);
}
html.th-on[data-mode="sun"] *,html.th-on[data-mode="sun"] *::before,html.th-on[data-mode="sun"] *::after{box-shadow:none!important;backdrop-filter:none!important;text-shadow:none!important}
html.th-on[data-mode="sun"] .th-case{background:#FFFFFF;border:2px solid var(--th-ink)}
html.th-on[data-mode="sun"] .th-case .card,html.th-on[data-mode="sun"] .th-case .tile{background:#FFFFFF;border-color:var(--th-ink)}

/* The public header (th-nav.js, #thH) paints with cd-signature's legacy names — --tx, --tx2, --mut, --panel — which
   th-core.css declares once, in light. In dark that left navy links on the night (about.html, 4 Sep 2026, 1.8:1).
   The system re-points those names into itself, so the one header follows the room. And it carries both cuts of
   every wordmark, as the shell does: ink on the day, the white cut on the night. */
html.th-on{--tx:var(--th-ink);--tx2:var(--th-ink2);--mut:var(--th-mut);--mut-2:var(--th-mut);--panel:var(--sheet)}

/* ── 2 · BASE ──────────────────────────────────────────────────────────── */
/* LAW 108 §F — the blooms ride here. `background-image:none!important` used to sit on this
   line and was the single declaration keeping every page flat: it stripped any gradient the
   room might carry. It is replaced by the field's own blooms, which are none in sunlight. */
html.th-on,html.th-on body{background:var(--field-blooms,none),var(--bed)!important;background-attachment:fixed!important;color:var(--th-ink);font:14px/20px var(--sans);-webkit-font-smoothing:antialiased}
html.th-on h1{font:600 24px/32px var(--disp);letter-spacing:-.01em;margin:0}
html.th-on h2{font:600 18px/24px var(--sans);margin:0 0 var(--s3)}
html.th-on h3{font:600 15px/20px var(--sans);margin:0 0 var(--s2)}
html.th-on p{margin:0 0 var(--s3)}
html.th-on a{color:var(--acc-t);text-decoration:none}
html.th-on a:hover{text-decoration:underline}
html.th-on hr{border:0;border-top:1px solid var(--line);margin:var(--s5) 0}
html.th-on ::selection{background:var(--acc-w)}
html.th-on :where(a,button,input,select,textarea,summary,[tabindex]):focus-visible{outline:2px solid var(--acc);outline-offset:2px}
@media (prefers-reduced-motion:reduce){html.th-on *{transition:none!important;animation:none!important}}

/* ── 3 · FURNITURE — the system's own classes, and the legacy names that map to them ── */
/* LAW 108 §G — white stops being the ground and becomes the thing ON it. A pane over flat
   canvas is a grey box (Law 80), which is why §F had to land first. backdrop-filter is
   declared with its -webkit- partner and degrades to a solid tint where unsupported. */
html.th-on .card,html.th-on .panel,html.th-on .w,html.th-on .pv,html.th-on .box,html.th-on .tile{background:var(--glass,#FFFFFF);-webkit-backdrop-filter:var(--glass-blur,none);backdrop-filter:var(--glass-blur,none);border:1px solid var(--glass-line,var(--line));border-radius:var(--th-r);padding:var(--s5);margin:0 0 var(--s4);box-shadow:var(--lift-2,none),var(--glass-lit,none)}
html.th-on .card h2,html.th-on .panel h2,html.th-on .pv h2{font:600 15px/20px var(--sans);letter-spacing:0;text-transform:none;color:var(--th-ink);margin:0 0 var(--s3);display:flex;justify-content:flex-start;align-items:center;gap:var(--s2);flex-wrap:wrap}
html.th-on .card h2>svg,html.th-on .card h2>.ic,html.th-on .panel h2>svg,html.th-on .pv h2>svg{width:18px;height:18px;flex:none;color:var(--th-ink2)}
html.th-on .card h2>.btn,html.th-on .card h2>.chip,html.th-on .card h2>.pill,html.th-on .card h2>.tag,html.th-on .card h2>.badge,html.th-on .card h2>a,html.th-on .card h2>.r,html.th-on .card h2>.n,html.th-on .card h2>.count,html.th-on .card h2>small,html.th-on .card h2>button{margin-left:auto;font-weight:500}
/* 3 Sep 2026: the element-qualified forms (button.btn, a.btn) sat at (0,2,2) and beat the secondary rule below at (0,2,1), so every <button class="btn btn-g"> and <a class="btn btn-g"> painted in the accent — one flat colour on every button, no hierarchy. The bare form already outranks any a.btn/button.btn in the other sheets (0,1,1). */
/* BTN-ALL, 3 Sep 2026 — Sean: "you didn't check all the buttons, they are old school microsoft". Measured on every page: 22 pages
   still showed the browser's grey fill on 52 bare <button>s and on page-local classes (btn2, soc, savebtn, save, opt, lyr…). Every
   button on a th-on page now takes the sheet's secondary look by element — the fill, the ink, the hairline, the radius, the face —
   and nothing about its size, so option cards and tabs keep their geometry; .btn adds the geometry, .btn-p the primary. The shell's
   own controls (#thTop, #thBar, #thSheet) outrank this by their ids. */
html.th-on button,html.th-on input[type=submit],html.th-on input[type=button]{appearance:none;-webkit-appearance:none;background:var(--sheet);color:var(--th-ink);border:1px solid var(--th-line2);border-radius:var(--th-rsm);font-family:var(--sans);font-weight:600;cursor:pointer;box-shadow:none}
html.th-on button:hover,html.th-on input[type=submit]:hover,html.th-on input[type=button]:hover{background:var(--well);border-color:var(--th-ink2)}
html.th-on button:disabled,html.th-on input[type=submit]:disabled{opacity:.55;cursor:default}
html.th-on .btn,html.th-on .btn-p,html.th-on .btn-g{height:var(--th-h);padding:0 var(--s4);border-radius:var(--th-rsm);border:1px solid transparent;font:600 14px var(--sans);display:inline-flex;align-items:center;justify-content:center;gap:var(--s2);cursor:pointer;background:var(--btn-bg);color:var(--btn-ink);border-color:var(--btn-line);white-space:nowrap;text-decoration:none;box-shadow:none;transform:none;letter-spacing:0;text-transform:none}
/* 22 Sep 2026 · THE ACCENT IS OPT-IN. Measured across eleven live products, a real
   accent covers 1.6-2.1% of the screen; ours was on 51% of every button because the
   base rule above painted it. And the conversion evidence is unambiguous that CONTRAST
   outweighs hue by 3.2x — so when half the buttons shout, the one mechanism that
   actually converts is switched off. Sean, 22 Sep: "may it just the buttons in the teal
   and too much of it". A button is quiet now unless it ASKS to be loud. */
html.th-on .btn:hover{background:var(--btn-bg-h);border-color:var(--btn-line-h);text-decoration:none}
/* the primary reads its OWN tokens, falling back to the accent — so which
   anchor it wears is a setting, not an edit here (mig1490, _thememake.py) */
html.th-on .btn-p,html.th-on .btn.btn-p,html.th-on .btn-primary,html.th-on .btn.btn-primary,html.th-on .btn.primary{background:var(--btn-p-bg,var(--acc));color:var(--btn-p-ink,var(--acc-on));border-color:transparent}
html.th-on .btn-p:hover,html.th-on .btn-primary:hover,html.th-on .btn.primary:hover{background:var(--acc-h);border-color:transparent}
/* 20 Sep 2026 — <b> AND <strong> WERE THE BROWSER'S BOLD, NOT OURS. Measured on the rendered
   quote page: eleven elements at weight 700 or 900 while no stylesheet on the platform declared
   either. They are bare <b> tags taking the user-agent default, which is why every static check
   read clean. §4.4: "Medium is the button, label and nav weight — never bold." 590 is the cut
   Instrument Sans rides for semibold, so this is the law's own third weight. */
html.th-on b,html.th-on strong{font-weight:590}

/* ══ THE TOUCH FLOOR — §10, "Touch targets 44px, 56px in the field" ══════════
   20 September 2026. Measured: twelve controls render under 44px — .btn-sm and the
   segmented/tab buttons at 30px, a quantity stepper and photo-remove buttons at 24px,
   a thumbnail button at 18px. Raising them everywhere would have cost the desk its
   density for no gain: a 30px button under a mouse is fine, and Linear runs 36px rows
   all day. What is NOT fine is that same 30px button under a thumb on a roof.
   So the floor applies where a finger does: coarse pointers and phone widths. Nothing
   on the desk moves. The 56px field size stays what `.cd-field` is for, and checkboxes
   and radios are excluded because their tap target is the label around them, not the box. */
@media (pointer: coarse), (max-width: 700px){
  html.th-on button,
  html.th-on .btn, html.th-on .btn-p, html.th-on .btn-g, html.th-on .btn-sm, html.th-on .btn.sm,
  html.th-on .m-seg button, html.th-on .tab, html.th-on .otab, html.th-on .lpre button,
  html.th-on a.btn,
  html.th-on input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=file]):not([type=hidden]),
  html.th-on select, html.th-on [role="button"]{
    min-height:44px;
  }
  html.th-on .btn-sm, html.th-on .btn.sm{padding:0 var(--s4)}
}
html.th-on .btn.sec,html.th-on .btn-g,html.th-on .btn.ghost,html.th-on .btn-ghost,html.th-on .btn.secondary,html.th-on .btn.g{background:var(--sheet);color:var(--th-ink);border-color:var(--th-line2)}
html.th-on .btn.sec:hover,html.th-on .btn-g:hover,html.th-on .btn-ghost:hover{background:var(--well);border-color:var(--th-ink2)}
html.th-on .btn.danger{background:var(--sheet);color:var(--c-risk);border-color:var(--c-risk)}
html.th-on .btn-sm,html.th-on .btn.sm{height:30px;padding:0 var(--s3);font-size:13px}
html.th-on .btn:disabled{opacity:.5;cursor:not-allowed}
html.th-on input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=file]):not([type=color]):not([type=hidden]),html.th-on select,html.th-on textarea{background:var(--sheet);border:1px solid var(--th-line2);border-radius:var(--th-rsm);color:var(--th-ink);font:400 16px var(--sans);padding:0 var(--s3);height:var(--th-h);max-width:100%;box-shadow:none}
html.th-on textarea{height:auto;min-height:88px;padding:var(--s2) var(--s3);line-height:20px}
html.th-on input:focus,html.th-on select:focus,html.th-on textarea:focus{outline:none;border-color:var(--acc);box-shadow:0 0 0 3px var(--acc-w)}
html.th-on label{font-size:13px;color:var(--th-mut)}
html.th-on table{width:100%;border-collapse:collapse;font-variant-numeric:tabular-nums;background:var(--sheet)}
html.th-on th{font:600 12px/16px var(--sans);letter-spacing:.04em;text-transform:uppercase;color:var(--th-mut);text-align:left;padding:var(--s3) var(--s4);border-bottom:1px solid var(--line);background:var(--well)}
html.th-on td{padding:var(--s3) var(--s4);border-bottom:1px solid var(--line);vertical-align:middle}
html.th-on tr:last-child td{border-bottom:0}
html.th-on td.num,html.th-on th.num,html.th-on td.r,html.th-on th.r{text-align:right}
html.th-on .chip,html.th-on .pill,html.th-on .tag,html.th-on .badge{display:inline-flex;align-items:center;height:24px;padding:0 var(--s2);border-radius:999px;font:500 12px var(--sans);letter-spacing:0;text-transform:none;background:var(--well2);color:var(--th-ink);border:0;white-space:nowrap}
html.th-on .chip.ok,html.th-on .pill.ok,html.th-on .pin,html.th-on .stat.ok,html.th-on .chip.healthy,html.th-on .m-chip.healthy{background:var(--c-money-w);color:var(--c-money)}
html.th-on .chip.warn,html.th-on .pill.warn,html.th-on .pill.wait,html.th-on .pill.amber,html.th-on .stat.amb,html.th-on .m-chip.watch{background:var(--c-watch-w);color:var(--c-watch)}
html.th-on .chip.bad,html.th-on .pill.bad,html.th-on .pill.no,html.th-on .pout,html.th-on .m-chip.failing{background:var(--c-risk-w);color:var(--c-risk)}
html.th-on .chip.info,html.th-on .chip.run,html.th-on .m-chip.running{background:var(--c-site-w);color:var(--c-site)}
html.th-on .chip.ppl{background:var(--c-people-w);color:var(--c-people)}
html.th-on .chip.on,html.th-on .pill.on{background:var(--th-ink);color:var(--bed)}   /* ink on the room: white on navy in light, navy on light in dark */
html.th-on .m-chip.money{background:var(--bz-w);color:var(--bz)}
html.th-on .kpis,html.th-on .m-kpis,html.th-on .stats,html.th-on .okpi,html.th-on .seats{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));background:var(--sheet);border:1px solid var(--line);border-radius:var(--th-r);margin:0 0 var(--s5);overflow:hidden;gap:0;padding:0}
html.th-on .kpis>*,html.th-on .m-kpi,html.th-on .k,html.th-on .stats>*,html.th-on .okpi>*,html.th-on .seats>*{padding:var(--s4) var(--s5);border-left:1px solid var(--line);border-top:0;border-right:0;border-bottom:0;border-radius:0;margin:0;background:transparent;min-width:0;box-shadow:none;display:block}
html.th-on .kpis>*:first-child,html.th-on .m-kpi:first-child,html.th-on .k:first-child,html.th-on .stats>*:first-child,html.th-on .okpi>*:first-child,html.th-on .seats>*:first-child{border-left:0}
html.th-on .kpis:empty,html.th-on .stats:empty,html.th-on .okpi:empty,html.th-on .seats:empty{display:none}
html.th-on .k .n,html.th-on .m-kpi .m-v,html.th-on .kpi b,html.th-on .stat .v,html.th-on .stat .n,html.th-on .kpi .n,html.th-on .kpi .v,html.th-on .seat .v{font:500 24px/32px var(--disp);font-variant-numeric:tabular-nums;color:var(--door-ink,var(--th-ink))!important;background:none;letter-spacing:0;margin:0;display:block;-webkit-text-fill-color:currentColor}
html.th-on .k .l,html.th-on .m-kpi .m-l,html.th-on .kpi span,html.th-on .stat .l,html.th-on .kpi .l,html.th-on .seat .l{font:400 13px/16px var(--sans);color:var(--th-mut);letter-spacing:0;text-transform:none;background:none;border:0;padding:0;display:block;height:auto;border-radius:0}
html.th-on .grad-text{background:none!important;-webkit-text-fill-color:currentColor!important;color:var(--th-ink)}
html.th-on .k .n.amber,html.th-on .m-kpi.hot .m-v{color:var(--c-watch)!important}html.th-on .k .n.bad{color:var(--c-risk)!important}html.th-on .m-kpi.good .m-v{color:var(--c-money)!important}
html.th-on .tabs,html.th-on .seg,html.th-on .m-seg,html.th-on .otabs{display:inline-flex;gap:2px;flex-wrap:wrap;border:1px solid var(--line);background:var(--sheet);border-radius:var(--th-rsm);padding:3px;margin:0 0 var(--s4);max-width:100%}
html.th-on .tabs button,html.th-on .seg button,html.th-on .m-seg button,html.th-on .tab,html.th-on .otab{height:30px;padding:0 var(--s3);border:0;border-radius:var(--th-btn,10px);background:transparent;color:var(--th-mut);font:500 13px var(--sans);cursor:pointer;white-space:nowrap;letter-spacing:0;text-transform:none;box-shadow:none;min-width:max-content;width:auto;overflow:visible;text-overflow:clip}
html.th-on .tabs button.on,html.th-on .seg button.on,html.th-on .tab.on,html.th-on .otab.on,html.th-on .otab[aria-selected="true"],html.th-on .tab[aria-selected="true"],html.th-on .m-seg button[aria-pressed="true"]{background:var(--th-ink);color:#fff}
html.th-on .head,html.th-on .m-hrow,html.th-on .hrow{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--s4);flex-wrap:wrap;margin:0 0 var(--s5)}
html.th-on .sub,html.th-on .lead,html.th-on .m-sub,html.th-on .gp{color:var(--th-mut);font-size:13px;margin-top:var(--s1);max-width:70ch;letter-spacing:0;text-transform:none}
html.th-on .grid{display:grid;gap:var(--s4)}
html.th-on .empty,html.th-on .m-empty{color:var(--th-mut);padding:var(--s5) 0;text-align:center}
html.th-on .disc,html.th-on .note,html.th-on .m-foot,html.th-on .foot{color:var(--th-mut);font-size:13px;line-height:20px;background:transparent;border:0;padding:0;margin-top:var(--s3)}
html.th-on details.m-how summary{color:var(--acc-t);cursor:pointer}
html.th-on .toast{background:var(--th-ink);color:#fff;border:0;border-radius:var(--th-r);padding:var(--s3) var(--s4);box-shadow:0 8px 24px rgba(var(--shadow-c),.25)}
html.th-on .tbl{background:var(--sheet);border:1px solid var(--line);border-radius:var(--th-r);overflow:auto}
html.th-on table.m-tab,html.th-on .m-tab{border:1px solid var(--line);border-radius:var(--th-r);overflow:hidden}
html.th-on .m-acts button,html.th-on .m-acts a{color:var(--acc-t);font:500 13px var(--sans);background:none;border:0}
html.th-on .txform{display:grid;gap:var(--s2);align-items:center;margin-bottom:var(--s3)}
html.th-on .modbar{display:flex;gap:2px;flex-wrap:wrap;align-items:center;margin:0 0 var(--s4);border:1px solid var(--line);background:var(--sheet);border-radius:var(--th-r);padding:var(--s1)}
html.th-on .modbar button.m{font:500 13px var(--sans);padding:0 var(--s3);height:32px;border-radius:var(--th-rsm);border:0;background:transparent;color:var(--th-mut);cursor:pointer}
html.th-on .modbar button.m:hover{color:var(--th-ink);background:var(--well)}
html.th-on .modbar button.create{background:var(--acc);color:var(--acc-on);height:32px;padding:0 var(--s3);border-radius:var(--th-rsm);border:0;font:600 13px var(--sans);cursor:pointer}
html.th-on .pop{background:var(--sheet);border:1px solid var(--line);border-radius:var(--th-r);box-shadow:0 12px 32px rgba(var(--shadow-c),.16)}
/* the place and site makers — "+ Add a place" beside every selector, and the small form it opens (th-place-maker.js) */
html.th-on .pm-wrap{display:inline-flex;align-items:center;gap:var(--s2);max-width:100%;flex-wrap:wrap}
html.th-on .pm-wrap select{flex:1 1 220px;min-width:0}
html.th-on .pm-add{white-space:nowrap}
html.th-on #thPm{position:fixed;inset:0;z-index:90;background:var(--scrim);display:flex;align-items:center;justify-content:center;padding:var(--s4)}
html.th-on #thPm .pm-box{background:var(--sheet);border:1px solid var(--line);border-radius:var(--th-r);box-shadow:0 20px 60px rgba(var(--shadow-c),.22);width:min(560px,100%);padding:var(--s6)}
html.th-on #thPm h2{font:600 18px/24px var(--sans);margin:0 0 var(--s1)}
html.th-on #thPm .pm-sub{color:var(--th-mut);font-size:13px;margin:0 0 var(--s4)}
html.th-on #thPm .pm-form{display:grid;gap:var(--s3)}
html.th-on #thPm .pm-f{display:grid;gap:var(--s1);font-size:13px;color:var(--th-mut)}
html.th-on #thPm .pm-f input,html.th-on #thPm .pm-f select{width:100%}
html.th-on #thPm .pm-row{display:grid;grid-template-columns:2fr 1fr 1fr;gap:var(--s3)}
html.th-on #thPm .pm-row.pm-two{grid-template-columns:1fr 1fr}
html.th-on #thPm .pm-msg{font-size:13px;padding:var(--s2) var(--s3);border-radius:var(--th-rsm)}
html.th-on #thPm .pm-msg.ok{background:var(--c-money-w);color:var(--c-money)}html.th-on #thPm .pm-msg.bad{background:var(--c-risk-w);color:var(--c-risk)}
html.th-on #thPm .pm-acts{display:flex;justify-content:flex-end;gap:var(--s2);margin-top:var(--s2)}
@media(max-width:639px){html.th-on #thPm .pm-row{grid-template-columns:1fr 1fr}html.th-on #thPm .pm-row .pm-f:first-child{grid-column:1/-1}}
/* the workshop strip — a tool shown before it is live says so in the system's voice, not a dark band */
html.th-on #thPrev{position:fixed;left:0;right:0;bottom:0;z-index:50;display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;padding:var(--s3) var(--s5);background:var(--sheet);border-top:1px solid var(--line);color:var(--th-ink);box-shadow:0 -8px 24px rgba(18,57,85,.06)}
html.th-on #thPrev .tp-t{flex:1 1 320px;font-size:13px;color:var(--th-ink2)}
html.th-on #thPrev input{width:240px;max-width:100%}
html.th-on #thPrev #tpGo{height:var(--th-h);padding:0 var(--s4);border:0;border-radius:var(--th-rsm);background:var(--acc);color:var(--acc-on);font:600 14px var(--sans);cursor:pointer}
html.th-on #thPrev .tp-x{width:32px;height:32px;border:0;background:transparent;color:var(--th-mut);cursor:pointer;border-radius:var(--th-rsm)}
html.th-on #thPrev .tp-x:hover{background:var(--well);color:var(--th-ink)}


/* ── 3b · THE 2026 FURNITURE — 7 Sep 2026. Sean, tonight: "the userface, design … look like an outdated platform
   compared to modern software … stop constraining yourself … make it the state of the art platform." The law already
   held the shape — §10: pill buttons, scale(.96) on press, the micro-shadow 0 4px 30px, glass at blur(12px), a bento
   grid — and §4j held the elevation scale since 5 Sep. The furniture never wore them: hairline boxes, 6px corners,
   36px controls, no motion. This section makes every surface wear the shape the law already describes, by order
   (same specificity, later wins) so nothing above is rewritten. NO COLOUR IS ADDED: the ground stays white, the
   serious palette stays, every neutral is a token. Depth is light and edge; controls are pills; a tile that is a door
   lifts under the hand; motion is 120–180 ms on one curve; the sun (data-mode="sun") still strips every shadow. */
html.th-on{--th-r:12px;--th-rsm:10px;--th-h:40px;--th-r-lg:16px;--th-btn:10px;--th-pill:9999px;/* --th-btn added 12 Sep 2026 on Sean's ruling: "my buttons are still rounded to much". EVERY button on all three pillars was --th-pill (9999px) — a full lozenge — which is why GeoMundra's six doors read as capsules. The 2026 mock he approved used 9px on its CTA and 12px on its cards; 10px is that, on the scale already here (it equals --th-rsm). --th-pill STAYS for the things that are genuinely pills: meters, status chips and the segmented-control track, where a lozenge is the pattern and not a default. */--ease:cubic-bezier(.2,.7,.2,1);--t-fast:120ms;--t-base:180ms;--sh-micro:0 4px 30px rgba(var(--shadow-c),.08);/* --glass moved to cd-signature §G, LAW 108: one place. It was declared here on html.th-on, which outranks :root, so §G was being silently overridden — the exact failure the law exists to stop, found by measuring the live page. */--glass-edge:color-mix(in srgb,var(--sheet) 60%,transparent)}
html.th-on,html.th-on body{font-size:15px;line-height:24px}
html.th-on h1{font:600 28px/36px var(--disp);letter-spacing:-.015em}
html.th-on h3{font:600 16px/24px var(--sans)}
/* surfaces: an edge and a lift, and a lift under the hand where a tile is a door */
html.th-on .card,html.th-on .panel,html.th-on .w,html.th-on .pv,html.th-on .box,html.th-on .tile{border-color:var(--edge);box-shadow:var(--lift-1);padding:var(--s6)}
html.th-on .card h2,html.th-on .panel h2,html.th-on .pv h2{font:600 16px/24px var(--sans)}
html.th-on a.card,html.th-on a.tile,html.th-on .tile[role=button],html.th-on .card[role=button],html.th-on .tile.link,html.th-on .card.link{transition:box-shadow var(--t-base) var(--ease),transform var(--t-base) var(--ease),border-color var(--t-fast) var(--ease)}
/* THE MAP'S ZOOM BUTTONS: Leaflet gives them line-height 30px and role=button; the 44 px target above stretched the box and left
   the + and − glyphs at the top (measured 24 Sep 2026 on allies, jobdesk, logistics, site-access at 390). Centre what is inside. */
html.th-on .leaflet-bar a,html.th-on .leaflet-control-zoom a{display:flex;align-items:center;justify-content:center;line-height:1}
html.th-on a.card:hover,html.th-on a.tile:hover,html.th-on .tile[role=button]:hover,html.th-on .card[role=button]:hover,html.th-on .tile.link:hover,html.th-on .card.link:hover{box-shadow:var(--lift-hover);transform:translateY(-2px);border-color:var(--th-line2);text-decoration:none}
/* controls: pills, a hand-feel on press, one motion curve */
html.th-on button,html.th-on input[type=submit],html.th-on input[type=button],html.th-on .btn,html.th-on .btn-p,html.th-on .btn-g{border-radius:var(--th-btn);transition:background-color var(--t-fast) var(--ease),border-color var(--t-fast) var(--ease),color var(--t-fast) var(--ease),box-shadow var(--t-base) var(--ease),transform var(--t-fast) var(--ease)}
html.th-on .btn,html.th-on .btn-p,html.th-on .btn-g{padding:0 var(--s5)}
html.th-on .btn:not(.sec):not(.btn-g):not(.ghost):not(.secondary):not(.g):not(.danger),html.th-on .btn-p{box-shadow:0 1px 0 rgba(255,255,255,.16) inset,0 1px 2px rgba(var(--shadow-c),.14),0 8px 20px -12px rgba(var(--shadow-c),.45)}
/* .btn-ghost joined 19 Sep 2026: th-core paints it transparent but html.th-on .btn outranked that, so on about/trust every button — primary AND ghost — was solid cyan. Measured live in Sean's Chrome. */
html.th-on .btn.sec,html.th-on .btn-g,html.th-on .btn.ghost,html.th-on .btn-ghost,html.th-on .btn.secondary,html.th-on .btn.g{background:var(--well2);border-color:transparent}
html.th-on .btn.sec:hover,html.th-on .btn-g:hover,html.th-on .btn.ghost:hover,html.th-on .btn-ghost:hover,html.th-on .btn.secondary:hover,html.th-on .btn.g:hover{background:var(--well2);border-color:var(--th-line2);box-shadow:0 1px 2px rgba(var(--shadow-c),.10)}
html.th-on button:active:not(:disabled),html.th-on .btn:active:not(:disabled){transform:scale(.96)}
html.th-on .btn-sm,html.th-on .btn.sm{height:32px;padding:0 var(--s4)}
/* inputs: the height of the button beside them, a quiet hairline that wakes under the hand */
html.th-on input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=file]):not([type=color]):not([type=hidden]),html.th-on select{height:var(--th-h);border-radius:var(--th-rsm);font-size:16px;padding:0 var(--s4);transition:border-color var(--t-fast) var(--ease),box-shadow var(--t-base) var(--ease)}
html.th-on textarea{border-radius:var(--th-rsm);font-size:16px;padding:var(--s3) var(--s4);line-height:24px}
html.th-on input:hover:not(:focus):not([type=checkbox]):not([type=radio]):not([type=range]):not([type=file]),html.th-on select:hover:not(:focus),html.th-on textarea:hover:not(:focus){border-color:var(--th-ink2)}
/* chips: a touch larger, still quiet */
html.th-on .chip,html.th-on .pill,html.th-on .tag,html.th-on .badge{height:26px;padding:0 var(--s3);font:600 12px/16px var(--sans)}
/* tabs: a tinted track and a white pill that carries the current one — the segmented control, not a navy block */
/* ── THE TAB TRACK IS NOT A LOZENGE — SEAN, 15 SEP 2026 ─────────────────────
   "I prefer the slightly rounded, squarish corners over these round tablet
   look... they're not fitting to the site."
   HE ALREADY RULED THIS ON 12 SEP — "my buttons are still rounded to much" —
   and every button moved from --th-pill to --th-btn. The exception written
   that day kept the pill for "meters, status chips, and the segmented-control
   track", and the track is exactly what he is now looking at. A segmented
   control IS a row of buttons; it only escaped the 12 Sep ruling on a
   technicality, and three days later his eye found it.
   THE RULE THAT REPLACES THE EXCEPTION: shape carries meaning. You press it →
   --th-btn. It is telling you something → a lozenge. Measured before changing:
   --th-pill had exactly TWO consumers on the whole platform, both of them
   here, and .pill and .adchip already use --th-btn and 4px — so the chips were
   never lozenges and nothing else moves. 26 pages carry these classes. */
html.th-on .tabs,html.th-on .seg,html.th-on .m-seg,html.th-on .otabs{background:var(--well2);border-color:transparent;border-radius:var(--th-btn);padding:3px;gap:2px}
/* §3.11, THE SAME DAY IT WAS RULED, AND IT CAUGHT THIS RULE'S OWN WORK.
   height:32px with font:600 13px/16px is a 16px line in a 32px box, and a
   bare .tab is display:block — so the line sat at 0 and left SIXTEEN PIXELS
   of dead space under it. Measured on allies, guide and prestart: top 0,
   bottom 16, sixteen findings. A button inside .tabs was fine only by
   accident — its container is inline-flex, so the browser centred it; a .tab
   standing on its own had nothing doing that for it.
   Stating a height obliges you to say where the text sits in it. Measured
   after: 8/8, centred. This rule reaches 26 pages at once (17 .tabs, 8 .seg,
   1 .otabs) — saying that out loud is what §3.10 asks for. */
html.th-on .tabs button,html.th-on .seg button,html.th-on .m-seg button,html.th-on .tab,html.th-on .otab{height:32px;padding:0 var(--s4);display:inline-flex;align-items:center;justify-content:center;border-radius:var(--th-btn);font:600 13px/16px var(--sans);transition:background-color var(--t-fast) var(--ease),color var(--t-fast) var(--ease),box-shadow var(--t-base) var(--ease)}
html.th-on .tabs button.on,html.th-on .seg button.on,html.th-on .tab.on,html.th-on .otab.on,html.th-on .otab[aria-selected="true"],html.th-on .tab[aria-selected="true"],html.th-on .m-seg button[aria-pressed="true"]{background:var(--sheet);color:var(--th-ink);box-shadow:0 1px 2px rgba(var(--shadow-c),.14),0 0 0 1px var(--edge)}
/* the numbers: a bento of tiles, each on its own lift, the figure in the display face */
html.th-on .kpis,html.th-on .m-kpis,html.th-on .stats,html.th-on .okpi,html.th-on .seats{background:transparent;border:0;border-radius:0;gap:var(--s3);overflow:visible}
html.th-on .kpis>*,html.th-on .m-kpi,html.th-on .k,html.th-on .stats>*,html.th-on .okpi>*,html.th-on .seats>*{background:var(--sheet);border:1px solid var(--edge);border-radius:var(--th-r);box-shadow:var(--lift-1);padding:var(--s5)}
html.th-on .kpis>*:first-child,html.th-on .m-kpi:first-child,html.th-on .k:first-child,html.th-on .stats>*:first-child,html.th-on .okpi>*:first-child,html.th-on .seats>*:first-child{border-left:1px solid var(--edge)}
html.th-on .k .n,html.th-on .m-kpi .m-v,html.th-on .kpi b,html.th-on .stat .v,html.th-on .stat .n,html.th-on .kpi .n,html.th-on .kpi .v,html.th-on .seat .v{font:500 32px/40px var(--disp);letter-spacing:-.01em}
/* tables: a hover you can follow, the frame lifted like a card */
html.th-on tbody tr:hover td{background:var(--well)}
html.th-on .tbl,html.th-on table.m-tab,html.th-on .m-tab{border-color:var(--edge);box-shadow:var(--lift-1)}
html.th-on .toast{border-radius:var(--th-r);box-shadow:var(--lift-3)}
html.th-on .pop,html.th-on #thPm .pm-box{border-radius:var(--th-r-lg);border-color:var(--edge);box-shadow:var(--lift-3)}
html.th-on .sub,html.th-on .lead,html.th-on .m-sub,html.th-on .gp{font-size:14px;line-height:20px}
html.th-on .modbar{border-color:var(--edge);box-shadow:var(--lift-1);border-radius:var(--th-r)}
html.th-on .modbar button.m,html.th-on .modbar button.create{border-radius:var(--th-btn)}

/* ── 4 · THE SHELL — the same markup th-shell.js has always drawn, wearing the system ── */
/* D19 notch handling, 3 Sep 2026: the bar and everything hung from it grow by the device's safe-area insets (0 on every screen without a notch). The sheet owns the bar's geometry with !important, so the insets live here, not in the shell. */
html.th-on #thTop{background:var(--sheet)!important;backdrop-filter:none!important;border-bottom:1px solid var(--line)!important;height:calc(56px + env(safe-area-inset-top,0))!important;padding-top:env(safe-area-inset-top,0)!important;box-shadow:none}
html.th-on #thTop .sr{background:var(--sheet);border:1px solid var(--th-line2);border-radius:var(--th-rsm);color:var(--th-mut);height:var(--th-h);padding:0 var(--s3)}
html.th-on #thSide .sr{display:flex;align-items:center;gap:var(--s2);margin:var(--s2) var(--s3) var(--s1);height:var(--th-h);padding:0 var(--s3);background:var(--sheet);border:1px solid var(--th-line2);border-radius:var(--th-rsm);color:var(--th-mut)}
html.th-on #thSide .sr input{flex:1;min-width:0;border:0;background:transparent;color:var(--th-ink);font:inherit;font-size:16px;outline:0}
html.th-on #thSide .sr svg{width:16px;height:16px;flex:none}
html.th-on #thSide .sr kbd{font-size:12px;padding:2px 5px;border:1px solid var(--th-line2);border-radius:4px;color:var(--th-mut)}
html.th-on #thTop .ib,html.th-on #thTop .bg{border:1px solid var(--th-line2);border-radius:var(--th-rsm);background:var(--sheet);color:var(--th-ink2);width:var(--th-h);height:var(--th-h)}
html.th-on #thTop .bk{border-color:var(--th-line2);color:var(--th-ink2);border-radius:var(--th-rsm)}
html.th-on #thTop .cr,html.th-on #thTop .cr .pg{font:600 15px var(--sans);color:var(--th-ink)}
html.th-on #thTop .biz{border-radius:var(--th-rsm)}
/* Same ruling: this is height:var(--th-h) — a full-height control in the row
   beside the search field — so it is --th-btn, not a lozenge. The avatar
   INSIDE it stays circular; that is a portrait, not a corner. */
html.th-on #thTop #thAcct{display:flex;flex-direction:row;align-items:center;gap:var(--s2);width:auto;height:var(--th-h);padding:0 var(--s3) 0 var(--s1);border-radius:var(--th-btn)}
html.th-on #thAcctAv{background:var(--th-ink)!important;color:#FFFFFF!important;width:28px!important;height:28px!important;font:600 12px var(--sans)!important}
html.th-on #thAcctNm{color:var(--th-ink2)!important;font-size:13px!important}
html.th-on .printonly{display:none}
html.th-on #thGnav{background:var(--sheet)!important;border-right:1px solid var(--line)!important;backdrop-filter:none!important;top:calc(56px + env(safe-area-inset-top,0))!important;padding-left:env(safe-area-inset-left,0)}
html.th-on #thGnav .gb{border-bottom:1px solid var(--line);color:var(--th-mut)}
html.th-on #thGnav .gi{border-radius:var(--th-rsm);color:var(--th-ink2);height:40px}
html.th-on #thGnav .gi:hover{background:var(--well);color:var(--th-ink)}
html.th-on #thGnav .gi[aria-current]{background:var(--acc-w);color:var(--acc-t);font-weight:600}
html.th-on #thGnav .gi[aria-current]::before{display:none}
html.th-on #thGnav .gi svg{color:inherit}
html.th-on #thGnav .sec{color:var(--th-mut)}
html.th-on #thGnav .gi .gimg{width:20px;height:20px;display:block;flex:none}
html.th-on #thGnav .gi.gdead{opacity:.45;cursor:default}
html.th-on #thGnav .dv{height:1px;background:var(--line);margin:var(--s2) var(--s3)}
html.th-on #thNav .gl.gs{font:600 12px/16px var(--sans);letter-spacing:0;text-transform:none;color:var(--th-ink2);padding-top:var(--s3);white-space:normal;overflow:visible;text-overflow:clip}
html.th-on #thNav .gnote{font:400 12px/16px var(--sans);color:var(--th-mut);padding:var(--s2) var(--s3)}
html.th-on #thSide{background:var(--sheet)!important;border-right:1px solid var(--line)!important;backdrop-filter:none!important;top:calc(56px + env(safe-area-inset-top,0))!important;box-shadow:none}
html.th-on #thSide .st{border-bottom:1px solid var(--line);height:56px}
html.th-on #thSide .sttl{font:600 14px var(--sans);color:var(--th-ink)}
html.th-on #thNav .gl{font:600 12px/16px var(--sans);letter-spacing:.06em;color:var(--th-mut)}
html.th-on #thNav a{border-radius:var(--th-rsm);color:var(--th-ink2);font:500 14px var(--sans);padding:0 var(--s2);height:var(--th-h)}
html.th-on #thNav a:hover{background:var(--well);color:var(--th-ink)}
html.th-on #thNav a.on{background:var(--acc-w);color:var(--acc-t);box-shadow:none;font-weight:600}
html.th-on #thNav a.on::before{display:none}
/* 19 Sep 2026 — HIS WORDS: "the fill on icons are to dark you can hardly see the icon design".
   He was right and this one line was the whole cause. color:inherit made every rail icon
   EXACTLY the colour of its own label, in every state, and at a higher specificity than any
   rule in th-shell.js — so no icon rule anywhere could ever lighten them. A filled duotone
   glyph at 19px in label-dark reads as a blob: Bank and Books & reports were two identical
   dark slabs. Measured in his Chrome: icon rgb(43,59,71), label rgb(43,59,71), the same.
   The icon now sits BACK from the word on --th-mut, comes forward on hover, and takes the
   accent on the row you are on — so the rail has three states instead of one.
   NOT DONE HERE, deliberately: the duotone backing paths live inside a <use> shadow tree and
   no descendant selector from this sheet can reach them. Three attempts in the browser proved
   it; shipping those rules would be more CSS that paints nothing. */
html.th-on #thNav a .ei{color:var(--th-mut)}
html.th-on #thNav a:hover .ei{color:var(--th-ink)}
html.th-on #thNav a.on .ei{color:var(--acc-t)}
html.th-on #thUser{background:var(--sheet);border:1px solid var(--line);border-radius:var(--th-r)}
html.th-on #thUser .av{background:var(--th-ink);border-radius:50%;color:#fff;font:600 12px var(--sans)}
html.th-on #thUser span{color:var(--th-mut)}
html.th-on #thRight{background:var(--sheet)!important;border-left:1px solid var(--line)!important;backdrop-filter:none!important;top:calc(56px + env(safe-area-inset-top,0))!important}
html.th-on #thRight .qa a{background:var(--sheet);border:1px solid var(--line);border-radius:var(--th-rsm);color:var(--th-ink)}
html.th-on #thRight .rtab.on{background:var(--acc-w);color:var(--acc-t)}
html.th-on #thPal .bx{border-radius:var(--th-r);box-shadow:0 20px 60px rgba(var(--shadow-c),.22)}
html.th-on #thPalR a[aria-selected='true']{background:var(--acc-w)}
html.th-on #thSwP{border-radius:var(--th-r)}
html.th-on body{padding-top:calc(56px + env(safe-area-inset-top,0))!important}
html.th-on a.skip{background:var(--acc);color:var(--acc-on)}
/* THE THREE PILLARS — Sean, 3 Sep 2026 ("A"): Trade Handy, GeoBidder and GeoMundra sit in the bar as their own lockups,
   on every page, public and app; the current one is underlined. The twelve softwares stay in Trade Handy's rail. */
html.th-on .pillars{display:flex;align-items:center;gap:4px;margin-left:8px;padding-left:12px;border-left:1px solid var(--line);flex:none}
html.th-on .pillars .pl{display:inline-flex;align-items:center;gap:8px;height:36px;padding:0 8px;border-radius:var(--th-rsm);text-decoration:none;position:relative;color:var(--th-ink2)}
html.th-on .pillars .pl img{height:18px;width:auto;display:block}
html.th-on .pillars .pl img.sy{display:none;height:20px}
html.th-on .pillars a.pl:hover{background:var(--well)}
html.th-on .pillars .pl.soon{cursor:default}html.th-on .pillars .pl.soon img{opacity:.5}
html.th-on .pillars .pl em{font:600 12px/16px var(--sans);letter-spacing:.06em;text-transform:uppercase;color:var(--acc-t);background:var(--acc-w);border-radius:999px;padding:2px 6px;font-style:normal}
/* 5 Sep 2026 — the dark face: the accent wash sat the 10px word at 4.31:1 (measured on about.html); the secondary ink on the rail hover clears 4.5 */
html.th-on[data-theme="dark"] .pillars .pl em{color:var(--th-ink2);background:var(--well)}
html.th-on #thBrand[aria-current]::after,html.th-on .pillars .pl[aria-current]::after{content:'';position:absolute;left:8px;right:8px;bottom:-10px;height:2px;border-radius:2px;background:var(--acc)}
html.th-on #thBrand{position:relative}html.th-on #thH .in>a:first-child{position:relative}
html.th-on #thBrand[aria-current]::after{bottom:1px;left:0;right:6px}
html.th-on #thH .in>a:first-child{display:inline-flex;align-items:center;height:40px}html.th-on #thH .in>.pillars{margin-left:0}
@media(max-width:1023px){html.th-on .pillars .pl img.wm{display:none}html.th-on .pillars .pl img.sy{display:block}html.th-on .pillars .pl em{display:none}}
@media(max-width:639px){html.th-on .pillars{display:none}}
/* the bar sits above the rails on a desk, so its menus open in front of them; on a phone the drawer keeps the top */
@media(min-width:768px){html.th-on #thTop{z-index:70!important}}
html.th-on [hidden]{display:none!important}  /* the hidden attribute always wins: a display rule on a class (e.g. .sr-pick{display:grid}) outranked the browser default and showed a hidden picker, found 3 Sep 2026 */
/* the public site's header and footer */
html.th-on #thH{background:var(--sheet)!important;border-bottom:1px solid var(--line)!important;backdrop-filter:none!important}
html.th-on #thH nav a{color:var(--th-ink2)}html.th-on #thH nav a:hover{color:var(--th-ink)}
html.th-on #thH .cta,html.th-on #thH .pill{background:var(--acc);color:var(--acc-on);border-radius:var(--th-rsm);height:var(--th-h);display:inline-flex;align-items:center;padding:0 var(--s4);font-weight:600}
html.th-on #thF{background:var(--sheet)!important;border-top:1px solid var(--line)!important;color:var(--th-mut)!important}
html.th-on #thF h4{color:var(--th-ink);font:600 12px/16px var(--sans);letter-spacing:.06em}
html.th-on #thF a{color:var(--th-mut)}html.th-on #thF a:hover{color:var(--acc-t)}
html.th-on #thF .trust{color:var(--c-money)}


/* ── 4-2 · THE SHELL, 2026 — the bar breathes, the first rail sits a step lower than the sheet, rows are pills of light,
   the search is a pill that wakes on focus. Same markup, same ids; only the wear. Heights move from 56 to 60 in the
   four places the sheet owns them. */
html.th-on #thTop{height:calc(60px + env(safe-area-inset-top,0))!important;box-shadow:0 1px 0 var(--line),var(--sh-micro)}
html.th-on #thGnav,html.th-on #thSide,html.th-on #thRight{top:calc(60px + env(safe-area-inset-top,0))!important}
html.th-on body{padding-top:calc(60px + env(safe-area-inset-top,0))!important}
html.th-on #thGnav{background:linear-gradient(var(--well),var(--well)) var(--sheet)!important}
html.th-on #thGnav .gi{height:44px;border-radius:var(--th-rsm);transition:background-color var(--t-fast) var(--ease),color var(--t-fast) var(--ease)}
html.th-on #thGnav .gi[aria-current]{box-shadow:inset 3px 0 0 var(--acc)}
html.th-on #thNav a{height:40px;border-radius:var(--th-rsm);padding:0 var(--s3);transition:background-color var(--t-fast) var(--ease),color var(--t-fast) var(--ease)}
html.th-on #thSide .sr,html.th-on #thTop .sr{height:var(--th-h);border-radius:var(--th-btn);padding:0 var(--s4);background:var(--well2);border-color:transparent;transition:background-color var(--t-fast) var(--ease),border-color var(--t-fast) var(--ease),box-shadow var(--t-base) var(--ease)}
html.th-on #thSide .sr:focus-within,html.th-on #thTop .sr:focus-within{background:var(--sheet);border-color:var(--acc);box-shadow:0 0 0 3px var(--acc-w)}
html.th-on #thTop .ib,html.th-on #thTop .bg{border-radius:var(--th-btn);border-color:transparent;background:var(--well2);transition:background-color var(--t-fast) var(--ease),border-color var(--t-fast) var(--ease)}
html.th-on #thTop .ib:hover,html.th-on #thTop .bg:hover{border-color:var(--th-line2)}
html.th-on #thTop #thAcct{background:var(--well2);border:1px solid transparent}
html.th-on #thTop #thAcct:hover{border-color:var(--th-line2)}
html.th-on .pillars .pl img{height:20px}
html.th-on .pillars .pl{height:40px;padding:0 10px;border-radius:var(--th-btn);transition:background-color var(--t-fast) var(--ease)}
html.th-on #thRight .qa a{border-radius:var(--th-rsm);border-color:var(--edge);box-shadow:var(--lift-1);transition:box-shadow var(--t-base) var(--ease),transform var(--t-base) var(--ease)}
html.th-on #thRight .qa a:hover{box-shadow:var(--lift-hover);transform:translateY(-1px)}
html.th-on #thH .cta,html.th-on #thH .pill{border-radius:var(--th-btn);box-shadow:0 1px 2px rgba(var(--shadow-c),.14),0 8px 20px -12px rgba(var(--shadow-c),.45)}
html.th-on #thUser{border-color:var(--edge);box-shadow:var(--lift-1)}

/* ── 4b · MAP CHROME — GeoMundra's panels over the world (Law 100, 3 Sep 2026).
   The map is the map — its artwork stays in the map style. Everything a person
   reads or presses on top of it is platform furniture: white panels on the one
   light theme, navy ink, deep teal for the one action, the same faces, the same
   radius. The pages keep only geometry (position, size, gap) in <style data-layout>.
   Status on alerts is Tier Two colour (Law 78): watch, risk, money, each with a word. */
html.th-on .bar{background:var(--sheet);border-bottom:1px solid var(--line)}
html.th-on .wordmark,html.th-on .wm{color:var(--th-ink);text-decoration:none}
html.th-on .wordmark .strap,html.th-on .hud .strap{color:var(--th-mut);font-size:12px;font-weight:600;letter-spacing:.14em;text-transform:uppercase}
html.th-on .search .go{background:none;border:0;color:var(--th-mut);cursor:pointer}
html.th-on .search .go:hover{color:var(--acc-t)}
html.th-on .search .hits{background:var(--sheet);border:1px solid var(--line);border-radius:var(--th-r);box-shadow:0 12px 30px rgba(var(--shadow-c),.16)}
html.th-on .search .hits button{background:none;border:0;border-bottom:1px solid var(--line);color:var(--th-ink);font:inherit;font-size:13px;cursor:pointer}
html.th-on .search .hits button:last-child{border-bottom:0}
html.th-on .search .hits button:hover{background:var(--well)}
html.th-on .search .hits .src,html.th-on .res .sub2{color:var(--th-mut);font-size:12px}
html.th-on .tzchip,html.th-on .help,html.th-on .compass{background:var(--sheet);border:1px solid var(--line);border-radius:999px;color:var(--th-mut);font-size:12px;font-weight:600;font-variant-numeric:tabular-nums}
html.th-on .tzchip b,html.th-on .help b,html.th-on .compass b{color:var(--th-ink)}
html.th-on .thlink,html.th-on .backlink,html.th-on .views button,html.th-on .vis button,html.th-on .fuelbar button{background:var(--sheet);border:1px solid var(--th-line2);border-radius:var(--th-rsm);color:var(--th-ink);font:inherit;font-size:13px;font-weight:600;text-decoration:none;cursor:pointer}
html.th-on .thlink:hover,html.th-on .backlink:hover,html.th-on .views button:hover,html.th-on .vis button:hover,html.th-on .fuelbar button:hover{border-color:var(--acc);color:var(--acc-t)}
html.th-on .thlink .dot{background:var(--th-mut);border-radius:50%}
html.th-on .views button[disabled]{opacity:.55;cursor:default}
html.th-on .views button[disabled]:hover{border-color:var(--th-line2);color:var(--th-ink)}
html.th-on .views .soon,html.th-on .fuelbar .fl,html.th-on .pres h2,html.th-on .lpanel h2,html.th-on .lpanel .lgrp,html.th-on .live h2,html.th-on .sky h2,html.th-on .sky .grp{color:var(--th-mut);font-size:12px;font-weight:590;letter-spacing:.12em;text-transform:uppercase}
html.th-on .vis button.on,html.th-on .fuelbar button[aria-pressed="true"]{background:var(--acc);border-color:var(--acc);color:#fff}
html.th-on .fuelbar button .n{font-size:12px;opacity:.75;font-weight:600}
html.th-on .fuelbar .none,html.th-on .pres .state,html.th-on .pres .count,html.th-on .lnote,html.th-on .lcatline,html.th-on .lfresh,html.th-on .lmeta,html.th-on .lnone,html.th-on .stream,html.th-on .live .src,html.th-on .sky .src,html.th-on .sky .note,html.th-on .sky .obj .az,html.th-on .sky .obj .sub,html.th-on .doorsrc,html.th-on .doorbox p.sub,html.th-on .pcard span{color:var(--th-mut)}
html.th-on .pres,html.th-on .fuelbar,html.th-on .lpanel,html.th-on .toast,html.th-on .live,html.th-on .sky,html.th-on .res,html.th-on .alert,html.th-on .peerpop,html.th-on .maplibregl-popup-content{background:rgba(255,255,255,.96);border:1px solid var(--line);border-radius:var(--th-r);color:var(--th-ink);box-shadow:0 8px 24px rgba(18,57,85,.14);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}
html.th-on .maplibregl-popup-content{padding:8px 12px!important;font-size:13px}
html.th-on .maplibregl-popup-tip{border-top-color:#fff!important;border-bottom-color:#fff!important}
html.th-on .maplibregl-ctrl-attrib{background:rgba(255,255,255,.8)!important;color:var(--th-mut)!important;font-size:12px}
html.th-on .maplibregl-ctrl-attrib a{color:var(--th-mut)!important}
html.th-on .pres .state b{color:var(--th-ink);font-weight:600}
html.th-on .pres .count b,html.th-on .stream b,html.th-on .pcard em,html.th-on .whochip button,html.th-on .lpre button.on,html.th-on .lcat:hover .lcat-name,html.th-on .lback:hover{color:var(--acc-t)}
html.th-on .peer{background:var(--acc);border:2.5px solid #fff;border-radius:50%;box-shadow:0 0 0 2px var(--acc),0 2px 8px rgba(var(--shadow-c),.35);cursor:pointer}
html.th-on .peer.me{background:var(--th-ink);box-shadow:0 0 0 2px var(--th-ink),0 2px 8px rgba(var(--shadow-c),.35)}
html.th-on .lpanel .lgrp{border-top:1px solid var(--line)}
html.th-on .lpanel .lgrp:first-of-type{border-top:0}
html.th-on .lrow{color:var(--th-ink);font-size:13px}
html.th-on .lrow input{accent-color:var(--acc);cursor:pointer}
html.th-on .lrow label{cursor:pointer}
html.th-on .lrow .sw{border:1px solid var(--th-line2);border-radius:var(--th-btn,10px)}
html.th-on .lrow.soon{opacity:.55}
html.th-on .lrow.soon label{cursor:default}
html.th-on .lrow .s2,html.th-on .lsubhead .all,html.th-on .lcat-count,html.th-on .lcat-chev{color:var(--th-mut);font-size:12px;font-weight:590;letter-spacing:.06em}
html.th-on .lrow .s2{background:var(--well);border:1px solid var(--line);border-radius:var(--th-rsm)}
html.th-on .lcat{border-bottom:1px solid var(--line);cursor:pointer}
html.th-on .lcat:last-of-type{border-bottom:0}
html.th-on .lcat-name{color:var(--th-ink);font-size:13px;font-weight:600}
html.th-on .lsw .tr{background:var(--well);border:1px solid var(--th-line2);border-radius:12px;transition:.15s}
html.th-on .lsw .kn{background:var(--th-mut);border-radius:50%;transition:.15s}
html.th-on .lsw input:checked ~ .tr,html.th-on .lsw.half .tr{background:var(--acc-w);border-color:var(--acc)}
html.th-on .lsw input:checked ~ .kn,html.th-on .lsw.half .kn{background:var(--acc)}
html.th-on .lback{color:var(--th-mut);cursor:pointer;font-size:12px;font-weight:600}
html.th-on .lsubhead{border-bottom:1px solid var(--line)}
html.th-on .lsubhead .n{font-weight:590}
html.th-on .lsearch,html.th-on .find input{background:var(--sheet);border:1px solid var(--th-line2);border-radius:var(--th-rsm);color:var(--th-ink);font:inherit;font-size:16px;outline:0}
html.th-on .lsearch::placeholder,html.th-on .find input::placeholder{color:var(--th-mut)}
html.th-on .lsearch:focus,html.th-on .find input:focus,html.th-on .search input:focus{border-color:var(--acc);box-shadow:0 0 0 3px var(--acc-w)}
html.th-on .lpre button{background:var(--sheet);border:1px solid var(--th-line2);border-radius:999px;color:var(--th-ink);font:inherit;font-size:12px;font-weight:600;cursor:pointer}
html.th-on .lpre button:hover{border-color:var(--acc);color:var(--acc-t)}
html.th-on .lpre button.on{background:var(--acc-w);border-color:var(--acc)}
html.th-on .lfresh b{color:var(--th-ink);font-weight:600}
html.th-on .toast{opacity:0;transition:opacity .3s;pointer-events:none}
html.th-on .toast.show{opacity:1}
html.th-on .door{background:var(--scrim);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
html.th-on .doorbox{background:var(--sheet);border:1px solid var(--line);border-radius:var(--th-r);box-shadow:0 24px 60px rgba(var(--shadow-c),.28)}
html.th-on .doorbox h1{color:var(--th-ink)}
html.th-on .pcard{background:var(--sheet);border:1px solid var(--th-line2);border-radius:var(--th-r);color:var(--th-ink);font:inherit;cursor:pointer;transition:border-color .15s}
html.th-on .pcard:hover{border-color:var(--acc)}
html.th-on .pcard.locked{opacity:.6;cursor:default}
html.th-on .pcard.locked:hover{border-color:var(--th-line2)}
html.th-on .pcard.locked em{color:var(--th-mut)}
html.th-on .pcard b{color:var(--th-ink);font-weight:600}
html.th-on .pcard em{font-style:normal;font-size:12px;font-weight:600}
html.th-on .doorfoot button{background:none;border:0;color:var(--th-mut);font:inherit;font-size:13px;cursor:pointer;text-decoration:underline}
html.th-on .doorfoot button:hover{color:var(--th-ink)}
html.th-on .whochip{background:var(--well);border:1px solid var(--line);border-radius:var(--th-rsm);font-size:12px}
html.th-on .whochip button{background:none;border:0;font:inherit;font-size:12px;cursor:pointer}
html.th-on .live .place{color:var(--th-ink);font-weight:590}
html.th-on .live .row{color:var(--th-ink)}
html.th-on .live .row span:first-child{color:var(--th-mut)}
html.th-on .live .dot{background:var(--acc);border-radius:50%;box-shadow:0 0 8px var(--acc);animation:th-pulse 2.2s infinite}
@keyframes th-pulse{50%{opacity:.35}}
html.th-on .sky .obj{border-bottom:1px solid var(--line)}
html.th-on .sky .obj:last-of-type{border-bottom:0}
html.th-on .sky .obj .nm{font-weight:600}
html.th-on .sky .obj.down{opacity:.45}
html.th-on .sky .grp{border-top:1px solid var(--line)}
html.th-on .res div{border-bottom:1px solid var(--line);cursor:pointer;font-size:13px}
html.th-on .res div:last-child{border-bottom:0}
html.th-on .res div:hover{background:var(--well)}
html.th-on .fc div{background:var(--well);border:1px solid var(--line);border-radius:var(--th-rsm)}
html.th-on .fc .t,html.th-on .fc .p{color:var(--th-mut);font-size:12px;text-transform:uppercase;letter-spacing:.04em}
html.th-on .fc .v{font-weight:590}
html.th-on .alert{border-left:3px solid var(--acc);cursor:pointer;transition:opacity .6s}
html.th-on .alert b{font-size:13px}
html.th-on .alert span{color:var(--th-mut)}
html.th-on .alert.warn{border-left-color:var(--c-watch)}
html.th-on .alert.bad{border-left-color:var(--c-risk)}
html.th-on .alert.ok{border-left-color:var(--c-money)}
@media(prefers-reduced-motion:reduce){html.th-on .live .dot{animation:none}}
html.th-on .gm-mut{color:var(--th-mut)}html.th-on .gm-ink{color:var(--th-ink)}html.th-on .gm-gold{color:var(--bz)}html.th-on .gm-warn{color:var(--c-watch)}html.th-on .gm-acc{color:var(--acc-t)}html.th-on .gm-line-t{border-top:1px solid var(--line)}html.th-on .gm-well{background:var(--well)}


/* ── 4b-2 · THE MAP CHROME, 2026 — glass at blur(12px) (§10), the lift, pills; the map stays the map. The panels take
   the sheet at 86% with the blur behind, so the world shows through the furniture the way it does in the best map
   software; in the sun every shadow and blur is stripped by the rule above. Pressed view buttons finally show it. */
html.th-on .bar{background:var(--glass);-webkit-backdrop-filter:blur(12px) saturate(1.2);backdrop-filter:blur(12px) saturate(1.2);border-bottom:1px solid rgba(var(--shadow-c),.08);box-shadow:var(--sh-micro)}
html.th-on .pres,html.th-on .fuelbar,html.th-on .lpanel,html.th-on .live,html.th-on .sky,html.th-on .res,html.th-on .alert,html.th-on .peerpop,html.th-on .maplibregl-popup-content,html.th-on .sospanel{background:var(--glass);-webkit-backdrop-filter:blur(12px) saturate(1.2);backdrop-filter:blur(12px) saturate(1.2);border:1px solid var(--glass-edge);border-radius:var(--th-r-lg);box-shadow:0 0 0 1px rgba(var(--shadow-c),.08),var(--lift-2)}
html.th-on .maplibregl-popup-content{border-radius:var(--th-r)!important;padding:10px 14px!important;font-size:13px}
html.th-on .views button,html.th-on .vis button,html.th-on .fuelbar button,html.th-on .thlink,html.th-on .backlink{height:40px;border-radius:var(--th-btn);border-color:rgba(var(--shadow-c),.10);background:var(--glass);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);box-shadow:var(--lift-1);font-weight:600;transition:background-color var(--t-fast) var(--ease),border-color var(--t-fast) var(--ease),color var(--t-fast) var(--ease),box-shadow var(--t-base) var(--ease),transform var(--t-fast) var(--ease)}
html.th-on .views button:hover,html.th-on .vis button:hover,html.th-on .fuelbar button:hover{box-shadow:var(--lift-hover);border-color:var(--acc)}
html.th-on .views button[aria-pressed="true"],html.th-on .vis button.on,html.th-on .fuelbar button[aria-pressed="true"]{background:var(--acc-w);border-color:var(--acc);color:var(--acc-t)}
html.th-on .views button:active,html.th-on .vis button:active,html.th-on .fuelbar button:active{transform:scale(.96)}
html.th-on .lpanel h2,html.th-on .lpanel .lgrp,html.th-on .pres h2,html.th-on .fuelbar .fl,html.th-on .live h2,html.th-on .sky h2,html.th-on .sky .grp{font-size:12px;letter-spacing:.1em}
html.th-on .lrow{font-size:14px}
html.th-on .lsearch,html.th-on .find input{height:36px;border-radius:var(--th-btn);padding:0 var(--s4);background:var(--well2);border-color:transparent;font-size:16px}
html.th-on .lsearch:focus,html.th-on .find input:focus{background:var(--sheet);border-color:var(--acc)}
html.th-on .lpre button{height:30px;padding:0 12px}
html.th-on .pcard{border-radius:var(--th-r);border-color:var(--edge);box-shadow:var(--lift-1);transition:box-shadow var(--t-base) var(--ease),transform var(--t-base) var(--ease),border-color var(--t-fast) var(--ease)}
html.th-on .pcard:hover{box-shadow:var(--lift-hover);transform:translateY(-2px)}
html.th-on .doorbox{border-radius:var(--th-r-lg);box-shadow:var(--lift-3)}
html.th-on .tzchip,html.th-on .help,html.th-on .compass{background:var(--glass);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border-color:rgba(var(--shadow-c),.10);box-shadow:var(--lift-1)}
html.th-on .toast{background:var(--th-ink)}

/* ── 4c · THE SITE RECORD — diary, permits, conditions, inspections, securities (3 Sep 2026).
   th-site-record.js draws one list grammar for every record on a place; the pages kept
   only geometry under Law 100 and the chips had no paint anywhere. Standing is Tier Two
   colour with a word: green = settled, watch = due or expiring, risk = failed or called. */
html.th-on .sr-lede{color:var(--th-ink2);max-width:70ch}
html.th-on .sr-mut{color:var(--th-mut);font-size:13px}
html.th-on .sr-say{background:var(--acc-w);border:1px solid var(--acc);border-radius:var(--th-rsm);color:var(--th-ink);padding:var(--s2) var(--s3);font-size:13px}
html.th-on .sr-say.is-bad{background:var(--c-risk-w);border-color:var(--c-risk);color:var(--c-risk)}
html.th-on .sr-list{list-style:none;margin:0;padding:0;display:grid;gap:var(--s3)}
html.th-on .sr-item{background:var(--sheet);border:1px solid var(--line);border-radius:var(--th-r);padding:var(--s4) var(--s5)}
html.th-on .sr-item.is-sealed{border-color:var(--th-line2)}
html.th-on .sr-item.is-bad{border-color:var(--c-risk)}
html.th-on .sr-head{display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap;margin-bottom:var(--s2)}
html.th-on .sr-date{font-weight:600;color:var(--th-ink)}
html.th-on .sr-chip{display:inline-flex;align-items:center;height:22px;padding:0 var(--s2);border-radius:999px;font:500 12px var(--sans);background:var(--well2);color:var(--th-ink);white-space:nowrap}
html.th-on .sr-chip-sealed,html.th-on .sr-chip-done,html.th-on .sr-chip-current,html.th-on .sr-chip-released{background:var(--c-money-w);color:var(--c-money)}
html.th-on .sr-chip-expiring,html.th-on .sr-chip-overdue,html.th-on .sr-chip-hold,html.th-on .sr-chip-due-release{background:var(--c-watch-w);color:var(--c-watch)}
html.th-on .sr-chip-expired,html.th-on .sr-chip-ncr,html.th-on .sr-chip-called{background:var(--c-risk-w);color:var(--c-risk)}
html.th-on .sr-body{margin:0 0 var(--s2)}
html.th-on .sr-f{display:flex;gap:var(--s2);font-size:13px;padding:2px 0}
html.th-on .sr-k{color:var(--th-mut);min-width:110px;flex:none}
html.th-on .sr-v{color:var(--th-ink)}
html.th-on .sr-acts{display:flex;gap:var(--s2);flex-wrap:wrap;align-items:center;margin-top:var(--s3)}
html.th-on .sr-amends{border-top:1px solid var(--line);margin-top:var(--s3);padding-top:var(--s2)}
html.th-on .sr-amend-row{padding:var(--s2) 0;border-bottom:1px dashed var(--line)}
html.th-on .sr-plan{margin-bottom:var(--s4)}
html.th-on .sr-plan h2{font:600 15px/20px var(--sans);margin:0 0 var(--s3)}
html.th-on .sr-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:var(--s3)}
html.th-on .sr-grid label{display:grid;gap:var(--s1);font-size:13px;color:var(--th-mut)}
html.th-on .sr-grid input,html.th-on .sr-grid select{width:100%}
html.th-on .sr-pick{display:grid;gap:var(--s1);min-width:260px}

/* ── 4c·ii · THE LICENCE GRAMMAR — three things the sr- set had no word for (12 Sep 2026).
   Added for the premises licence register (mig1212/mig1213), and written as part of the shared
   set rather than in the page, because a second register with conditions under it will want the
   same three and Law 100 says one system paints everything.
     .sr-law    what instrument a row was read against — or, far more often, the sentence saying
                NOBODY HAS READ ONE. It is deliberately quiet: it is not a warning, it is an
                honest note about what the platform does and does not know.
     .sr-sub    a record hanging off another record — a condition under its licence. Inset and
                tinted so the nesting is visible without another card border.
     .sr-more   one primary action per row and the rest behind one control, Sean's ruling of
                11 Sep 2026. A native <details>, so it works with no JavaScript and the keyboard
                gets it for free. */
html.th-on .sr-law{border-left:2px solid var(--th-line2);background:var(--well2);border-radius:0 var(--th-rsm) var(--th-rsm) 0;padding:var(--s2) var(--s3);margin:var(--s3) 0 0;font-size:13px;color:var(--th-ink2)}
html.th-on .sr-law strong{color:var(--th-ink);font-weight:600}
html.th-on .sr-law p{margin:var(--s1) 0 0}
html.th-on .sr-law.is-read{border-left-color:var(--c-money);background:var(--c-money-w)}
html.th-on .sr-law a{color:var(--acc);text-decoration:underline}

html.th-on .sr-subs-wrap{border-top:1px solid var(--line);margin-top:var(--s3);padding-top:var(--s3)}
html.th-on .sr-subs-h{font:600 12px/16px var(--sans);text-transform:uppercase;letter-spacing:.06em;color:var(--th-mut);margin:0 0 var(--s2)}
html.th-on .sr-subs{list-style:none;margin:0;padding:0;display:grid;gap:var(--s2)}
html.th-on .sr-sub{background:var(--well2);border:1px solid var(--line);border-radius:var(--th-rsm);padding:var(--s3)}
html.th-on .sr-sub .sr-head{margin-bottom:var(--s1)}
html.th-on .sr-sub .sr-body{margin:0 0 var(--s1)}
html.th-on .sr-sub .sr-acts{margin-top:var(--s2)}
/* A VOIDED ROW IS DIMMED, NEVER HIDDEN. It happened, and the reason is on it. */
html.th-on .sr-sub.is-void{border-style:dashed;opacity:.72}

html.th-on .sr-more{position:relative}
html.th-on .sr-more>summary{list-style:none;cursor:pointer;display:inline-flex;align-items:center;gap:var(--s1);min-height:44px;padding:0 var(--s3);border:1px solid var(--line);border-radius:var(--th-rsm);background:var(--sheet);color:var(--th-ink2);font:500 13px var(--sans)}
html.th-on .sr-more>summary::-webkit-details-marker{display:none}
html.th-on .sr-more>summary::after{content:'';width:6px;height:6px;border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;transform:rotate(45deg) translateY(-2px)}
html.th-on .sr-more[open]>summary::after{transform:rotate(-135deg) translateY(-1px)}
html.th-on .sr-more>summary:hover{border-color:var(--th-line2);color:var(--th-ink)}
html.th-on .sr-more>summary:focus-visible{outline:2px solid var(--acc);outline-offset:2px}
html.th-on .sr-more-in{display:grid;gap:var(--s2);margin-top:var(--s2);padding:var(--s3);background:var(--well2);border:1px solid var(--line);border-radius:var(--th-rsm);justify-items:start}
html.th-on .sr-more-in .btn{width:100%;justify-content:flex-start}

/* ── 4c·iii · THE ASK — one inline editor, replacing 153 native dialogs (13 Sep 2026).
   th-ask.js opens this next to the control that asked for it. It is NOT a modal: no overlay,
   nothing centred, nothing trapped — on a phone the member keeps their place in the list they
   were reading, which is the whole reason a dialog was the wrong control here.
   Targets are 44px, inputs are 16px so iOS does not zoom the page when one is focused, and the
   error line is a sentence under its own field rather than a banner at the top. */
/* ── THE RANKING, PRINTED. Sean, in his own words: "publish the ranking algorithm — the 0% fee is
   the only reason we CAN". It sits on board.html above the pool, closed by default, because a trade
   who wants to know why they did not get a job should find the answer where the job was. */
html.th-on .howshared{border:1px solid var(--line);border-radius:var(--th-rsm);background:var(--well2);margin:0 0 var(--s3)}
html.th-on .howshared>summary{list-style:none;cursor:pointer;min-height:44px;display:flex;align-items:center;gap:var(--s2);padding:0 var(--s3);font:600 13px var(--sans);color:var(--th-ink)}
html.th-on .howshared>summary::-webkit-details-marker{display:none}
html.th-on .howshared>summary::after{content:'';width:6px;height:6px;border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;transform:rotate(45deg) translateY(-2px)}
html.th-on .howshared[open]>summary::after{transform:rotate(-135deg) translateY(-1px)}
html.th-on .howshared>summary:focus-visible{outline:2px solid var(--acc);outline-offset:2px}
html.th-on .howshared-in{padding:0 var(--s3) var(--s3);font-size:13px;color:var(--th-ink2);max-width:72ch}
html.th-on .howshared-in p{margin:0 0 var(--s2)}
html.th-on .howshared-in ul{margin:0 0 var(--s2);padding-left:var(--s4);display:grid;gap:var(--s1)}
html.th-on .howshared-in strong{color:var(--th-ink)}
html.th-on .howshared-hard{border-left:2px solid var(--acc);padding-left:var(--s3);margin-top:var(--s3)}

html.th-on .th-ask-host{margin-top:var(--s2)}
html.th-on .th-ask{border:1px solid var(--acc);border-left-width:2px;border-radius:var(--th-rsm);background:var(--sheet);padding:var(--s3) var(--s4);display:grid;gap:var(--s3)}
html.th-on .th-ask-t{font:600 14px/20px var(--sans);color:var(--th-ink);margin:0}
html.th-on .th-ask-lede{font-size:13px;color:var(--th-ink2);margin:calc(var(--s1) * -1) 0 0;max-width:66ch}
html.th-on .th-ask-fs{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:var(--s3)}
html.th-on .th-ask-f{display:grid;gap:var(--s1);align-content:start}
html.th-on .th-ask-f label{font-size:13px;color:var(--th-mut)}
html.th-on .th-ask-opt{color:var(--th-mut);opacity:.8}
html.th-on .th-ask-f input,html.th-on .th-ask-f textarea,html.th-on .th-ask-f select{width:100%;min-height:44px;font-size:16px;font-family:var(--sans)}
html.th-on .th-ask-f textarea{min-height:78px;resize:vertical;line-height:1.45}
html.th-on .th-ask-hint{font-size:12px;color:var(--th-mut);margin:0}
html.th-on .th-ask-err{font-size:12px;color:var(--c-risk);margin:0}
html.th-on .th-ask-f.is-bad input,html.th-on .th-ask-f.is-bad textarea,html.th-on .th-ask-f.is-bad select{border-color:var(--c-risk)}
html.th-on .th-ask-acts{display:flex;gap:var(--s2);flex-wrap:wrap;align-items:center}
html.th-on .th-ask-acts .btn{min-height:44px}
html.th-on .th-ask-note{font-size:12px;color:var(--th-mut);flex:1;min-width:180px}
/* A destructive save says so in its colour as well as its words (Law 79: never hue alone —
   the word on the button carries it too). */
html.th-on .th-ask .btn.is-danger{background:var(--c-risk);border-color:var(--c-risk);color:#fff}
@media (max-width:600px){
  html.th-on .th-ask-fs{grid-template-columns:1fr}
  html.th-on .th-ask-acts .btn{flex:1}
}

/* ── 4d · THE CLOCKS — tenancy, work orders, custody, hire, due diligence, clocks (3 Sep 2026).
   Six modules (th-tenancy, th-workorder, th-custody, th-hire-contract, th-duediligence,
   th-clocks) on nineteen pages share one t- grammar: an item, a head with a chip, key/value
   rows, a meter with a number and a label, a say line. The pages hold only geometry under
   Law 100 and nothing painted the tones; a chip that says "urgent" was the same grey as one
   that says "ok". Tier Two colour with the word beside it, the same wash as the site record:
   ok = settled (green) · soon / warn = watch · urgent = risk · gone = over, in ink on the line. */
html.th-on .t-item{background:var(--sheet);border:1px solid var(--line);border-radius:var(--th-r)}
html.th-on .t-item.t-urgent{border-left:3px solid var(--c-risk)}
html.th-on .t-item.t-soon,html.th-on .t-item.t-warn{border-left:3px solid var(--c-watch)}
html.th-on .t-item.t-ok{border-left:3px solid var(--c-money)}
html.th-on .t-item.t-gone{border-color:var(--th-line2)}
html.th-on .t-title{font-weight:600;color:var(--th-ink)}
html.th-on .t-chip{display:inline-flex;align-items:center;height:22px;border-radius:999px;font:500 12px var(--sans);background:var(--well2);color:var(--th-ink);white-space:nowrap}
html.th-on .t-chip-ok{background:var(--c-money-w);color:var(--c-money)}
html.th-on .t-chip-soon,html.th-on .t-chip-warn{background:var(--c-watch-w);color:var(--c-watch)}
html.th-on .t-chip-urgent{background:var(--c-risk-w);color:var(--c-risk)}
html.th-on .t-chip-gone{background:var(--well);color:var(--th-mut);border:1px solid var(--line)}
html.th-on .t-k{color:var(--th-mut);font-size:13px}
html.th-on .t-v{color:var(--th-ink);font-size:13px}
/* D24, 3 Sep 2026: MONEY HAS ONE CLASS. Every amount — .money, .amt, .price, .t-money — is painted here and nowhere else: tabular figures so columns of amounts line up, 600 weight, the ink. A page keeps its own class name; the sheet decides what money looks like. */
html.th-on .money,html.th-on .amt,html.th-on .price,html.th-on .t-money{font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1;font-weight:600;color:var(--th-ink);white-space:nowrap}
html.th-on .t-mut,html.th-on .t-sub{color:var(--th-mut);font-size:13px}
html.th-on .t-ledger{background:var(--well);border-radius:var(--th-rsm);padding:var(--s2) var(--s3);margin:var(--s2) 0}
html.th-on .t-meters{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:var(--s3)}
html.th-on .t-meter{background:var(--sheet);border:1px solid var(--line);border-radius:var(--th-r);padding:var(--s3) var(--s4)}
html.th-on .t-meter .t-n{display:block;font:600 24px/28px var(--sans);color:var(--th-ink);font-variant-numeric:tabular-nums}
html.th-on .t-meter .t-l{display:block;color:var(--th-mut);font-size:12px}
html.th-on .t-meter.t-urgent{border-color:var(--c-risk)}html.th-on .t-meter.t-urgent .t-n{color:var(--c-risk)}
html.th-on .t-meter.t-soon .t-n,html.th-on .t-meter.t-warn .t-n{color:var(--c-watch)}
html.th-on .t-meter.t-ok .t-n{color:var(--c-money)}
html.th-on .t-say{background:var(--acc-w);border:1px solid var(--acc);border-radius:var(--th-rsm);color:var(--th-ink);font-size:13px}
html.th-on .t-say.is-bad{background:var(--c-risk-w);border-color:var(--c-risk);color:var(--c-risk)}
html.th-on .t-fail{background:var(--c-risk-w);border:1px solid var(--c-risk);border-radius:var(--th-rsm);color:var(--c-risk)}
html.th-on .t-empty{background:var(--sheet);border:1px dashed var(--line);border-radius:var(--th-r);color:var(--th-mut)}
html.th-on .t-empty-t{color:var(--th-ink);font-weight:600}
html.th-on .t-lede{color:var(--th-ink2)}
html.th-on .t-top{border-bottom:1px solid var(--line)}
html.th-on .t-h2{font:600 15px/20px var(--sans);color:var(--th-ink);margin:var(--s4) 0 var(--s2)}
html.th-on .t-body{color:var(--th-ink2);font-size:13px}

/* 4 Sep 2026 · member progress · the record is in _patch and the board */
html.th-on .th-case{background:radial-gradient(1100px 480px at 18% -10%, rgba(0,184,187,.10), transparent 60%),radial-gradient(900px 480px at 92% 110%, rgba(123,92,255,.08), transparent 60%),linear-gradient(180deg,#FFFFFF 0%,#D0E5F5 100%);color:var(--th-ink);border-radius:var(--th-r);padding:var(--s6) var(--s5)}   /* light: a navy wash on the Poseidon ramp, Poseidon ink */
html.th-on .th-case h1,html.th-on .th-case h2,html.th-on .th-case h3{color:var(--th-ink)}
html.th-on .th-case .note,html.th-on .th-case .muted,html.th-on .th-case p{color:var(--th-ink2)}
html.th-on .th-case a{color:var(--acc-t)}
html.th-on .th-case .card,html.th-on .th-case .tile{background:rgba(255,255,255,.62);border:1px solid #ABD1ED;color:var(--th-ink);box-shadow:none}
html.th-on .th-case .eyebrow{color:var(--acc-t);font-size:12px;letter-spacing:.14em;text-transform:uppercase;font-weight:590}
/* 9 Sep 2026 · ONE VOICE PER SIZE. This rule switched the TYPEFACE on any element
   marked .num, so a figure inside a sentence came out in JetBrains Mono while the
   words around it stayed in Instrument Sans — measured on levels.html: mono and sans
   both in use at 11, 12, 13 AND 14px. Two faces at one size sit on different
   baselines with different digit widths, and that is what reads as 'not aligned'.
   tabular-nums gives a column of figures that line up perfectly WITHOUT changing
   voice, which is all .num was ever for. Mono stays where it is asked for by name —
   code, keys, refs — and nowhere else. */
html.th-on .th-case .num,html.th-on .num{font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1}
html.th-on .th-case .prog{height:5px;border-radius:999px;background:rgba(18,57,85,.12);overflow:hidden}
html.th-on .th-case .prog b{display:block;height:100%;border-radius:999px;background:linear-gradient(90deg,var(--g-aurora),var(--g-cyan))}
html.th-on .th-case .rar{font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:var(--th-mut)}
html.th-on .th-case .locked .cap{color:var(--th-ink2)}
/* dark: the case sinks below the room and the emblems glow; light ink */
html.th-on[data-theme="dark"] .th-case{background:radial-gradient(1100px 480px at 18% -10%, rgba(0,184,187,.20), transparent 60%),radial-gradient(900px 480px at 92% 110%, rgba(123,92,255,.16), transparent 60%),linear-gradient(180deg,var(--surface-sunk,#071520) 0%,#071520 100%);color:#FAFCFE}
html.th-on[data-theme="dark"] .th-case h1,html.th-on[data-theme="dark"] .th-case h2,html.th-on[data-theme="dark"] .th-case h3{color:#FAFCFE}
html.th-on[data-theme="dark"] .th-case .note,html.th-on[data-theme="dark"] .th-case .muted,html.th-on[data-theme="dark"] .th-case p{color:#ABD1ED}
html.th-on[data-theme="dark"] .th-case a{color:var(--g-ice)}
html.th-on[data-theme="dark"] .th-case .card,html.th-on[data-theme="dark"] .th-case .tile{background:linear-gradient(180deg,rgba(255,255,255,.05),rgba(255,255,255,.015));border:1px solid var(--g-night-line);color:#FAFCFE}
html.th-on[data-theme="dark"] .th-case .eyebrow{color:var(--g-cyan)}
html.th-on[data-theme="dark"] .th-case .btn-g{background:rgba(255,255,255,.08);color:#FAFCFE;border:1px solid var(--g-night-line)}
html.th-on[data-theme="dark"] .th-case .prog{background:rgba(255,255,255,.1)}
html.th-on[data-theme="dark"] .th-case .rar{color:#ABD1ED}
html.th-on[data-theme="dark"] .th-case .locked .cap{color:#ABD1ED}
/* the points chip: what a moment paid, in exposure */
html.th-on .th-chip{display:inline-flex;align-items:center;gap:8px;padding:6px 12px;border-radius:999px;background:linear-gradient(90deg,var(--g-aurora),var(--g-cyan));color:var(--g-chip-ink);font-weight:590;font-size:13px}
/* the level chip in the top bar: the hexagon and the number, one tap to the case */
html.th-on #thTop .th-lvl{display:inline-flex;align-items:center;gap:6px;padding:0 10px 0 4px;width:auto;text-decoration:none}
html.th-on #thTop .th-lvl .th-em{width:28px;height:28px}
html.th-on #thTop .th-lvl b{font:590 13px/1 var(--mono);color:var(--th-ink)}
html.th-on #thTop .th-lvl i{display:none;width:8px;height:8px;border-radius:50%;background:var(--g-fire);box-shadow:0 0 0 2px var(--sheet)}
html.th-on #thTop .th-lvl.has-new i{display:block}
/* the star tier beside a five-star score — the colour is the count behind it (spine.star_tier) */
html.th-on .th-star{display:inline-block;width:16px;height:16px;vertical-align:-3px}
html.th-on .th-star[data-tier="yellow"]{color:var(--g-gold)}html.th-on .th-star[data-tier="blue"]{color:var(--g-storm)}
html.th-on .th-star[data-tier="turquoise"]{color:var(--g-cyan)}html.th-on .th-star[data-tier="purple"]{color:var(--g-violet)}
html.th-on .th-star[data-tier="red"]{color:var(--g-red)}html.th-on .th-star[data-tier="green"]{color:var(--g-green)}
html.th-on .th-star[data-tier="shooting"]{color:var(--g-pink)}html.th-on .th-star:not([data-tier]){color:var(--th-line2)}
/* the three tracks and a switch, painted here so a page keeps geometry only (Law 100) */
html.th-on .ring-arc[data-track="work"],html.th-on .ring-track[data-track="work"]{color:var(--g-fire)}html.th-on .ring-arc[data-track="people"],html.th-on .ring-track[data-track="people"]{color:var(--g-cyan)}html.th-on .ring-arc[data-track="record"],html.th-on .ring-track[data-track="record"]{color:var(--g-storm)}
html.th-on [role="switch"]{width:46px;height:26px;border-radius:999px;border:0;background:var(--th-line2);position:relative;cursor:pointer;transition:background .2s;font-size:0}
html.th-on [role="switch"]::after{content:"";position:absolute;top:3px;left:3px;width:20px;height:20px;border-radius:50%;background:var(--sheet);box-shadow:0 1px 3px rgba(18,57,85,.3);transition:transform .2s cubic-bezier(.34,1.56,.64,1)}
html.th-on [role="switch"][aria-checked="true"]{background:linear-gradient(90deg,var(--g-aurora),var(--g-cyan))}
html.th-on [role="switch"][aria-checked="true"]::after{transform:translateX(20px)}
html.th-on [role="switch"]:disabled{opacity:.45;cursor:not-allowed}
/* the buttons, throughout: a press that answers the finger, and nothing louder on serious surfaces */
html.th-on .btn{transition:transform .16s cubic-bezier(.34,1.56,.64,1),box-shadow .16s ease,background .16s ease}
html.th-on .btn:active:not(:disabled){transform:scale(.97)}
html.th-on .btn-p:hover:not(:disabled){box-shadow:0 6px 18px color-mix(in srgb,var(--acc) 28%,transparent)}
@media (prefers-reduced-motion:reduce){html.th-on .btn{transition:none}html.th-on .btn:active:not(:disabled){transform:none}}

/* ── 4f · TOUCH — the phone in the hand (4 Sep 2026). Measured live at 386px: rail rows 36px tall, star pins 25px and
   invisible until hover, the lock labels 9.5px, the dock labels 10px, the panel headings 10px. The law says 44px targets and
   56px on site; a phone has no hover. These rules apply under a coarse pointer or a narrow screen and nowhere else. */
@media (pointer:coarse),(max-width:640px){
  html.th-on #thNav a{min-height:44px}
  html.th-on #thNav .thStar{width:40px;height:40px;padding:0;opacity:.55}
  html.th-on .lk,html.th-on #thNav .lk{font-size:12px}
  html.th-on #thRight h4{font-size:12px}
  html.th-on #thSide .sr kbd{display:none}
  html.th-on .btn-sm,html.th-on .btn.sm{height:36px}
  html.th-on #thTop .ib,html.th-on #thTop .bg{width:44px;height:44px}
  html.th-on #thBar a,html.th-on #thBar button{min-height:48px}
  html.th-on #thBar span{font-size:12px}
}

/* ── 5 · RESPONSIVE — the three rules ─────────────────────────────────── */
@media(max-width:767px){html.th-on .kpis,html.th-on .m-kpis{grid-template-columns:repeat(2,minmax(0,1fr))}html.th-on .head,html.th-on .m-hrow,html.th-on .hrow{flex-direction:column;align-items:stretch}html.th-on h1{font-size:22px;line-height:28px}html.th-on .txform{grid-template-columns:1fr!important}}
html.th-on .tbl,html.th-on .table-wrap{overflow-x:auto}

/* ── 6 · PRINT — a member's document never carries our chrome ─────────── */
@media print{html.th-on #thTop,html.th-on #thGnav,html.th-on #thSide,html.th-on #thRight,html.th-on #thH,html.th-on #thF,html.th-on .modbar,html.th-on .btn{display:none!important}html.th-on body{padding:0!important}html.th-on .printonly{display:block}}

/* ── 4g · THE MARKETPLACE — GeoBidder wears colour by CATEGORY and by STATE; the words stay ink ────────────────
   Sean, 4 Sep 2026, on geobidder.html rendered white and grey: "GeoBidder has been punished, can you add a bit of
   design back into it". The page keeps geometry only (Law 100); this is its paint. Twelve category hues, sets of
   three, assigned by FAMILY so one hue means the same thing on every surface — the chip, the tile, the drawer row.
   Tokens only: the game set in th-tier2.css. A glyph sits WHITE on its hue (a badge), a wash is the hue mixed into
   the sheet, so the same rule paints light and dark. */
/* THE FAMILIES, on the colour-vision-safe subset (research-pillars-colour.md, 4 Sep 2026: storm–violet, ice–lilac, aurora–green,
   fire–gold and pink–green collapse under deutan/protan; red stays the word for time running out). Seven hues for twelve families;
   a family shares a hue because the hue means the family; every tile carries its glyph and its word (Law 79). */
[data-cat="vehicles"],[data-cat="vparts"]{--cat:var(--g-storm)}
[data-cat="property"],[data-cat="business"],[data-cat="office"]{--cat:var(--g-aurora)}
[data-cat="plant"],[data-cat="tools"],[data-cat="materials"]{--cat:var(--g-fire)}
[data-cat="tech"],[data-cat="phones"],[data-cat="audio"],[data-cat="photo"],[data-cat="games"]{--cat:var(--g-ice)}
[data-cat="marine"],[data-cat="sports"],[data-cat="hobbies"]{--cat:var(--g-cyan)}
[data-cat="clothing"],[data-cat="cosmetics"],[data-cat="watches"]{--cat:var(--g-pink)}
[data-cat="home"],[data-cat="seasonal"],[data-cat="animals"],[data-cat="books"],[data-cat="films"],[data-cat="music"],[data-cat="toys"],[data-cat="kids"],[data-cat="antiques"],[data-cat="collectables"],[data-cat="coins"],[data-cat="stamps"],[data-cat="tickets"],[data-cat="wine"]{--cat:var(--house)}
/* SEAN, 15 SEP 2026: "I prefer the slightly rounded, squarish corners over
   these round tablet look." MEASURED in his browser: these category links
   render 44px tall at 999px — a full lozenge, the widest one 191px, and the
   most prominent row on the GeoBidder page. The rule already written at
   --th-btn above says which way this goes: a control you PRESS, at field
   height, is --th-btn; only a status indicator or a track stays a pill. A
   44px lozenge is a control, so it takes the platform button shape. The dot
   on the next line keeps its 50% — that is a dot, not a corner. */
html.th-on .quick a{border:1px solid var(--line);border-radius:var(--th-btn);background:var(--sheet);color:var(--th-ink);font-weight:600;font-size:13px;display:inline-flex;align-items:center;gap:8px;text-decoration:none}
html.th-on .quick a::before{content:"";width:8px;height:8px;border-radius:50%;background:var(--cat,var(--acc));box-shadow:0 0 0 3px color-mix(in srgb,var(--cat,var(--acc)) 22%,transparent)}
html.th-on .quick a:hover,html.th-on .quick a.on{background:color-mix(in srgb,var(--cat,var(--acc)) 14%,var(--sheet));border-color:color-mix(in srgb,var(--cat,var(--acc)) 55%,transparent);color:var(--th-ink)}
html.th-on .tile{border:1px solid var(--line);transition:transform .16s ease,box-shadow .16s ease,border-color .16s ease}
html.th-on .tile .ic{border-radius:10px;background:var(--cat,var(--acc));color:#fff;box-shadow:0 6px 16px color-mix(in srgb,var(--cat,var(--acc)) 35%,transparent)}
html.th-on .tile:hover{border-color:color-mix(in srgb,var(--cat,var(--acc)) 50%,transparent);box-shadow:0 10px 26px color-mix(in srgb,var(--cat,var(--acc)) 18%,transparent)}
html.th-on .tile[data-cat="tech"] .ic,html.th-on .tile[data-cat="phones"] .ic,html.th-on .tile[data-cat="audio"] .ic,html.th-on .tile[data-cat="photo"] .ic,html.th-on .tile[data-cat="games"] .ic,html.th-on .tile[data-cat="property"] .ic,html.th-on .tile[data-cat="business"] .ic,html.th-on .tile[data-cat="office"] .ic,html.th-on .tile[data-cat="marine"] .ic,html.th-on .tile[data-cat="sports"] .ic,html.th-on .tile[data-cat="hobbies"] .ic{color:#123955}
html.th-on .tile .nm{font-weight:590;color:var(--th-ink)}
html.th-on .tile .ct{color:var(--th-mut);font-size:12px}
html.th-on .landing h2{color:var(--th-ink)}
html.th-on .landing p.s{color:var(--th-mut)}
html.th-on .seeall{background:var(--sheet);border:1px solid var(--th-line2);border-radius:var(--th-rsm);color:var(--th-ink2);font-weight:600}
html.th-on .seeall:hover{background:var(--well);border-color:var(--th-ink2)}
/* the state of a listing: one hue each, white label, the same four everywhere a listing is shown */
html.th-on .ph .bdg{border-radius:var(--th-rsm,10px);background:var(--g-green);color:#fff;font:590 12px/1 var(--sans);letter-spacing:.06em;text-transform:uppercase}
html.th-on .ph .bdg.auc{background:var(--g-fire)}
html.th-on .ph .bdg.urg{background:var(--g-red)}
html.th-on .ph .bdg.swp{background:var(--g-violet)}
html.th-on .ph{background:var(--well2);color:var(--th-mut)}
html.th-on .ph .cnt{background:var(--scrim);color:#fff;border-radius:999px;font-size:12px;font-weight:600}
html.th-on .card .pr{color:var(--th-ink);font-weight:590}
html.th-on .card .pl{color:var(--th-mut);font-size:12px}
html.th-on .card .ti{color:var(--th-ink)}
html.th-on .card .attrs{color:var(--th-mut);font-size:12px}
html.th-on .vf{color:var(--g-green);font-weight:600;font-size:12px}
html.th-on[data-theme="light"] .vf,html.th-on:not([data-theme="dark"]) .vf{color:color-mix(in srgb,var(--g-green) 72%,var(--th-ink))}
html.th-on .biz{background:var(--well2);color:var(--th-ink2);border-radius:4px;font-size:12px;font-weight:600}
html.th-on .rem{color:var(--th-mut);font-size:12px}
html.th-on .rem.urg{color:var(--g-red);font-weight:590}
/* promotion is gold, on every surface: the chip, the zone, the key tile, the ribbon */
html.th-on .adchip{background:var(--g-gold);color:var(--g-chip-ink);border-radius:var(--th-pill,9999px);font:590 12px/1 var(--sans);letter-spacing:.08em;text-transform:uppercase}
html.th-on .pz{background:color-mix(in srgb,var(--g-gold) 9%,var(--sheet));border:1px solid color-mix(in srgb,var(--g-gold) 45%,transparent);border-radius:var(--th-r)}
html.th-on .pzh{color:var(--th-ink);font-weight:590}
html.th-on .pzh::before{content:"";width:10px;height:10px;border-radius:50%;background:var(--g-gold);box-shadow:0 0 0 3px color-mix(in srgb,var(--g-gold) 25%,transparent)}
html.th-on .keytile{background:var(--sheet);border:1px solid color-mix(in srgb,var(--g-gold) 45%,transparent);border-radius:var(--th-r)}
html.th-on .card.t-ribbon::before{background:var(--g-fire);color:#fff;font:590 12px/1 var(--sans);letter-spacing:.06em;text-transform:uppercase}
/* the glass bar (7 Sep 2026): the second treatment finally painted — a translucent gold bar at the card's foot, the word on it in ink */
html.th-on .card.t-bar::after{background:color-mix(in srgb,var(--g-gold) 26%,var(--sheet));-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border-top:1px solid color-mix(in srgb,var(--g-gold) 45%,transparent);color:var(--th-ink);font:590 12px/1 var(--sans);letter-spacing:.06em;text-transform:uppercase}
/* the trust strip: three glyphs, three meanings, three colours; the words stay ink */
html.th-on .trustbar{background:var(--sheet);border-bottom:1px solid var(--line);color:var(--th-ink2);font-size:13px}
html.th-on .trustbar span:nth-child(1) svg{color:var(--g-green)}
html.th-on .trustbar span:nth-child(2) svg{color:var(--g-gold)}
html.th-on .trustbar span:nth-child(3) svg{color:var(--g-storm)}
html.th-on .trustbar svg{width:16px;height:16px}
/* the front door: search and sell carry the pillar's teal running into Cyan Sky; a brand line under the header */
html.th-on #th-header .searchbox .go,html.th-on #th-header .btn-sell{background:var(--acc);color:var(--acc-on);border:0;font-weight:590}
html.th-on #th-header .searchbox .go:hover,html.th-on #th-header .btn-sell:hover{filter:brightness(1.06)}
html.th-on #th-header header.top{border-bottom:2px solid transparent;border-image:linear-gradient(90deg,var(--house),var(--g-cyan)) 1}   /* the one front-door band: the house teal running to Cyan Sky, the mark's own direction */
html.th-on .nav .right a{color:var(--th-ink2);font-weight:600}
html.th-on .nav .right a:hover{color:var(--acc-t)}

/* two readings the colour census returned on 4 Sep 2026: table headers in the muted ink on the 4% navy well read 4.4:1,
   and the fail banner's muted line read 4.0:1 on its rose wash. One step darker each, everywhere. */
html.th-on th,html.th-on .thtf-h{color:var(--th-ink2)}
html.th-on .t-fail .t-mut,html.th-on .t-fail{color:var(--c-risk)}

/* ── 4i · THE DOOR HUES — one hue per main-menu door, the same meaning on every page ──────────────────────────────
   Sean, 4 Sep 2026: "the default face is vibrant", "I want to see what you showed me on my whole website", "consistency
   over all three pillars, and colour balance"; the research (research-pillars-colour.md): ~90% neutral canvas, colour on
   meaning, never on buttons. Each door owns one hue from the colour-vision-safe set (red is reserved for time running
   out; Mission Control stays ink). th-shell.js writes the current door on <html data-door>; this sheet paints it on the
   current row of the rail, the crumb chip, the numbers and the tile icon wells of that door's pages. Every door's glyph
   carries its hue always only when html[data-door-all] is set (his "stronger" option). */
html{--door:var(--acc);--door-ink:var(--th-ink)}   /* no door → the ink; the numbers rule in §2 reads --door-ink */
html[data-door="today"]{--door:var(--house);--door-ink:var(--house)}
html[data-door="jobs"]{--door:var(--g-fire);--door-ink:color-mix(in srgb,var(--g-fire) 59%,var(--th-ink))}
html[data-door="paperwork"]{--door:var(--g-ice);--door-ink:color-mix(in srgb,var(--g-ice) 42%,var(--th-ink))}
html[data-door="money"]{--door:var(--g-aurora);--door-ink:color-mix(in srgb,var(--g-aurora) 44%,var(--th-ink))}
html[data-door="people"]{--door:var(--g-pink);--door-ink:color-mix(in srgb,var(--g-pink) 73%,var(--th-ink))}
html[data-door="site"]{--door:var(--g-storm);--door-ink:color-mix(in srgb,var(--g-storm) 82%,var(--th-ink))}
html[data-door="compliance"]{--door:var(--g-cyan);--door-ink:color-mix(in srgb,var(--g-cyan) 57%,var(--th-ink))}
html[data-door="plant-assets"]{--door:var(--g-gold);--door-ink:color-mix(in srgb,var(--g-gold) 45%,var(--th-ink))}
html[data-door="geobidder"]{--door:var(--house);--door-ink:var(--house)}
html[data-door="command-centre"]{--door:var(--th-ink);--door-ink:var(--th-ink)}
html.th-on[data-theme="dark"]{--door-ink:color-mix(in srgb,var(--door) 72%,#FFFFFF)}   /* the hue lifted towards white until it reads at 4.6:1 on the night (storm was 3.7:1 raw) */
html.th-on[data-mode="sun"]{--door-ink:var(--th-ink)}
html.th-on #thGnav .gi[aria-current]{background:color-mix(in srgb,var(--door) 14%,var(--sheet));color:var(--door-ink)}
html.th-on #thGnav .gi[aria-current] svg{color:var(--door)}
/* the door's own row in the rail, whether or not the page is that door's home */
html.th-on[data-door="today"] #thGnav .gi[data-k="today"]{background:color-mix(in srgb,var(--door) 14%,var(--sheet));color:var(--door-ink)}
html.th-on[data-door="today"] #thGnav .gi[data-k="today"] svg{color:var(--door)}
html.th-on[data-door="jobs"] #thGnav .gi[data-k="jobs"]{background:color-mix(in srgb,var(--door) 14%,var(--sheet));color:var(--door-ink)}
html.th-on[data-door="jobs"] #thGnav .gi[data-k="jobs"] svg{color:var(--door)}
html.th-on[data-door="paperwork"] #thGnav .gi[data-k="paperwork"]{background:color-mix(in srgb,var(--door) 14%,var(--sheet));color:var(--door-ink)}
html.th-on[data-door="paperwork"] #thGnav .gi[data-k="paperwork"] svg{color:var(--door)}
html.th-on[data-door="money"] #thGnav .gi[data-k="money"]{background:color-mix(in srgb,var(--door) 14%,var(--sheet));color:var(--door-ink)}
html.th-on[data-door="money"] #thGnav .gi[data-k="money"] svg{color:var(--door)}
html.th-on[data-door="people"] #thGnav .gi[data-k="people"]{background:color-mix(in srgb,var(--door) 14%,var(--sheet));color:var(--door-ink)}
html.th-on[data-door="people"] #thGnav .gi[data-k="people"] svg{color:var(--door)}
html.th-on[data-door="site"] #thGnav .gi[data-k="site"]{background:color-mix(in srgb,var(--door) 14%,var(--sheet));color:var(--door-ink)}
html.th-on[data-door="site"] #thGnav .gi[data-k="site"] svg{color:var(--door)}
html.th-on[data-door="compliance"] #thGnav .gi[data-k="compliance"]{background:color-mix(in srgb,var(--door) 14%,var(--sheet));color:var(--door-ink)}
html.th-on[data-door="compliance"] #thGnav .gi[data-k="compliance"] svg{color:var(--door)}
html.th-on[data-door="plant-assets"] #thGnav .gi[data-k="plant-assets"]{background:color-mix(in srgb,var(--door) 14%,var(--sheet));color:var(--door-ink)}
html.th-on[data-door="plant-assets"] #thGnav .gi[data-k="plant-assets"] svg{color:var(--door)}
html.th-on[data-door="geobidder"] #thGnav .gi[data-k="geobidder"]{background:color-mix(in srgb,var(--door) 14%,var(--sheet));color:var(--door-ink)}
html.th-on[data-door="geobidder"] #thGnav .gi[data-k="geobidder"] svg{color:var(--door)}
html.th-on[data-door="command-centre"] #thGnav .gi[data-k="command-centre"]{background:color-mix(in srgb,var(--door) 14%,var(--sheet));color:var(--door-ink)}
html.th-on[data-door="command-centre"] #thGnav .gi[data-k="command-centre"] svg{color:var(--door)}
html[data-door-all] #thGnav .gi[data-k="today"] svg{color:var(--house)}
html[data-door-all] #thGnav .gi[data-k="jobs"] svg{color:var(--g-fire)}
html[data-door-all] #thGnav .gi[data-k="paperwork"] svg{color:color-mix(in srgb,var(--g-ice) 60%,var(--th-ink))}
html[data-door-all] #thGnav .gi[data-k="money"] svg{color:color-mix(in srgb,var(--g-aurora) 70%,var(--th-ink))}
html[data-door-all] #thGnav .gi[data-k="people"] svg{color:var(--g-pink)}
html[data-door-all] #thGnav .gi[data-k="site"] svg{color:var(--g-storm)}
html[data-door-all] #thGnav .gi[data-k="compliance"] svg{color:var(--g-cyan)}
html[data-door-all] #thGnav .gi[data-k="plant-assets"] svg{color:color-mix(in srgb,var(--g-gold) 70%,var(--th-ink))}
html[data-door-all] #thGnav .gi[data-k="geobidder"] svg{color:var(--house)}
html.th-on #thTop .bk{border-color:color-mix(in srgb,var(--door) 45%,transparent);color:var(--door-ink)}
html.th-on .pcard .ic,html.th-on .tool .ic,html.th-on .card h2>.ic{background:color-mix(in srgb,var(--door) 16%,var(--sheet));color:var(--door-ink);border-radius:10px}
html.th-on .card h2>svg,html.th-on .card h2>.ic svg,html.th-on .panel h2>svg,html.th-on .pv h2>svg{color:var(--door-ink)}
html.th-on .eyebrow,html.th-on .card .eyebrow{color:var(--door-ink)}

/* ── 4h · THE TWO CUTS OF EVERY WORDMARK — ink on the day, white on the night, ink again in the sun. Last in the sheet on
   purpose: it must beat the pillar rule that makes every mark display:block (4 Sep 2026: both cuts showed at once). */
html.th-on img.wm-rev,html.th-on .pillars img.wm-rev{display:none}
html.th-on[data-theme="dark"] img.wm-ink,html.th-on[data-theme="dark"] .pillars img.wm-ink{display:none}
html.th-on[data-theme="dark"] img.wm-rev,html.th-on[data-theme="dark"] .pillars img.wm-rev{display:block}
html.th-on[data-mode="sun"] img.wm-ink,html.th-on[data-mode="sun"] .pillars img.wm-ink{display:block}
html.th-on[data-mode="sun"] img.wm-rev,html.th-on[data-mode="sun"] .pillars img.wm-rev{display:none}

/* ── 4j · THE DEPTH — 5 Sep 2026 ──────────────────────────────────────────────────────────────────
   Sean, on the shell sample: "still need to add more attention to the whole design, looks still flat",
   and then: "this now to new them law, and is to look the same site wide and owner side, full scale
   and consistent, do not stop do not rush, do with precision, as a delicate operation."

   MEASURED FIRST. The sheet had no elevation system at all — eleven one-off box-shadows in 657 lines,
   and the single rule that paints every surface on the estate
       html.th-on .card,.panel,.w,.pv,.box,.tile{background:var(--sheet);border:1px solid var(--line)}
   gave a card the same weight as the page behind it. .card is on 90 pages, .k on 30, .stat on 16.
   That flatness is not a taste; it is an absence.

   WHAT THIS DOES AND DOES NOT DO
   · It adds an elevation SCALE as tokens, so depth is a system and not a sprinkle of shadows.
   · It does NOT change the ground. "Light blue is out" was ruled twice and LIGHT-GROUND is still
     Sean's open decision, so --bed and --sheet are untouched. Depth here is light and edge, not a
     new background colour.
   · It does NOT add colour. §4i already puts the door's hue on the row you stand in and nowhere
     else, which is the quiet he asked for after the first sample read as "slight over kill".
   · Gold is spent three times only: standing, the company, and money.

   THE SHADOW IS THE BRAND'S INK, NOT BLACK. --shadow-c is 18,57,85 (Poseidon), so a lifted card
   casts a shadow the same family as the type above it. Black on a warm sheet reads as dirt.

   TWO SHADOWS PER STEP, NOT ONE. A single blur reads as a sticker. Every step is a tight contact
   shadow (the object meeting the page) plus a wide ambient one (the room), with a top inner
   highlight in light mode only — at night there is no light above to catch an edge. */
html.th-on{
  --lift-1:0 1px 0 rgba(255,255,255,.95) inset, 0 1px 2px rgba(var(--shadow-c),.05), 0 14px 28px -22px rgba(var(--shadow-c),.55);
  --lift-2:0 1px 0 rgba(255,255,255,.95) inset, 0 2px 4px rgba(var(--shadow-c),.06), 0 24px 44px -30px rgba(var(--shadow-c),.62);
  --lift-3:0 1px 0 rgba(255,255,255,.9) inset,  0 4px 8px rgba(var(--shadow-c),.08), 0 40px 70px -34px rgba(var(--shadow-c),.7);
  --lift-hover:0 1px 0 rgba(255,255,255,.95) inset, 0 2px 4px rgba(var(--shadow-c),.07), 0 22px 40px -26px rgba(var(--shadow-c),.62);
  /* the hairline that separates a lifted thing from the page — warmer than --line, so an edge in
     light reads as an edge and not as a drawn rule */
  --edge:color-mix(in srgb,var(--line) 82%, rgba(var(--shadow-c),.10));
  /* THE METAL'S TWO INKS, TAKEN FROM LAW 77 AND NOT INVENTED. The law sets the range: light uses
     #9C7E41 through #B4914B, dark uses #D4C098 through #EAE1CE, because bronze is weak in daylight
     and beautiful at night (measured 25 Aug 2026: #D4C098 is 1.68:1 on the light canvas and 8.63:1
     on the Poseidon ground). The first cut of this section used four golds of my own; the look gate
     stopped the push, which is the gate working. --gold-ink is the word, --gold-glyph is the mark. */
  --gold-ink:#9C7E41; --gold-glyph:#B4914B;
}
/* DARK — no white highlight (there is no light above), and the ambient goes to true black, because
   a Poseidon shadow on a Poseidon room is invisible. Law 77's logic, applied to depth. */
html.th-on[data-theme="dark"]{
  --lift-1:0 1px 2px rgba(0,0,0,.30), 0 16px 30px -22px rgba(0,0,0,.75);
  --lift-2:0 2px 6px rgba(0,0,0,.38), 0 26px 48px -30px rgba(0,0,0,.85);
  --lift-3:0 6px 12px rgba(0,0,0,.45), 0 44px 74px -34px rgba(0,0,0,.9);
  --lift-hover:0 2px 6px rgba(0,0,0,.40), 0 24px 44px -26px rgba(0,0,0,.8);
  --edge:color-mix(in srgb,var(--line) 70%, rgba(255,255,255,.06));
  --gold-ink:#EAE1CE; --gold-glyph:#D4C098;
}
/* SUNLIGHT — depth is invisible at 100,000 lux and a shadow only muddies the edge. In the fourth
   switch the lift comes off and the border does the work, which is what Law 80 asks of this mode. */
html.th-on[data-mode="sun"]{ --lift-1:none; --lift-2:none; --lift-3:none; --lift-hover:none; --edge:var(--th-ink); }

/* THE RESTING SURFACES. Same selector list the sheet already paints, so nothing new is invented and
   no page needs an edit — the one lever, per Law 100. */
html.th-on .card,html.th-on .panel,html.th-on .w,html.th-on .pv,html.th-on .box,html.th-on .tile{
  box-shadow:var(--lift-1); border-color:var(--edge);
}
/* a card you can act on lifts on hover and settles on press — the only motion in this section */
html.th-on a.card:hover,html.th-on button.card:hover,html.th-on .card.is-link:hover,
html.th-on .tile:hover,html.th-on a.tile:hover{ box-shadow:var(--lift-hover); }
html.th-on a.card:active,html.th-on button.card:active,html.th-on .tile:active{ box-shadow:var(--lift-1); }
html.th-on .card,html.th-on .tile{ transition:box-shadow .16s ease, border-color .16s ease; }
@media (prefers-reduced-motion:reduce){ html.th-on .card,html.th-on .tile{transition:none} }

/* THINGS THAT FLOAT ABOVE THE PAGE take the higher steps. These class names already exist in the
   shell and the pages; naming them here gives them the same physics as everything else. */
html.th-on .menu,html.th-on .dropdown,html.th-on .pop,html.th-on .popover,html.th-on #thUserMenu,
html.th-on .sheet-pop,html.th-on .tt{ box-shadow:var(--lift-2); border-color:var(--edge); }
html.th-on .modal,html.th-on dialog,html.th-on .drawer,html.th-on .th-modal{ box-shadow:var(--lift-3); border-color:var(--edge); }

/* WHAT THE PAGES FLOAT, PAINTED BY ROLE. _rebuild.py (Law 100) moved every page to geometry and this
   sheet paints everything — but these overlays were page-local class names nothing here named, so on
   5 Sep 2026 the marketplace's category menu, its search suggestions and its dialogs drew their text
   straight over the page (Sean: "messed up"). Three roles: a scrim, a floating sheet, a bar. A new
   page-local overlay carries one of these class names or it is not painted — _rebuild.py --check now
   refuses an unpainted one. */
html.th-on .megascrim,html.th-on .gb-scrim,html.th-on .dlg .scrim,html.th-on .cf .scrim,
html.th-on #builder,html.th-on #hire{ background:var(--scrim); }
html.th-on .drawer,html.th-on .flyout,html.th-on .sugg,html.th-on .side.open,html.th-on .dlg .sheet,
html.th-on .cf .sheet,html.th-on .kmenu,html.th-on #builder .bx,html.th-on #hire .bx,html.th-on .ss-toast,
html.th-on .thb-bar,html.th-on #thInstall{ background:var(--sheet); color:var(--th-ink); border:1px solid var(--edge); box-shadow:var(--lift-3); }
html.th-on .flyout,html.th-on .sugg,html.th-on .dlg .sheet,html.th-on .cf .sheet,html.th-on .kmenu,
html.th-on #builder .bx,html.th-on #hire .bx,html.th-on .ss-toast,html.th-on .thb-bar,html.th-on #thInstall{ border-radius:var(--th-r); }
html.th-on .drawer{ border-width:0 1px 0 0; }
html.th-on .drawer .dhd{ border-bottom:1px solid var(--line); }
html.th-on .flyout{ border-radius:0 0 var(--th-r) 0; }
html.th-on .sheet-foot,html.th-on .mobcta{ background:var(--sheet); color:var(--th-ink); border-top:1px solid var(--edge); box-shadow:0 -8px 24px -16px rgba(var(--shadow-c),.45); }
html.th-on .modal:has(> .sheet){ background:var(--scrim); box-shadow:none; border:0; }
html.th-on dialog{ background:var(--sheet); color:var(--th-ink); border:1px solid var(--edge); border-radius:var(--th-r); }
html.th-on dialog::backdrop{ background:var(--scrim); }
/* PAUSED UNTIL PAID (mig1056): the standing line the shell paints at the top of a page in grace or held. Gold, because
   it is money (Law 83); the word carries the state (Law 79), the button is the way out. */
html.th-on .th-hold{ display:flex; gap:12px; align-items:center; flex-wrap:wrap; margin:0 0 16px; padding:10px 14px; background:var(--gold2, #EAE1CE); color:var(--th-ink); border:1px solid var(--gold, #B4914B); border-radius:var(--th-r); }
html.th-on .th-hold .th-hold-w{ font-weight:590; letter-spacing:.02em; }
html.th-on .th-hold .th-hold-t{ flex:1; min-width:240px; font-size:14px; }
html.th-on .th-hold.is-held{ border-width:2px; }
html.th-on[data-hold="read_only"] main form :is(input,select,textarea,button):disabled{ opacity:.55; cursor:not-allowed; }
html.th-on .modal > .sheet,html.th-on .basetoggle,html.th-on .legend{ background:var(--sheet); color:var(--th-ink); border:1px solid var(--edge); border-radius:var(--th-r); box-shadow:var(--lift-3); }

/* THE BAR AND THE RAILS get a floor, not a shadow box: one hairline of light on top and a short
   ambient below, so the page slides under them instead of butting against them. */
html.th-on #thTop{ box-shadow:0 1px 0 rgba(255,255,255,.9) inset, 0 8px 20px -16px rgba(var(--shadow-c),.42); }
html.th-on[data-theme="dark"] #thTop{ box-shadow:0 10px 22px -18px rgba(0,0,0,.85); }
html.th-on[data-mode="sun"] #thTop{ box-shadow:none; }
html.th-on #thGnav{ box-shadow:10px 0 26px -24px rgba(var(--shadow-c),.5); }
html.th-on #thSide{ box-shadow:10px 0 26px -26px rgba(var(--shadow-c),.45); }
html.th-on[data-theme="dark"] #thGnav{ box-shadow:12px 0 30px -24px rgba(0,0,0,.9); }
html.th-on[data-theme="dark"] #thSide{ box-shadow:12px 0 30px -26px rgba(0,0,0,.85); }
html.th-on[data-mode="sun"] #thGnav,html.th-on[data-mode="sun"] #thSide{ box-shadow:none; }

/* GOLD, SPENT THREE TIMES. Law 77: the metal inverts in the dark — lighter at night, never darker.
   1 · STANDING — the level chip in the bar, which is the member's own rank. */
/* IN DAYLIGHT THE METAL IS LINE AND MARK, NOT THE WORD. Measured: Law 77's light metal #9C7E41 on
   the chip's own gold tint is 3.64:1 — fine for a mark (SC 1.4.11 asks 3), short of the 4.5 a word
   needs. So in light the word takes the ink and the metal holds the edge and the star; at night the
   metal is the word, where the law says it is beautiful and where it measures 8.44:1. This is Law 77
   obeyed, not worked around: the value is the law's, the job it does changes with the ground. */
html.th-on .lvlchip,html.th-on .pill.lvl,html.th-on .th-level-chip{
  border-color:color-mix(in srgb,var(--g-gold) 52%,transparent);
  background:linear-gradient(180deg,color-mix(in srgb,var(--g-gold) 15%,var(--sheet)),color-mix(in srgb,var(--g-gold) 7%,var(--sheet)));
  color:var(--th-ink); font-weight:600;
}
html.th-on .lvlchip .st,html.th-on .pill.lvl .st,html.th-on .th-level-chip .st{ color:var(--gold-glyph); }
html.th-on[data-theme="dark"] .lvlchip,html.th-on[data-theme="dark"] .pill.lvl,html.th-on[data-theme="dark"] .th-level-chip{
  background:linear-gradient(180deg,color-mix(in srgb,var(--g-gold) 22%,var(--sheet)),color-mix(in srgb,var(--g-gold) 10%,var(--sheet)));
  color:var(--gold-ink);
}
/* 2 · THE COMPANY — Mission Control is the owner's own door, and it is the only row on the rail
   that is not a stage of the work. It reads as the company, in the company's metal. */
html.th-on #thGnav .thIntBlock .gi[data-k="command-centre"]{
  background:linear-gradient(180deg,color-mix(in srgb,var(--g-gold) 14%,var(--sheet)),color-mix(in srgb,var(--g-gold) 6%,var(--sheet)));
  border:1px solid color-mix(in srgb,var(--g-gold) 40%,transparent);
  color:var(--th-ink); font-weight:600;
}
html.th-on #thGnav .thIntBlock .gi[data-k="command-centre"] svg{ color:var(--gold-glyph); }
html.th-on[data-theme="dark"] #thGnav .thIntBlock .gi[data-k="command-centre"]{
  background:linear-gradient(180deg,color-mix(in srgb,var(--g-gold) 20%,var(--sheet)),color-mix(in srgb,var(--g-gold) 9%,var(--sheet)));
  border-color:color-mix(in srgb,var(--g-gold) 46%,transparent); color:var(--gold-ink);
}
html.th-on[data-theme="dark"] #thGnav .thIntBlock .gi[data-k="command-centre"] svg{ color:var(--gold-glyph); }
html.th-on[data-mode="sun"] #thGnav .thIntBlock .gi[data-k="command-centre"]{
  background:var(--sheet); border-color:var(--th-ink); color:var(--th-ink);
}
/* 3 · MONEY keeps the metal it already had in §4d/D24; nothing is repainted here. Gold is not
   spent a fourth time — a colour that means three things means none of them. */

/* THE DUOTONE ICON'S SECOND TONE. th-iconset.js ships every d-* glyph with its back plate at
   opacity 0.6 — a measurement, not a taste: Phosphor's own 0.2 composites to 1.44:1 on our ink and
   fails WCAG 2.2 SC 1.4.11's 3:1 for an icon that carries meaning; 0.6 clears it at 3.24:1. The
   plate inherits currentColor, so an icon in a door's hue is two tones of that one hue and never a
   second colour smuggled in. Nothing to declare here but the rule that it must not be overridden. */
html.th-on svg use{ pointer-events:none; }

/* PRINT — paper has no elevation. Every lift comes off so a printed page is line work. */
@media print{
  html.th-on .card,html.th-on .panel,html.th-on .w,html.th-on .pv,html.th-on .box,html.th-on .tile,
  html.th-on #thTop,html.th-on #thGnav,html.th-on #thSide{ box-shadow:none!important; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   §M-2 · THE MATERIALS, WIRED — LAW 108, 8 September 2026
   ───────────────────────────────────────────────────────────────────────────
   §M in cd-signature declares WHAT each material is. This section is the only
   place that says WHICH ELEMENT WEARS IT. Nothing below holds a colour: every
   value is a var() into §M, which is a var() into §P. Change a purpose and it
   reaches here without anyone editing this file.

   Appended as a section by order, the same way the 2026 furniture was — nothing
   above is rewritten, so this can be lifted out again in one piece.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── THE INSTRUMENT. `.meter` was used fourteen times across the platform and
      had NO CSS AT ALL — every one of them was an unstyled div relying on an
      inline width. A meter that only moves is decoration (Law 83); this one
      carries the ramp, so its colour says which purpose is advancing. ── */
html.th-on .meter{height:10px;border-radius:var(--th-pill,9999px);background:var(--meter-track);
  overflow:hidden;box-shadow:var(--meter-inset)}
html.th-on .meter>i{display:block;height:100%;border-radius:inherit;
  background:var(--meter-cool);box-shadow:var(--meter-glow-cool);
  transition:width .9s var(--ease,cubic-bezier(.2,.7,.2,1))}
html.th-on .meter.flow>i{background:var(--meter-flow);box-shadow:var(--meter-glow-flow)}
html.th-on .meter.fire>i{background:var(--meter-fire);box-shadow:var(--meter-glow-fire)}
html.th-on .meter.gold>i{background:var(--meter-gold);box-shadow:var(--meter-glow-gold)}
html.th-on .meter.soc>i {background:var(--meter-soc)}
html.th-on .meter.vio>i {background:var(--meter-vio)}
html.th-on .meter.sm{height:6px}

/* ── GLOW. ONLY live things. If it pulses, it is happening now — a running
      clock, an open gate, a bid still moving. Never decoration. ── */
html.th-on .beacon{position:relative;display:inline-block;width:9px;height:9px;border-radius:50%;
  flex:none;color:var(--p-reward-1);background:currentColor;box-shadow:var(--beacon-live)}
html.th-on .beacon.hot{color:var(--p-growth-3);box-shadow:var(--beacon-hot)}
html.th-on .beacon.red{color:var(--p-emerg-1);box-shadow:var(--beacon-red)}
html.th-on .beacon::after{content:'';position:absolute;inset:-6px;border-radius:50%;
  border:1px solid currentColor;opacity:.35;animation:thPing 2.6s cubic-bezier(.22,.61,.36,1) infinite}
@keyframes thPing{0%{transform:scale(.6);opacity:.55}70%{transform:scale(1.55);opacity:0}100%{opacity:0}}

/* ── CRYSTAL. ONE per screen, on the thing the record is asking of you. The
      prism lives on the BORDER: the fill must stay near-opaque or the conic
      shows through and the whole card goes rainbow (found by rendering it). ── */
html.th-on .crystal{position:relative;border:1.5px solid transparent;border-radius:var(--th-r);
  background:linear-gradient(var(--crystal-fill),var(--crystal-fill)) padding-box,
             var(--crystal-edge) border-box;
  -webkit-backdrop-filter:var(--glass-blur);backdrop-filter:var(--glass-blur);
  box-shadow:var(--lift-2),var(--glass-lit),var(--crystal-halo)}
html.th-on .crystal::before{content:'';position:absolute;inset:0;border-radius:inherit;
  pointer-events:none;background:var(--crystal-sheen)}
html.th-on .crystal>*{position:relative;z-index:1}

/* ── GOLD as a surface. Metal, a lit edge and a sheen crossing it. The LETTERS
      GO DARK — #9C7E41 as text is 3.84:1 and Law 73 forbids darkening the metal
      to fix that, so the gold stays in the ground and the edge (Law 107). ── */
html.th-on .gold-surface{position:relative;overflow:hidden;border-radius:var(--th-r);
  background:var(--gold-surface);border:1px solid var(--gold-edge);color:var(--gold-letters);
  -webkit-backdrop-filter:var(--glass-blur);backdrop-filter:var(--glass-blur);
  box-shadow:var(--lift-2),inset 0 1px 0 rgba(255,255,255,.75),var(--gold-halo)}
html.th-on .gold-surface::after{content:'';position:absolute;top:0;left:-60%;width:44%;height:100%;
  pointer-events:none;background:var(--gold-sheen);animation:thSheen 6.5s cubic-bezier(.22,.61,.36,1) infinite}
@keyframes thSheen{0%{left:-60%}42%{left:130%}100%{left:130%}}
html.th-on .gold-surface>*{position:relative;z-index:1}
/* the gold MARK — a hairline and small caps, never a filled pill, so it can sit
   beside a red warning and never be read as one (Law 107) */
html.th-on .au{display:inline-flex;align-items:center;gap:6px;height:25px;padding:0 11px;
  border-radius:var(--th-pill,9999px);border:1px solid var(--gold-edge);color:var(--gold-letters);
  background:var(--gold-surface);font:590 12px var(--sans);letter-spacing:.12em;
  text-transform:uppercase;white-space:nowrap;box-shadow:inset 0 1px 0 rgba(255,255,255,.7)}
html.th-on .au svg{width:11px;height:11px;flex:none}

/* ── FLAME. Growth, and ALWAYS a whole surface — never a small mark, because a
      small warm mark is a warning and this is the opposite of one. ── */
html.th-on .flame{position:relative;overflow:hidden;border-radius:var(--th-r);
  background:var(--flame-surface);color:var(--flame-ink);border:1px solid rgba(255,255,255,.18);
  box-shadow:var(--lift-2),var(--flame-halo),inset 0 1px 0 rgba(255,255,255,.22)}
html.th-on .flame::before{content:'';position:absolute;inset:-30% -10% auto -10%;height:150%;
  pointer-events:none;
  background:var(--flame-flicker);
  animation:thFlicker 5.5s cubic-bezier(.22,.61,.36,1) infinite alternate}
@keyframes thFlicker{0%{transform:translateY(5px) scale(1)}100%{transform:translateY(-7px) scale(1.07)}}
html.th-on .flame>*{position:relative;z-index:1}
html.th-on .flame h2,html.th-on .flame h3,html.th-on .flame b{color:#fff}
/* the streak — twelve days, and the lit ones are the reward */
html.th-on .streak{display:flex;gap:5px;align-items:flex-end;height:40px}
html.th-on .streak i{flex:1;border-radius:4px;background:rgba(255,255,255,.20)}
html.th-on .streak i.on{background:var(--streak-lit);box-shadow:var(--streak-glow)}

/* ── THE RING. A gradient stroke needs a <defs> gradient in the page's own SVG;
      this styles the parts that are not the stroke, so a ring is consistent
      wherever one is drawn. ── */
html.th-on .ring{position:relative;flex:none}
html.th-on .ring svg{display:block;transform:rotate(-90deg)}
html.th-on .ring circle.tr{stroke:var(--meter-track);fill:none}
html.th-on .ring circle.va{stroke-linecap:round;fill:none;
  transition:stroke-dashoffset 1.2s cubic-bezier(.22,.61,.36,1)}
html.th-on .ring .t{position:absolute;inset:0;display:grid;place-content:center;text-align:center;gap:2px}

/* Nobody gets to move if the person asked for stillness. */
@media (prefers-reduced-motion:reduce){
  html.th-on .beacon::after,html.th-on .gold-surface::after,html.th-on .flame::before{animation:none}
  html.th-on .meter>i,html.th-on .ring circle.va{transition:none}
}

/* ═══════════════════════════════════════════════════════════════════════════
   §H · THE HERO SPEAKS FIRST — 8 September 2026
   ───────────────────────────────────────────────────────────────────────────
   THE DEFECT. `html.th-on h1` above sets 28px/36px — correct for an app screen,
   and it is (0,1,2), so it beats every page's own `.hero h1` at (0,1,1). Fifteen
   public pages carry a hero; FOURTEEN of them were rendering their headline at
   the app size, and index.html's own `clamp(40px,6.2vw,72px)` was being thrown
   away and then capped at 15ch — a 273px column of 28px type in a 1160px band.
   Measured in the browser, not read from the source: that is the "flat" on the
   main pages, and no gate can see it because both rules are valid CSS.

   THE RULE. A hero is not a screen heading. One size for every hero on the
   platform, at a specificity that clears the app rule, so a page never has to
   fight the system to be read from across the room. Sizes are geometry, not
   colour — nothing here holds a hue, and the ink still comes from the band.
   ═══════════════════════════════════════════════════════════════════════════ */
html.th-on .hero h1{font:700 clamp(38px,5.6vw,68px)/1.05 var(--disp);
  letter-spacing:-.022em;text-wrap:balance}
html.th-on .hero h1 em{font-style:normal}
/* the lead under it carries the same step up, and stops at a readable measure */
html.th-on .hero .lead,html.th-on .hero p.lead{font-size:clamp(16px,1.3vw,19px);
  line-height:1.55;max-width:52ch}
@media(max-width:560px){html.th-on .hero h1{letter-spacing:-.015em}}

/* ── AND THE LINE BOX MUST FOLLOW THE TYPE. The h1/h2 rules above use the `font:`
      shorthand, which pins a line-height in PIXELS. A page that overrides only
      the font-size — 64 headings across 31 pages do exactly that, with
      an inline `font-size:clamp(24px,3.4vw,34px)` — keeps the 24px line box, so
      34px type overlaps itself on any heading that wraps. Seen on trust.html:
      a two-line h2 measured 48px tall for 68px of type.

      These two lines are the SAME numbers as above expressed as ratios
      (36/28 and 24/18), so nothing moves at the system's own sizes; they only
      start doing work the moment a page asks for a bigger heading. Card and
      panel headings keep their own line-height — those rules are more
      specific and are not touched. ── */
html.th-on h1{line-height:1.286}
html.th-on h2{line-height:1.333}

/* ═══════════════════════════════════════════════════════════════════════════
   §R · WHAT A PERSON ACTUALLY READS — 8 September 2026
   ───────────────────────────────────────────────────────────────────────────
   Sean, looking at the shipped pages: "it feels slightly wide to read the text
   from one side to the other side… if you agree on colouring the small tiles
   it needs to be glass, slightly transparent."

   THE MEASURE. `--max` is min(1680px,100%) in th-core under the FULL-WIDTH LAW,
   and that is right for a desk full of instruments — it is not a reading
   column. Counted on the rendered page at 1680px: body text ran 92 characters
   to the line and the hero pillar tiles 109. The readable band is 45–75. The
   container keeps every pixel it has; only running text is capped, so no
   layout moves.

   AND THE `ch` UNIT LIES ABOUT ITSELF. A first pass at 68ch still measured 92
   characters, because `ch` is the advance of "0" and in Instrument Sans that
   is narrower than the average letter. Every number below was set by counting
   the characters on a rendered line, never by trusting the unit.

   THE TILES. `.val` had NO surface at all — transparent, square, no border, no
   shadow, 24px of padding and nothing else: bare text on the field. It takes
   the same glass the hero pillars wear, plus a wash of its own purpose, so
   three ideas read as three things instead of one paragraph in three columns.
   Nothing here holds a colour — a tile names a §P purpose in `--pil` and this
   section mixes it. NO `--pil`, NO WASH: a card that has not been given a
   purpose renders exactly as it did before this section existed.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── 1 · THE MEASURE. 52ch measures ~69 characters; the body comes up to 16px
      at the same time, because 15px running text on a 1680px screen is the
      other half of "hard to read across". ── */
html.th-on .prose p,html.th-on .narrow p,html.th-on .pull,html.th-on .arcline{
  max-width:52ch;font-size:var(--fs-16);line-height:1.62}
html.th-on .pil p,html.th-on .val p,html.th-on .tile p,html.th-on .card p{max-width:60ch}

/* ── 2 · A TILE MAY CARRY ITS PURPOSE. The wash is 12% over the glass, so it
      is a tint ON translucent glass and never a coloured card. ── */
html.th-on .val,html.th-on [style*="--pil"].tile,html.th-on [style*="--pil"].card,
html.th-on [style*="--pil"].stat,html.th-on [style*="--pil"].kpi,html.th-on .stats>[style*="--pil"]{
  border-radius:var(--th-r);
  background:linear-gradient(135deg,color-mix(in oklab,var(--pil,transparent) 12%,transparent),transparent 62%),var(--glass);
  border:1px solid var(--glass-line);
  -webkit-backdrop-filter:var(--glass-blur);backdrop-filter:var(--glass-blur);
  box-shadow:var(--lift-1),var(--glass-lit)}
html.th-on [style*="--pil"] h3,html.th-on [style*="--pil"]>b{color:var(--pil-ink,var(--th-ink))}
html.th-on[data-theme="dark"] [style*="--pil"] h3,
html.th-on[data-theme="dark"] [style*="--pil"]>b,
html.th-on[data-ground="wash"]:not([data-theme="light"]) [style*="--pil"] h3,
html.th-on[data-ground="wash"]:not([data-theme="light"]) [style*="--pil"]>b{
  color:color-mix(in oklab,var(--pil,var(--p-live-2)) 82%,#fff)}

/* ── 3 · THE WHITE SLAB. `.k` is the KPI-CELL class above — furniture built to
      hold a big number — and about.html wraps four letters in it, so HIRE,
      CONNECT and WORK each rendered as a 477×66 white block. Inside a tile it
      is what it always was: the door's name, in the door's colour. Scoped to a
      tile so index.html's own seven `.k` cells are untouched. ── */
html.th-on .tile .k,html.th-on .card .k{
  display:inline-flex;align-items:center;width:auto;height:auto;
  padding:4px 10px;margin:0;border:0;border-radius:var(--th-pill,9999px);
  background:color-mix(in oklab,var(--pil,var(--th-ink)) 18%,transparent);
  color:var(--pil-ink,var(--th-ink));font:700 var(--fs-11)/1.6 var(--sans);
  letter-spacing:.14em;text-transform:uppercase;box-shadow:none}
/* 84% measured at 4.06 on HIRE and 4.45 on WORK — the chip has its OWN 18%
   wash under it, and that eats what the tile's 12% left. 11px bold uppercase
   is not large text, so 4.5 is the bar it has to clear, not 3. Lighter
   letters; the hue still says which door. Composited on canvas, which is the
   only way to read an oklab colour-mix over a gradient honestly. */
html.th-on[data-theme="dark"] .tile .k,html.th-on[data-theme="dark"] .card .k,
html.th-on[data-ground="wash"]:not([data-theme="light"]) .tile .k,
html.th-on[data-ground="wash"]:not([data-theme="light"]) .card .k{
  color:color-mix(in oklab,var(--pil,var(--p-live-2)) 42%,#fff)}

/* ── 4k · THE SEALED PHOTOGRAPH — th-capture.js's gallery, painted here (Law 100, 11 Sep 2026) ────────────────
   The shared module used to inject its own <style>; a module carrying paint is the drift Law 100 forbids, and it was
   painting with th-core's tokens on pages the system owns. Same geometry, the system's own tokens: --sheet for the
   tile, --well for the sunk image ground, --th-line2 for the focus ring, --th-r / --th-rsm for the corners. */
html.th-on .thcap-wrap{margin-top:10px}
html.th-on .thcap-grid{display:flex;flex-wrap:wrap;gap:10px;margin:0;padding:0;list-style:none}
html.th-on .thcap-tile{width:150px;border:1px solid var(--line);border-radius:var(--th-r);background:var(--sheet);overflow:hidden;display:flex;flex-direction:column}
html.th-on .thcap-tile img{display:block;width:100%;height:104px;object-fit:cover;background:var(--well)}
html.th-on .thcap-noshow{height:104px;display:flex;align-items:center;justify-content:center;text-align:center;padding:8px;background:var(--well);color:var(--th-mut);line-height:1.3}
html.th-on .thcap-meta{padding:7px 8px;color:var(--th-ink);line-height:1.35;flex:1}
html.th-on .thcap-seal{display:block;margin-top:4px;color:var(--th-mut);word-break:break-all}
html.th-on .thcap-check{display:block;width:100%;min-height:44px;border:0;border-top:1px solid var(--line);background:var(--sheet);color:var(--th-ink);cursor:pointer;padding:8px}
html.th-on .thcap-check:hover{background:var(--well)}
html.th-on .thcap-check:focus-visible{outline:2px solid var(--th-line2);outline-offset:-2px}
html.th-on .thcap-said{padding:6px 8px;line-height:1.35}
html.th-on .thcap-wd{border-top:1px solid var(--line);padding:7px 8px}
html.th-on .thcap-wd input{width:100%;min-height:44px;padding:6px 8px;border:1px solid var(--line);border-radius:var(--th-rsm);background:var(--sheet);color:var(--th-ink)}
html.th-on .thcap-wd button{min-height:44px;margin-top:6px;width:100%;border:1px solid var(--line);border-radius:var(--th-rsm);background:var(--sheet);color:var(--th-ink);cursor:pointer}
html.th-on .thcap-note{color:var(--th-mut);line-height:1.4;margin-top:6px}

/* ═══════════════════════════════════════════════════════════════════════════
   DENSITY — the treatment THEME10 names and nobody built. 12 September 2026.

   THE ITEM asks for ten treatments a member owns. FOURTEEN already work — light,
   dark, auto on the clock, system, Sunlight, text size, weight, line height,
   letter spacing, word spacing, focus ring, underlined links, solid-not-glass,
   square-not-rounded and motion off — every one with an engine, CSS in
   th-vision.css, markup in settings.html and wiring. Density and typeface are
   the two that were never built. This is density.

   WHAT IT MOVES, AND WHY ONLY THIS. Measured before writing a line:
     · --th-h is the control height and is used 11 times in th-system.css — every
       button, input, select and segmented track sits on it. It is the one honest
       lever, because it is what a person actually feels: how much of the screen
       a row of controls eats.
     · There is NO --sp- spacing scale on this platform. Spacing is literal, so a
       density switch CANNOT multiply it without touching hundreds of rules. It
       does not pretend to.
     · The type ramp is NOT touched. --vz-scale already owns size and a member who
       wants smaller text has a slider for it. A density control that also shrank
       type would fight that slider and make both unpredictable.

   THE TAP FLOOR ALREADY EXISTS AND THIS DEFERS TO IT. A first draft of this file
   invented its own `@media (pointer: coarse)` rule with a hard-coded 44px, and
   that was wrong twice over: cd-signature.css §1734 already raises every control
   to var(--tap-min) under `(hover: none) and (pointer: coarse)`, and --tap-min
   and --tap-field are declared at §1082. Writing a parallel rule with a literal
   would have put a second copy of the law in a second place, which is the exact
   failure Law 108 exists to stop. So compact simply does not survive that block:
   the existing floor overrides it on a finger, and this file re-states nothing.

   Three steps, and they say what they are on screen rather than implying more.
   ═══════════════════════════════════════════════════════════════════════════ */

/* The default, declared rather than implied, so the three read as one set. */
html.th-on[data-density="default"]{ --th-h:40px; --dens:1; }

/* Roomy — a big screen, or hands that want a bigger target. Above the tap floor
   on every device, so it needs no exception. */
html.th-on[data-density="roomy"]{ --th-h:46px; --dens:1.18; }

/* Compact — more rows on a desk with a mouse. Below --tap-min deliberately, and
   cd-signature.css §1734 raises it back on any coarse pointer without this file
   saying a word. The member keeps the choice; it stops applying where it would
   make the platform unusable, which is the same shape as Sunlight defeating the
   field blooms. */
html.th-on[data-density="compact"]{ --th-h:34px; --dens:.82; }

/* .cd-field is the gloves-on control and is 56px on every step. Work gloves cut
   effective touch precision to 20-25mm; a density preference is not a reason to
   make a control someone uses on a roof smaller. */
html.th-on[data-density] .cd-field{ height:var(--tap-field,56px); min-height:var(--tap-field,56px); }

/* The padding that hangs off the height, only on the surfaces that carry rows. */
html.th-on[data-density="roomy"]   .panel, html.th-on[data-density="roomy"]   .card,
html.th-on[data-density="compact"] .panel, html.th-on[data-density="compact"] .card{
  padding:calc(18px * var(--dens,1));
}

/* ═══════════════════════════════════════════════════════════════════════════
   TYPEFACE — the last treatment THEME10 names. 12 September 2026, Sean's ruling:
   the chrome gets its OWN set of pairings, and the brand pack stays on documents.

   WHY THAT LINE, AND IT IS LAW 106'S LINE. Font Studio already serves twelve
   faces from this domain for a member's brand pack — their invoices, their
   letterhead, their quotes. Law 106 says a brand colour that leaks out of a
   document into the chrome contradicts it, and a brand FACE is the same shape.
   So a member finishes the room; they do not rebrand it. What they choose here
   is the room's own voice, from faces the platform already owns and serves.

   A MEMBER PICKS A PAIRING, NEVER A FACE PER ELEMENT, and that is th-system.css
   §590's law: two faces at one size sit on different baselines with different
   digit widths, and that is what reads as "not aligned". It was measured on
   levels.html with mono and sans both in use at 11, 12, 13 AND 14px. Each
   pairing below is internally consistent, and mono stays where it is asked for
   by name — code, keys, refs — in all three.

   THREE, not twelve. The chrome is not a canvas; it is the thing the content
   sits in, and a platform with twelve voices is twelve platforms to keep
   legible. Three is a real choice and every one of them is defensible.
   ═══════════════════════════════════════════════════════════════════════════ */

/* AS IT SHIPS — the default, declared so a member can come back to it by name
   rather than by clearing a setting. */
html.th-on[data-face="ship"]{
  --font-display:"Bricolage Grotesque",var(--font-sans);
}

/* ONE VOICE — headings in the body face. The quietest of the three: nothing in
   the chrome competes with what the member is actually reading, which is the
   right answer for somebody who lives on this platform all day. */
html.th-on[data-face="one"]{
  --font-display:var(--font-sans);
}

/* SHARPER — ClashDisplay carries the headings. It ships three weights here
   (500, 600, 700 — th-font-clashdisplay-*.woff2, 45KB in all), it is licensed,
   it is served from this domain under Law 85, and IT IS NAMED IN NO TOKEN: the
   platform has been paying to host a face it never once uses. This is the
   treatment that puts it to work. */
html.th-on[data-face="sharp"]{
  /* THE FAMILY NAME HAS A SPACE. th-fonts.css declares it as 'Clash Display', and a
     first cut of this rule wrote "ClashDisplay" — which matches nothing, falls straight
     through to var(--font-sans), and looks exactly like the pairing working. That is the
     silent font fallback, and the only way to catch it is to read the @font-face rather
     than the filename. The woff2 files are th-font-clashdisplay-*.woff2; the FACE is
     'Clash Display'. */
  --font-display:"Clash Display",var(--font-sans);
}

/* THE MONO IS NOT A CHOICE and is restated here so no pairing quietly drops it.
   JetBrains Mono is where a reference, a key or a line of code lives, in all
   three pairings, because a ref that changes shape between members is a ref two
   people cannot read to each other over a phone. */
html.th-on[data-face]{ --font-mono:"JetBrains Mono",ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; }


/* ── THE OLD PRICE — SEAN, 14 SEPTEMBER 2026 ─────────────────────────────────
   "do what facebook does, edit listing old price a line through new price."
   Two classes. gb-price.js decides WHEN they appear; this file only says what
   they look like, which is the whole of Law 100. The struck number is quiet on
   purpose and the live one carries the weight: a reader's eye should land on
   what the thing costs NOW, with the old price as context rather than as the
   headline. --skin-mut is the muted ink both themes already define, so this
   needs no dark-mode block of its own. tabular-nums so the two numbers line up
   digit for digit instead of jittering against each other. */
.gbwas{ color:var(--skin-mut); font-weight:500; text-decoration-thickness:1px;
        margin-right:.35em; font-variant-numeric:tabular-nums }
.gbnow{ font-variant-numeric:tabular-nums }

/* ── §14 · THE PROGRAMME'S CHART (18 Sep 2026) — every mark takes a token; the page keeps geometry only.
   Critical = "must" blue (a day lost there is a day lost on the finish — colour AND the word "critical" on the row);
   done = the done violet (completed is not success); progress = ink over the bar; baseline = a line; float = a hairline. */
.g-off{fill:var(--line);opacity:.45}
.g-week{stroke:var(--line);stroke-width:1}
.g-row{stroke:var(--line);stroke-width:1;opacity:.6}
.g-lbl,.g-name,.g-sub{fill:var(--th-ink)}
.g-sub,.g-lbl{fill:var(--th-mut)}
.g-crit-t{fill:var(--sig-must-ink)}
.g-sum{font-weight:590}
.g-look{fill:var(--sig-info-bg)}
.g-today{stroke:var(--sig-warn);stroke-width:2}
.g-today-lbl{fill:var(--sig-warn-ink)}
.g-bar{fill:var(--acc);opacity:.95}
/* 19 Sep 2026 · THE DETAILS. A bar takes its PHASE's colour from the safe Tier Two series (the phase is named in
   the table beside it, Law 79); critical work wears the "must" outline and the word; done work is dimmed. */
.g-ph1{fill:var(--t2-1)}.g-ph2{fill:var(--t2-2)}.g-ph3{fill:var(--t2-3)}.g-ph4{fill:var(--t2-4)}.g-ph5{fill:var(--t2-5)}.g-ph6{fill:var(--t2-6)}.g-ph7{fill:var(--t2-7)}.g-ph8{fill:var(--t2-8)}
.g-swatch.g-ph0{background:var(--acc)}.g-swatch.g-ph1{background:var(--t2-1)}.g-swatch.g-ph2{background:var(--t2-2)}.g-swatch.g-ph3{background:var(--t2-3)}.g-swatch.g-ph4{background:var(--t2-4)}.g-swatch.g-ph5{background:var(--t2-5)}.g-swatch.g-ph6{background:var(--t2-6)}.g-swatch.g-ph7{background:var(--t2-7)}.g-swatch.g-ph8{background:var(--t2-8)}
.g-bar.g-crit,.g-ms.g-crit{stroke:var(--sig-must);stroke-width:2}
.g-bar.g-done,.g-ms.g-done{opacity:.55}
.g-band-m{fill:var(--line);opacity:.45}.g-band-w{fill:var(--line);opacity:.25}.g-band-d{fill:none}.g-band-off{fill:var(--line);opacity:.55}
/* the task table beside the chart: its rows are the chart's rows, 30px each under a 60px head — the system
   sheet's own table padding (.sheet-light td) would make them 55px and put every bar beside the wrong task */
.gantt .g-tbl th,.gantt .g-tbl td{padding:0 6px;height:30px;line-height:32px;border:0;vertical-align:middle}
.gantt .g-tbl thead th{height:60px;line-height:60px}
.gantt .g-tbl thead th,.gantt .g-tbl tbody td{background:transparent}
.g-band-lbl{fill:var(--th-ink);font-weight:600;font-size:12px}
.g-day-n{fill:var(--th-ink);font-size:12px}.g-day-l{fill:var(--th-mut);font-size:12px}
.g-tr-sum td{font-weight:590}.g-tr-crit td.g-td-state{color:var(--sig-must-ink);font-weight:600}
.g-prog{fill:var(--th-ink);opacity:.28;pointer-events:none}
.g-ms{fill:var(--bz);stroke:var(--th-ink);stroke-width:1}
.g-sumbar{fill:var(--th-ink);opacity:.85}
.g-base{fill:var(--th-mut);opacity:.7}
.g-float{stroke:var(--th-mut);stroke-width:2;stroke-dasharray:3 3}
.g-link{fill:none;stroke:var(--th-ink);stroke-width:1.2;opacity:.7}
.g-link.g-link-odd{stroke-dasharray:4 3}
.g-arrow{fill:var(--th-ink);opacity:.7}
.g-horizon{stroke:var(--sig-warn);stroke-width:1.5;stroke-dasharray:5 4}
.g-horizon-lbl{fill:var(--sig-warn-ink)}
:root[data-theme="dark"] .g-bar{opacity:1}


/* ── THE OPTIONS BAR ──────────────────────────────────────────────────────────
   th-options.js mounts this on a tool page: the settings for the thing you are
   holding, read from that product's own declarations in core.product_option.

   It is painted HERE and not in the page, because it is a component several
   tools mount, and Law 100 says the theme paints while a page keeps geometry
   only. It sits ABOVE the generated block on purpose — _thememake.py rewrites
   everything below that line, so anything written under it is lost on the next
   run of the generator.

   A chip that carries a dot is the account's OWN value; a chip without one is
   following the platform default. The dot is the accent, which is the one place
   on this bar colour is spent — a bar of coloured chips would say everything is
   exceptional, which is the opposite of what it means. */
html.th-on .obar{display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap;
  padding:var(--s2) var(--s3);border-radius:var(--th-rsm)}
html.th-on .obar .ochip{display:inline-flex;align-items:center;gap:6px;white-space:nowrap}
html.th-on .obar .ochip .ol{color:var(--th-ink2);font-weight:400}
html.th-on .obar .ochip .ov{color:var(--th-ink);font-weight:600;
  font-variant-numeric:tabular-nums}
html.th-on .obar .ochip .oy{width:6px;height:6px;border-radius:99px;background:var(--acc);
  display:inline-block;flex:0 0 auto}
html.th-on .obar .ochip[disabled]{opacity:.55;cursor:not-allowed}
html.th-on .obar .omsg{margin-left:auto}



/* CORRECTED BEFORE IT SHIPPED, 23 Sep 2026, by the design gate — twice in my own
   new block. (1) --th-bg is a token I invented; it is not declared anywhere, and
   a var() with no fallback DROPS the whole declaration, so every panel in this
   frame would have had no background at all. The real names are --sheet and
   --canvas. (2) Four type sizes sat under the 12px floor — 10.5, 11, 11.5 and
   12.5 — and the law's reason is the whole argument: a person has to read this.
   They are on the scale now (--fs-12, --fs-13). A frame is furniture a member
   stares at all day; it is the last place to shave a pixel. */
/* ── A PROGRAM IS AN APPLICATION ── the frame that stood here (th-app.js, 22 Sep)
   adopted the shell's second column as a tool palette and an iframe as the
   surface. Replaced outright on 23 Sep 2026 by the application in
   deploy/measure.html — ribbon on top, palettes belonging to the document,
   canvas filling the window — declared by html[data-thapp="1"], which
   th-shell.js honours by suppressing #thSide. th-app.js is retired to
   _ARCHIVE/retired-23sep/ and its 158 lines of .thapp-* paint went with it.
   Sean, 22 Sep: "it an actual software with all the programs and tools listed
   in the 1st menu" — still the brief; this is its second, real answer. */
/* >>> GENERATED BY _thememake.py — DO NOT EDIT BELOW THIS LINE <<< */
/* Written from core.product_option by _thememake.py. Anything between
   these markers is replaced on the next run — change the settings in
   Mission Control and push, never this text.

   It sits at the END of the last stylesheet every page loads, so it wins
   on cascade order over cd-signature.css and over this sheet's own
   earlier declarations. Only `--` declarations live here, never a rule,
   so it can never fight a component on specificity. */
html.th-on{
  --th-rsm: 10px;
  --th-btn: 10px;
  --th-h: 40px;
  --dens: 1;
  --btn-bg: var(--well2);
  --btn-ink: var(--th-ink);
  --btn-line: var(--th-line2);
  --btn-p-bg: var(--anchor-deepteal);
  --btn-p-ink: #FFFFFF;
  /* advisory: the share of a screen the accent may cover. Measured across
     eleven live products on 22 Sep 2026 at 1.6-2.1%. A browser walk judges
     a page against this; nothing enforces it at build time. */
  --accent-area-cap: 2;
}
[data-skin="th"]{ --accent: var(--anchor-cyan); }
[data-skin="gb"]{ --accent: var(--anchor-copper); }
[data-skin="gm"]{ --accent: var(--anchor-violet); }
/* >>> END GENERATED <<< */

/* THE PASSWORD EYE LIVES INSIDE THE FIELD (Sean, 24 Sep 2026: "the login password eye needs no tablet to live in, it can just
   be the eye on the right hand side in the password field"). login, signup and set-password all use span.pwwrap > input +
   button.pweye[data-eye]; the theme's button rule had painted the eye as a bordered tablet beside the field. */
html.th-on .pwwrap{position:relative;display:block}
html.th-on .pwwrap input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=file]):not([type=color]):not([type=hidden]){padding-right:44px}   /* (0,8,1): the field rule above is (0,6,1) and its 16 px would win; the words must stop before the eye */
html.th-on .pwwrap .pweye,html.th-on .pwwrap [data-eye]{position:absolute;right:6px;top:50%;transform:translateY(-50%);width:32px;height:32px;min-height:0;min-width:0;padding:0;margin:0;border:0;background:none;box-shadow:none;border-radius:calc(var(--th-rsm)*.4);display:inline-flex;align-items:center;justify-content:center;color:var(--th-mut);cursor:pointer}
html.th-on .pwwrap .pweye:hover,html.th-on .pwwrap [data-eye]:hover{color:var(--th-ink);background:none;border:0}
html.th-on .pwwrap .pweye:focus-visible,html.th-on .pwwrap [data-eye]:focus-visible{outline:2px solid var(--acc);outline-offset:1px}
html.th-on .pwwrap .pweye svg,html.th-on .pwwrap [data-eye] svg{width:20px;height:20px}

/* 3 Oct 2026 · asset-register.html marks a machine past its service as .tag.over — it carried no colour at all. */
html.th-on .tag.over{background:var(--sig-danger-bg);color:var(--sig-danger-ink);border:1px solid var(--sig-danger-line)}
