/* HICHEM PUBLIC V2.6 — materiality, hierarchy and the spatial species.
   Loaded after surface-base-v24.css and geometry-v25.css.

   Three jobs, in order:
   1. impose one type and spacing scale over the V2.4 micro-variation;
   2. give each room a species so the page stops repeating one section template;
   3. give the real public artifacts the weight of archival plates. */

:root{
  /* Type scale — 12 / 14 / 16 / 20 / 26 / 42 / 68 / 110. Nothing below 12px exists. */
  --t-micro:12px;
  --t-meta:14px;
  --t-body:16px;
  --t-lede:20px;
  --t-lead:26px;
  --t-object:clamp(30px,3.1vw,42px);
  --t-section:clamp(38px,4.6vw,66px);

  /* Spacing — 8 / 13 / 21 / 34 / 55 / 89 / 144. */
  --s1:8px; --s2:13px; --s3:21px; --s4:34px; --s5:55px; --s6:89px; --s7:144px;

  /* Semantic tints. Named, never re-derived at the point of use. */
  --pass:#4D5842;
  --fail:#A74D2C;
  --plate-mat:rgba(24,24,21,.055);
  --dark-body:rgba(251,248,241,.78);
  --dark-muted:rgba(251,248,241,.60);
}

/* ══════════════════════════════════════════════════════════════
   1. MICRO TYPOGRAPHY — one floor, no drift below it.
   ══════════════════════════════════════════════════════════════ */
.meta,.kicker,.room__aside,.quiet-link,.topbar__inner,.hero__routes a,
.surface-dock,.footer__inner,.tag,.plate__origin{font-size:var(--t-micro)}
.body-copy{font-size:var(--t-body);line-height:1.68}
.lead{font-size:clamp(var(--t-lede),2.1vw,var(--t-lead))}

/* Dark rooms: readable secondary text, and a hover state that gets lighter, never darker. */
.room--dark{color:var(--chalk)}
.room--dark p,.room--dark dd,.room--dark li{color:var(--dark-body)}
.room__aside--light{color:var(--dark-muted)}
.quiet-link--light{color:var(--dark-muted);border-bottom-color:var(--light-rule)}.quiet-link--light:focus-visible{color:var(--gold);border-bottom-color:var(--gold)}
.room--dark .quiet-link{color:var(--dark-muted);border-bottom-color:var(--light-rule)}
.room--dark a{color:inherit}

/* ══════════════════════════════════════════════════════════════
   2. SPATIAL SPECIES — the page stops using one grammar for everything.
   ══════════════════════════════════════════════════════════════ */

/* MONUMENT — occupies the viewport, carries a strong optical centre, says little. */
.room[data-species="monument"] .statement{max-width:12em}

/* CHAMBER — intimate and constrained. */
.room[data-species="chamber"] .statement{font-size:clamp(34px,3.9vw,54px);max-width:13em}

/* STUDY — denser and quieter. Nothing here gets a monument headline. */
.statement--study,.room[data-species="study"] .statement{font-size:clamp(26px,2.6vw,38px);line-height:1.06;letter-spacing:-.028em;max-width:18em}
.room[data-species="study"] .kicker{color:var(--graphite)}
.study-lead{margin-bottom:var(--s5);max-width:44em}
.study-grid{display:grid;align-items:start}
.study-copy{min-width:0}

/* PLATE — the artifact is the section. No headline competes with it. */
.room[data-species="plate"]{border-top:0;background:linear-gradient(180deg,rgba(243,239,228,.6),rgba(238,233,221,.92))}

/* APERTURE — a tonal break, not a dark theme. */
.room[data-species="aperture"] .statement{max-width:14em}

/* SILENCE — generous emptiness. One line has to carry the room. */
.room[data-species="silence"]{border-top:0;background:transparent}
.law-moment{padding-left:clamp(0px,4vw,var(--s6))}
.law-moment .kicker{margin-bottom:var(--s5)}
.law-moment__line{font:400 clamp(30px,4.2vw,58px)/1.14 var(--serif);letter-spacing:-.022em;max-width:16em}
.law-moment__gloss{font:400 var(--t-lede)/1.55 var(--serif);color:var(--graphite);margin-top:var(--s4);max-width:32em}
.law-moment .quiet-link{display:inline-block;margin-top:var(--s5)}

/* ══════════════════════════════════════════════════════════════
   3. THE HALL
   ══════════════════════════════════════════════════════════════ */
.hall__claim-block{min-width:0}
.hall__now{font:400 var(--t-lede)/1.5 var(--serif);color:var(--graphite);margin-top:var(--s4)}
.hall__lead{margin-top:var(--s4)}
.hall__body{margin-top:var(--s3);max-width:36em}
.hall__routes{gap:var(--s2) var(--s4);margin-top:var(--s5);align-items:baseline}
.hall__routes a{display:inline-flex;align-items:baseline;gap:var(--s1);border-bottom:1px solid var(--rule);padding-bottom:5px}
.hall__routes a span{color:var(--gold);font-weight:600}
.hall__routes a b{font-weight:600;color:var(--graphite)}.hall__routes a:focus-visible b{color:var(--ink)}.hall__routes a:focus-visible{border-bottom-color:var(--oxide)}

/* ══════════════════════════════════════════════════════════════
   4. THE THREE DOORS
   ══════════════════════════════════════════════════════════════ */
.doors{display:grid;border-top:1px solid var(--ink)}
.door{display:flex;flex-direction:column;padding-top:var(--s4);padding-bottom:var(--s2)}
.door__kind{font:600 var(--t-micro)/1.35 var(--mono);letter-spacing:.15em;text-transform:uppercase;color:var(--graphite)}
.door__name{font-size:clamp(27px,2.5vw,36px);font-weight:600;letter-spacing:-.03em;line-height:1.05;margin-top:var(--s3)}
.door__line{font:400 var(--t-body)/1.6 var(--serif);color:var(--graphite);margin-top:var(--s2);max-width:26em}
.door__proof{margin-top:var(--s3)}
.door__exits{display:flex;flex-direction:column;gap:var(--s1);margin-top:auto;padding-top:var(--s4)}
.door__exit{font:600 var(--t-micro)/1.4 var(--mono);letter-spacing:.1em;text-transform:uppercase;text-decoration:none;color:var(--graphite);align-self:flex-start;border-bottom:1px solid transparent;padding-bottom:3px}
.door__exit--primary{color:var(--ink);border-bottom-color:var(--rule)}.door__exit:focus-visible{color:var(--oxide-text);border-bottom-color:var(--oxide)}
@media (min-width:1261px){
  .door+.door{padding-inline-start:clamp(28px,3.4vw,55px);border-inline-start:1px solid var(--rule)}
  /* the gutter was carried entirely as leading padding, so card 1 ran 14% wider
     than its two peers and its dividing rule had no clearance */
  .door:first-child{padding-inline-end:clamp(28px,3.4vw,55px)}
  .doors{column-gap:0}
}
@media (max-width:1260px){.door+.door{border-top:1px solid var(--rule)}}

/* ══════════════════════════════════════════════════════════════
   5. LABEL VOCABULARY — five words, used the same way everywhere.
   ══════════════════════════════════════════════════════════════ */
.tag{display:inline-block;font:600 var(--t-micro)/1 var(--mono);letter-spacing:.14em;text-transform:uppercase;padding:7px 11px;border:1px solid currentColor;color:var(--graphite)}
.tag--artifact{color:var(--oxide-text)}
.tag--specimen{color:var(--graphite)}
.tag--reconstruction{color:var(--olive)}
.tag--law{color:var(--ink)}
.tag--private{color:var(--oxide-text)}
.tag--open{color:var(--graphite)}
.room--dark .tag{color:var(--dark-muted)}
.room--dark .tag--artifact{color:var(--gold)}

/* ══════════════════════════════════════════════════════════════
   6. THE APERTURE — disclosure stated once, in one place.
   ══════════════════════════════════════════════════════════════ */
.aperture{display:grid;align-items:start;min-height:0;margin-top:var(--s2)}
.aperture__side{min-width:0}
.aperture__label{font:600 var(--t-micro)/1 var(--mono);letter-spacing:.24em;text-transform:uppercase;color:var(--gold)}
.aperture__side--closed .aperture__label{color:var(--dark-muted)}
.aperture__side{padding:clamp(28px,4vw,55px)}
.aperture__list{list-style:none;margin-top:var(--s3)}
.aperture__list li{font:400 var(--t-body)/1.5 var(--serif);color:var(--dark-body);padding:var(--s2) 0;border-bottom:1px solid var(--light-rule)}
.aperture__side--closed .aperture__list li{color:var(--dark-muted)}
.aperture__legend{margin-top:var(--s6);border-top:1px solid var(--light-rule);padding-top:var(--s4)}
.aperture__legend-lead{font:400 var(--t-body)/1.6 var(--serif);color:var(--dark-body);max-width:40em;margin-bottom:var(--s4)}
.legend{display:grid}
.legend>div{display:grid;align-items:baseline;padding:var(--s2) 0;border-bottom:1px solid var(--light-rule)}
.legend dt{min-width:0}
.legend dd{font:400 var(--t-body)/1.5 var(--serif);color:var(--dark-muted)}

/* ══════════════════════════════════════════════════════════════
   7. ARCHIVAL PLATES — the real material, framed and mounted.
   ══════════════════════════════════════════════════════════════ */
.plate{display:block}
.plate__frame{position:relative;background:var(--chalk);border:1px solid var(--ink);box-shadow:0 var(--s3) var(--s6) rgba(24,24,21,.055)}
.plate__frame::after{content:"";position:absolute;inset:var(--s2);border:1px solid var(--plate-mat);pointer-events:none}
.plate__mast{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--s2) var(--s3);padding-bottom:var(--s3);border-bottom:1px solid var(--rule);margin-bottom:var(--s4)}
.plate__origin{font:500 var(--t-micro)/1.4 var(--mono);letter-spacing:.05em;color:var(--graphite);overflow-wrap:anywhere}
.plate__body{min-width:0}
.plate__title{font:600 var(--t-micro)/1 var(--mono);letter-spacing:.2em;text-transform:uppercase;color:var(--graphite)}
.plate__ascii{font:400 clamp(13px,1.15vw,16px)/1.28 var(--mono);color:var(--ink);margin:var(--s4) 0 var(--s3);white-space:pre;overflow-x:auto}
.plate__verdict{font:400 clamp(26px,3.2vw,42px)/1.12 var(--serif);letter-spacing:-.02em;color:var(--ink);margin-bottom:var(--s4);max-width:16em}
.plate__fields{display:grid;border-top:1px solid var(--rule)}
.plate__fields>div{display:contents}
.plate__fields dt,.plate__fields dd{padding:var(--s2) 0;border-bottom:1px solid var(--rule-soft);font:500 var(--t-meta)/1.4 var(--mono)}
.plate__fields dt{letter-spacing:.1em;text-transform:uppercase;color:var(--graphite)}
.plate__fields dd{color:var(--ink);word-break:break-word}
.plate__cmd{margin-top:var(--s4);font:500 var(--t-meta)/1.5 var(--mono);color:var(--graphite)}
.plate__cmd span{letter-spacing:.14em;text-transform:uppercase;font-size:var(--t-micro);margin-right:var(--s2)}
.plate__cmd code{color:var(--ink);background:rgba(24,24,21,.045);padding:4px 8px;overflow-wrap:anywhere}
.plate__section-label{margin-top:var(--s5);font:600 var(--t-micro)/1 var(--mono);letter-spacing:.2em;text-transform:uppercase;color:var(--oxide-text)}
.plate__list{list-style:none;margin-top:var(--s3)}
/* The list marker is house punctuation, not artifact content: a quiet point,
   and logical geometry so it sits on the correct side in Arabic. It used to be
   an em dash corrected by a later override layer; the correction now lives here,
   where the marker is actually declared. */
.plate__list li{font:400 var(--t-meta)/1.6 var(--mono);color:var(--graphite);padding:var(--s1) 0;padding-inline-start:var(--s3);position:relative;overflow-wrap:anywhere}
.plate__list li::before{content:"·";position:absolute;left:auto;inset-inline-start:0;color:var(--oxide)}
.plate__seal{margin-top:var(--s5);padding-top:var(--s3);border-top:1px solid var(--gold);font:600 var(--t-meta)/1.4 var(--mono);letter-spacing:.16em;text-transform:uppercase;color:var(--ink)}
.plate__caption{margin-top:var(--s3);font:400 var(--t-body)/1.6 var(--serif);color:var(--graphite);max-width:46em}
.plate__caption code{font:500 var(--t-meta) var(--mono);color:var(--ink)}
.plate__caption--wide{max-width:52em;margin-top:var(--s4)}
.plate__caption--light{color:var(--dark-muted)}
.plate__caption--light code{color:var(--gold)}

/* Machine-readable plates. Hashes and URLs are the one place a hard break is correct. */
.plate__code{font:400 clamp(12px,.95vw,14px)/1.72 var(--mono);color:var(--ink);white-space:pre-wrap;overflow-wrap:anywhere;margin:0}
.j-k{color:var(--graphite)}
.j-s{color:var(--ink)}
.j-n{color:var(--oxide-text)}
.j-hash{word-break:break-all;border-bottom:1px solid rgba(181,142,79,.55)}
.j-ok{color:var(--pass)}
.j-no{color:var(--fail)}

.plate--dark .plate__frame{background:rgba(251,248,241,.05);border-color:var(--light-rule);box-shadow:none}
.plate--dark .plate__frame::after{border-color:rgba(251,248,241,.07)}
.plate--dark .plate__mast{border-bottom-color:var(--light-rule)}
.plate--dark .plate__origin{color:var(--dark-muted)}
.plate--dark .plate__code{color:var(--dark-body)}
.plate--dark .j-k{color:var(--dark-muted)}
.plate--dark .j-s{color:var(--chalk)}
.plate--dark .j-n{color:var(--gold)}
.plate--dark .j-hash{border-bottom-color:rgba(181,142,79,.6)}

.plate--refused .plate__frame{border-color:var(--oxide)}
.receipt-pair{display:grid;align-items:start;margin-top:var(--s3)}

/* Operational documents keep their blanks. The blanks are the argument. */
.plate__doc{min-width:0}
.plate__doc-note{font:400 var(--t-body)/1.6 var(--serif);color:var(--graphite);padding-bottom:var(--s3);border-bottom:1px solid var(--rule);max-width:40em}
.plate__doc-head{margin-top:var(--s4);font:600 var(--t-micro)/1 var(--mono);letter-spacing:.2em;text-transform:uppercase;color:var(--ink)}
.plate__doc-list{list-style:none;margin-top:var(--s3)}
.plate__doc-list li{font:400 var(--t-meta)/1.5 var(--mono);color:var(--graphite);padding:var(--s1) 0;border-bottom:1px dotted var(--rule)}
.plate__doc-stop{margin-top:var(--s3);font:500 var(--t-meta)/1.5 var(--mono);color:var(--oxide-text)}
.plate__doc-choice{margin-top:var(--s3);font:600 var(--t-meta)/1.5 var(--mono);letter-spacing:.1em;color:var(--ink)}

/* ══════════════════════════════════════════════════════════════
   8. SMALLER OBJECTS
   ══════════════════════════════════════════════════════════════ */
.recovery-run{display:grid;list-style:none;margin-top:var(--s5);border-top:1px solid var(--ink)}
.recovery-run li{display:grid;grid-template-columns:44px minmax(0,1fr);align-items:baseline;gap:var(--s2);padding:var(--s2) 0;border-bottom:1px solid var(--rule-soft)}
.recovery-run span{font:600 var(--t-micro)/1.4 var(--mono);letter-spacing:.14em;color:var(--gold)}
.recovery-run b{font:600 var(--t-meta)/1.4 var(--sans);letter-spacing:-.01em}

.anatomy{min-width:0}
.anatomy__label{font:600 var(--t-micro)/1 var(--mono);letter-spacing:.2em;text-transform:uppercase;color:var(--graphite)}
.anatomy__list{display:grid;list-style:none;margin-top:var(--s3);border-top:1px solid var(--ink)}
.anatomy__list li{font:400 var(--t-meta)/1.5 var(--mono);color:var(--ink);padding:var(--s2) 0;border-bottom:1px solid var(--rule-soft)}
.anatomy__test{margin-top:var(--s4)}
.anatomy__test span{display:block;font:600 var(--t-micro)/1 var(--mono);letter-spacing:.16em;text-transform:uppercase;color:var(--oxide-text)}
.anatomy__test b{display:block;margin-top:var(--s1);font:400 var(--t-lede)/1.35 var(--serif);letter-spacing:-.015em}

/* Intellectual lineage is cited where it did the work, not displayed as a wall. */
.cite{margin-top:var(--s4);padding-inline-start:var(--s3);border-inline-start:2px solid var(--gold);max-width:38em}
.cite--wide{max-width:52em;margin-top:var(--s6)}
.cite__q{font:400 var(--t-lede)/1.4 var(--serif);letter-spacing:-.015em;color:var(--ink)}
.cite__who{margin-top:var(--s1);font:500 var(--t-meta)/1.5 var(--mono);color:var(--graphite)}
.cite__who a{color:var(--oxide-text);text-decoration:none;border-bottom:1px solid var(--rule)}.cite__who a:focus-visible{border-bottom-color:var(--oxide)}
.cite--light .cite__q{color:var(--chalk)}
.cite--light .cite__who{color:var(--dark-muted)}
.cite--light .cite__who a{color:var(--gold);border-bottom-color:var(--light-rule)}

.lineage{display:grid;list-style:none;margin-top:var(--s4);border-top:1px solid var(--ink)}
.lineage li{display:grid;align-items:baseline;padding:var(--s2) 0;border-bottom:1px solid var(--rule-soft)}
.lineage a{font:600 var(--t-meta)/1.4 var(--sans);color:var(--ink);text-decoration:none;border-bottom:1px solid var(--rule)}.lineage a:focus-visible{color:var(--oxide-text);border-bottom-color:var(--oxide)}
.lineage span{font:400 var(--t-meta)/1.4 var(--serif);color:var(--graphite)}

.laws__exit{margin-top:var(--s4)}

/* Corpus status words reuse the same five-label vocabulary. */
.corpus-panel small.tag{margin-top:auto;align-self:flex-start}

/* SPECTRA phases are real buttons now, not focusable list items.
   The base sheet makes the <li> the grid; the control has to be the grid instead,
   or the button is trapped inside a 48px track and its copy wraps one letter per line. */
.spectra-loop{list-style:none}
.spectra-loop li{display:block;padding:0;border-bottom:1px solid var(--light-rule);background:none;box-shadow:none;cursor:auto}.spectra-loop li.is-active{background:none;box-shadow:none}
.spectra-loop li>button{display:grid;width:100%;text-align:start;align-items:baseline;gap:var(--s2);background:transparent;border:0;padding:var(--s3) var(--s2);cursor:pointer;color:inherit}.spectra-loop li>button[aria-checked="true"]{background:rgba(251,248,241,.045);box-shadow:inset 2px 0 var(--gold)}
.spectra-loop li>button span{font:600 var(--t-micro)/1 var(--mono);letter-spacing:.14em;color:var(--dark-muted)}
.spectra-loop li>button b{font:600 var(--t-meta)/1.3 var(--sans);color:var(--chalk)}
.spectra-loop li>button small{font:400 var(--t-micro)/1.4 var(--mono);color:var(--dark-muted)}.spectra-loop li>button[aria-checked="true"] b{color:var(--gold)}
.spectra-loop li>button[aria-checked="true"] span{color:var(--gold)}

/* ══════════════════════════════════════════════════════════════
   9. CHROME — navigation is architecture, preferences are furniture.
   ══════════════════════════════════════════════════════════════ */
.surface-dock{display:grid;background:rgba(243,239,228,.94);border:1px solid rgba(24,24,21,.2);box-shadow:0 var(--s2) var(--s5) rgba(24,24,21,.075);font:600 var(--t-micro)/1.15 var(--mono);letter-spacing:.11em;text-transform:uppercase;color:var(--graphite);min-height:0}
.surface-dock>a{display:flex;align-items:center;justify-content:center;min-height:46px;padding:12px 16px;text-decoration:none;color:inherit;border-inline-end:1px solid rgba(24,24,21,.13)}
.surface-dock>a:last-child{border-inline-end:0}.surface-dock>a:focus-visible{background:rgba(24,24,21,.045);color:var(--ink)}
.surface-dock>a[aria-current="page"]{color:var(--ink);box-shadow:inset 0 -2px var(--gold)}
.surface-dock__home{font-size:16px;letter-spacing:0}

.footer__inner{display:grid;align-items:end;padding-block:var(--s4) var(--s5);max-width:var(--geo-reading);margin-inline:auto;font:600 var(--t-micro)/1.5 var(--mono);letter-spacing:.09em;text-transform:uppercase;color:var(--graphite)}
.footer__identity{display:flex;flex-direction:column;gap:var(--s1);min-width:0}
.footer__identity span:first-child{color:var(--ink)}
.prefs{display:grid;align-items:end}
.prefs__group{display:flex;flex-direction:column;gap:6px;margin:0}
.prefs__label{font-size:var(--t-micro);letter-spacing:.16em;color:var(--graphite)}
.prefs__toggle{background:transparent;border:1px solid var(--rule);padding:8px 12px;min-height:34px;font:inherit;line-height:1;font-size:var(--t-micro);letter-spacing:.1em;color:var(--graphite);cursor:pointer}
.prefs__toggle b{color:var(--ink);font-weight:600}

/* ══════════════════════════════════════════════════════════════
   10. MOTION — long, unsynchronised, and never required to read.
   ══════════════════════════════════════════════════════════════ */
body[data-motion="still"] .world>*,
body[data-motion="still"] .pulse,
body[data-motion="still"] .orbit,
body[data-motion="still"] .hero::after{animation:none!important}
body[data-motion="still"] .reveal{opacity:1!important;transform:none!important}

@media (prefers-reduced-motion:reduce){
  .plate__frame{box-shadow:none}
}

/* ══════════════════════════════════════════════════════════════
   11. THE 12px FLOOR — including inside the drawings.

   Vector labels live in viewBox units, so their *rendered* size is
   fs × (renderedWidth / viewBoxWidth). Measured on this build the labels
   were rendering at 4.2–11px. The values below are chosen per figure and
   per width band to land every label between roughly 11px and 14px.
   ══════════════════════════════════════════════════════════════ */
.segmented button{font-size:var(--t-micro);padding:12px 8px}
.node-list button{font-size:var(--t-micro)}
.node-list button span{opacity:1;font-weight:400;color:var(--graphite)}
.readout__meta{font-size:var(--t-micro)}
.gate-specimen dl dt,.gate-specimen dl dd{font-size:var(--t-micro)}
.gate-controls button{font-size:var(--t-micro)}
.gate-controls button b{font-size:var(--t-micro)}
.spectra-readout>span,.spectra-readout>small{font-size:var(--t-micro)}
.agent-card dt{font-size:var(--t-micro)}
.region-list button small,.corpus-panel small,.manifest-list b,.loop-readout>span{font-size:var(--t-micro)}
.hypotheses article small,.observation>span,.judgment__seal>span,.judgment__seal small,
.message-sheet>span,.message-sheet small,.gate-specimen__line span{font-size:var(--t-micro)}

/* vb 620 — home and cabinet hall figures */
.hero__visual text{font-size:14px}
/* vb 760 — SYSTASYS constellation */
.systasys-constellation text{font-size:17px}
/* vb 760 — continuity orbit */
.continuity-orbit text{font-size:14px}
/* vb 1240 — the wide working map */
.home-map__wide text{font-size:18px}
/* vb 340 — the dedicated mobile working map */
.home-map__mobile text{font-size:13px}

@media (max-width:760px){
  .hero__visual text{font-size:16px}
  .systasys-constellation text{font-size:20px}
  .continuity-orbit text{font-size:20px}
}
@media (max-width:543px){
  .hero__visual text{font-size:18px}
  .systasys-constellation text{font-size:22px}
  .continuity-orbit text{font-size:22px}
}
@media (max-width:430px){
  .hero__visual text{font-size:21px}
  .systasys-constellation text{font-size:26px}
  .continuity-orbit text{font-size:26px}
}
/* The check now fails below 12px rather than below 11.5px, and this band was
   landing at 11.7–11.9px between 341 and 400. Boundary moved from 379 to 400 so
   360 and 384 are covered by one step, and the step raised to clear 12px. */
@media (max-width:400px){
  .hero__visual text{font-size:24px}
  .systasys-constellation text{font-size:29px}
  .continuity-orbit text{font-size:30px}
}

/* ══════════════════════════════════════════════════════════════
   12. TOUCH TARGETS — standalone affordances reach 44px on touch widths.
   Links inside running prose are deliberately excluded; WCAG exempts them
   and padding them would break the paragraph rhythm.
   ══════════════════════════════════════════════════════════════ */
.receipt-copy details{margin-top:var(--s4);border-top:1px solid var(--light-rule);padding-top:var(--s3)}
.receipt-copy summary{font:600 var(--t-micro)/1.4 var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--dark-muted);cursor:pointer;padding:var(--s1) 0;list-style:none}
.receipt-copy summary::-webkit-details-marker{display:none}
.receipt-copy summary::before{content:"+ ";color:var(--gold)}
.receipt-copy details[open] summary::before{content:"– "}
.receipt-copy details p{margin-top:var(--s2);font:400 var(--t-body)/1.6 var(--serif)}

@media (max-width:760px){
  .skip{padding:15px 21px}
  .door__exit,.quiet-link,.laws__exit a,.law-moment .quiet-link{display:inline-flex;align-items:center;min-height:44px}
  .receipt-copy summary{min-height:44px;display:flex;align-items:center}
  .prefs__toggle{min-height:44px;padding-inline:16px}
  .segmented button,.node-list button{min-height:44px}
}

/* Remaining floor violations found by measuring the rendered page, not the source. */
.judgment__tabs button,.hyp-controls button,.hypotheses article span,.quiet-button,
.corpus-tabs button,.corpus-panel article>span,.readout small,.readout p,
.region-list button strong,.recovery-run span,.loop-readout>strong,.agent-card .meta,
.region-readout .meta,.manifest-list span,.spectra-loop li>button small{font-size:var(--t-micro)}
.readout p{font-size:var(--t-body)}
.skip{padding:16px 21px}
.law summary>span,.law__body em,.spectra-loop li>button>span,.region-laws span,.region-laws i,
.door__exits a,.plate__list li,.plate__doc-list li{font-size:var(--t-micro)}
.law__body em{font-size:var(--t-meta)}
.plate__list li,.plate__doc-list li{font-size:var(--t-meta)}
.region-list button>span,.corpus-panel article>span,.agent-card dd{font-size:var(--t-micro)}
.agent-card dd{font-size:var(--t-body)}

.meta--note,.spectra-copy .meta{text-transform:none;letter-spacing:.02em;line-height:1.6;max-width:34em}
.corpus-tabs{margin-top:var(--s6)}
@media (max-width:760px){
  .plate__fields dt{padding-right:var(--s3)}
  .plate__fields dd{word-break:break-word}
}

/* ══════════════════════════════════════════════════════════════
   13. SELECTED STATE — the controls became radiogroups, so the
   visual state has to follow aria-checked, not aria-selected.
   ══════════════════════════════════════════════════════════════ */
.segmented button[aria-checked="true"]{background:var(--ink);color:var(--chalk)}
.judgment__tabs button[aria-checked="true"]{background:var(--ink);color:var(--chalk)}
.agent-tabs button[aria-checked="true"]{color:var(--ink);padding-inline-start:10px;box-shadow:inset 2px 0 var(--gold)}
.node-list button[aria-checked="true"],.node-list button.is-active{color:var(--oxide-text);padding-inline-start:10px;padding-inline-end:0;box-shadow:inset 2px 0 var(--oxide)}
[dir="rtl"] .node-list button[aria-checked="true"],[dir="rtl"] .node-list button.is-active{box-shadow:inset -2px 0 var(--oxide)}
.region-list button[aria-checked="true"]{color:var(--ink);padding-inline-start:10px;box-shadow:inset 2px 0 var(--gold)}
.corpus-tabs button[aria-selected="true"]{color:var(--oxide-text);box-shadow:inset 0 -2px var(--oxide)}

/* ══════════════════════════════════════════════════════════════
   14. CONTRAST — measured on the rendered page, not on the palette.

   Gold is an illumination colour. At 2.63:1 on paper it is a mark, a rule or a
   line, never a character a visitor has to read. Everything below either moves
   off gold or moves onto a ground gold can survive.
   ══════════════════════════════════════════════════════════════ */
.hall__routes a span{color:var(--oxide-text)}
.region-laws i{color:var(--graphite)}

/* The capability manifest moved from a dark room to a quiet light one; its status
   tints were chosen for ink and washed out on paper. Re-toned for the new ground. */
.manifest-list{border-top-color:var(--rule)}
.manifest-list div{border-bottom-color:var(--rule)}
.manifest-list b{border-color:var(--rule);color:var(--graphite);font-size:var(--t-micro)}
.manifest-list b[data-state="visible"]{color:var(--graphite)}
.manifest-list b[data-state="proven"]{color:var(--olive);border-color:var(--olive)}
.manifest-list b[data-state="proof"]{color:var(--oxide-text);border-color:var(--oxide)}
.manifest-list b[data-state="future"]{color:#6B5526;border-color:#6B5526}
.manifest-list b[data-state="private"]{color:var(--chalk);background:var(--ink);border-color:var(--ink)}
.manifest-list span{color:var(--ink)}

/* The closing law reads in ink; the gold becomes the rule beside it. */
.manifest-quote{padding-inline-start:var(--s3);border-inline-start:2px solid var(--gold)}
.manifest-quote strong{color:var(--ink);font-weight:600}
.recovery-run span{color:var(--oxide-text)}

/* ══════════════════════════════════════════════════════════════
   15. THE DISTANT WORLD — measured, then rationed.

   Profiled at 412x915 with a 2x device pixel ratio: with the fixed background
   the scroll frame budget was p50 133ms; with it removed, p50 16.7ms. The cost
   is paint, not composite — `worldDust` animates background-position across a
   full-viewport layer and `worldOrbit` transforms a layer full of large radial
   gradients. Both cycles are measured in minutes, so on a touch device nobody
   can perceive what they cost.

   The brief's sacrifice order is followed exactly:
     1. backdrop blur   — dropped for coarse pointers (see geometry-v25.css)
     2. dust motion     — stopped here; the points remain, they stop drifting
     3. orbit motion    — stopped here; the rings remain
     4. grid intensity  — reduced here
   Nothing about content clarity is touched, and the desktop field is untouched.
   ══════════════════════════════════════════════════════════════ */
@media (pointer:coarse),(hover:none){
  .world__dust{animation:none}
  .world__orbits{animation:none}
  .world__grid{opacity:.14}
  .world__haze{opacity:.62}
}
/* The one animation that survives everywhere is composited, so hint it. */
.world__orbits{will-change:transform}

/* ── The dust layer, rebuilt to composite ──────────────────────
   Per-layer isolation at 1440x900 while scrolling:
     all four layers ........ p50 433ms
     minus grid ............. p50 433ms   (the grid is free)
     minus orbits ........... p50 417ms
     minus haze ............. p50 417ms
     minus dust ............. p50  83ms   ← the whole cost is here
     grid alone ............. p50  17ms

   The cause is not the number of points. It is `worldDust` animating
   background-position, which repaints four tiled radial gradients across the
   whole viewport on every frame. Moving the drift onto a child that animates
   `transform` lets the points rasterize once and then be moved by the
   compositor. The parallax keeps the parent transform, so the two never fight.

   The cycle alternates rather than loops, so it never has a seam to hide, and
   at 251s each way the movement is only perceptible as presence. */
.world__dust{background-image:none;animation:none;overflow:hidden}
.world__dust::before{
  content:"";position:absolute;inset:-14%;
  background-image:
    radial-gradient(circle at 11% 23%,rgba(181,142,79,.17) 0 1px,transparent 1.7px),
    radial-gradient(circle at 71% 31%,rgba(77,88,66,.14) 0 1px,transparent 1.55px),
    radial-gradient(circle at 38% 76%,rgba(24,24,21,.105) 0 .8px,transparent 1.45px),
    radial-gradient(circle at 87% 68%,rgba(147,68,39,.1) 0 1px,transparent 1.7px);
  background-size:311px 277px,401px 353px,229px 263px,487px 421px;
  animation:worldDrift 251s ease-in-out infinite alternate;
  will-change:transform;
}
@keyframes worldDrift{to{transform:translate3d(-46px,38px,0)}}
body[data-motion="still"] .world__dust::before{animation:none}
@media (prefers-reduced-motion:reduce){.world__dust::before{animation:none}}
@media (pointer:coarse),(hover:none){.world__dust::before{animation:none}}
.loop-readout+.quiet-link{display:inline-block;margin-top:var(--s4)}

/* ── V2.6.1 · plate provenance ─────────────────────────────────
   A plate labelled PUBLIC ARTIFACT has to say whether it is the whole file or
   an extract, otherwise the label promises more than the plate delivers. The
   scope line sits under the origin so the mast keeps its two-part balance. */
/* The mast was a two-part balance: label left, origin right. A flex row with a
   taller right-hand block wraps the label onto its own line and the whole thing
   reads as an accident, so the mast becomes an explicit two-column grid. The
   label now holds its place and the scope line stacks under the origin. */
.plate__mast{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:start;column-gap:var(--s4)}
.plate__provenance{display:flex;flex-direction:column;align-items:flex-end;gap:4px;min-width:0;justify-self:end}
.plate__scope{font:400 var(--t-micro)/1.4 var(--mono);letter-spacing:.04em;color:var(--graphite);text-align:right}
.plate--dark .plate__scope{color:var(--dark-muted)}
@media (max-width:760px){
  .plate__mast{grid-template-columns:minmax(0,1fr);gap:var(--s2)}
  .plate__provenance{align-items:flex-start;justify-self:start}
  .plate__scope{text-align:start}
}

/* ── V2.6.1 · the reflow width ─────────────────────────────────
   WCAG 1.4.10 asks content to reflow at 320 CSS px — 1280 at 400% browser zoom.
   Measured there, the vector labels fell to 10.4–10.9px, under this surface's own
   12px floor. This band exists only below 341px, so nothing at any tested device
   width moves. */
@media (max-width:340px){
  .hero__visual text{font-size:27px}
  .systasys-constellation text{font-size:33px}
  .continuity-orbit text{font-size:32px}
  .home-map__mobile text{font-size:15px}
}


/* ══════════════════════════════════════════════════════════════
   16. V2.6.2 · TOUCH TARGETS — the blind spot.

   The audit had been exempting the topbar and the hall/hero route links as
   though they were prose. They are standalone navigation and the declared
   contract is 44px, so they now meet it. Each block is re-proportioned so the
   larger target does not push the composition down:

     topbar     link 18px -> 44px, band padding 21px -> 8px   (bar height held)
     routes     link 20px -> 44px, row gap 13px -> 0          (rule does the separating)
     lineage    link 21px -> 44px, row padding 13px -> 0      (row height held)
   ══════════════════════════════════════════════════════════════ */
@media (max-width:430px){
  .topbar{padding-block:8px}
  .topbar__brand,.topbar__link{display:inline-flex;align-items:center;min-height:44px}

  .hall__routes{row-gap:0}
  .hall__routes a{min-height:44px;align-items:center;padding-bottom:0}

  .lineage li{padding-block:0}
  .lineage a{display:inline-flex;align-items:center;min-height:44px}
}
.plate__doc-note--tight{margin-top:var(--s3);padding-bottom:0;border-bottom:0;font:500 var(--t-meta)/1.5 var(--mono);color:var(--graphite)}
.plate__doc-list--choice li{color:var(--ink);font-weight:500;letter-spacing:.06em}

/* ══════════════════════════════════════════════════════════════
   17. V2.6.2 · the dock must not sit on the opening composition.

   Measured at rest on Samsung widths, the dock band crossed the hero drawing on
   all three routes — 12 of 12 page/width combinations, including the PROBLEM,
   PROOF and PATTERNS labels.

   Two causes, and only the first is a bug:

   1. The dock declared 50px and occupied 94px, because a `grid-template-rows:
      46px 46px` from the six-control era left a dead 48px strip below the three
      links. Fixed in geometry-v25.css. That alone removed half the intrusion.

   2. The rest is inherent: a fixed panel pinned to the fold will cross any hero
      taller than the viewport. Shrinking each drawing to dodge it was tried and
      rejected — it fought each page's geometry, still left 7 of 12 colliding,
      and pushed the vector labels toward the 12px floor.

   So the dock steps aside while the opening composition is on screen and returns
   once the reader is past it. Same three targets, same 44px, same semantics; it
   simply stops lying on the drawing. Without JS the dock stays put, which is the
   behaviour that shipped, so nothing regresses.
   ══════════════════════════════════════════════════════════════ */
@media (max-width:760px){
  .surface-dock{transition:transform .32s cubic-bezier(.2,.75,.2,1),opacity .28s ease}
  body[data-dock="stood-down"] .surface-dock{
    transform:translateY(calc(100% + 24px));
    opacity:0;
    pointer-events:none;
  }
}
@media (prefers-reduced-motion:reduce){
  .surface-dock{transition:none}
}

/* ══════════════════════════════════════════════════════════════
   18. V2.6.2 · linework must not bite a label.

   ASSO found two real intersections the earlier tangency check could not see,
   because that check compared HTML text against whole SVG boxes and never looked
   inside a drawing. On the Cabinet hero six strokes crossed CONSTRAINT; on the
   SYSTASYS constellation five crossed CONTINUITY.

   Offsetting the labels was rejected: both sit on their diagram's vertical axis,
   and the axis itself is one of the crossing strokes, so no position on centre is
   clean and moving off centre breaks the symmetry. Interrupting six paths per
   drawing would edit the artwork.

   So the label carries a halo, which is the standard cartographic remedy and the
   smallest one here. The ground behind both labels was sampled from the render
   before choosing the colour: 93% and 79% of it is a single flat tone one unit
   from --paper, so the halo is invisible and only the strokes are interrupted.
   Applied to these two labels only — everywhere else the drawings are already
   clean, and a site-wide halo would be a new visual language rather than a repair.
   ══════════════════════════════════════════════════════════════ */
.svg-label-shield{
  paint-order:stroke fill;
  stroke:var(--paper);
  stroke-width:5px;
  stroke-linejoin:round;
  stroke-linecap:round;
}

/* ══════════════════════════════════════════════════════════════
   19. V2.7 · THE MARK — the approved SYSTASYS identity, stated once,
       standing on the house's own material.

   The owner decision of 2026-08-20 authorises the existing figurative master
   and the exact Arabic signature for public use as an unregistered identity,
   and authorises no redraw. So both masters are served as files and placed,
   never re-pathed, re-spaced or reconstructed in markup, and the signature is
   real Arabic text so the glyphs join and shape as Arabic rather than as an
   image of Arabic.

   The masters are ivory and matte gold on carbon. Recolouring them for
   parchment was rejected: the gold opening carries meaning and a monochrome
   pass would flatten it.

   WHAT CHANGED IN V2.7, AND WHY.

   V2.6.3 gave the identity its own carbon plinth: a hard-edged black rectangle,
   bordered on four sides, inset inside the reading column, floating on cream,
   with the room's kicker orphaned above it. Every one of those is the signature
   of a pasted card, and the owner read the result as a collage — an image
   mounted onto an editorial page rather than a moment the page arrives at.

   The defect was never the identity. It was that the identity was MOUNTED.

   So the page stops mounting it and changes material instead. The whole closing
   room becomes carbon, edge to edge, and the black is a COURSE in the page's
   masonry rather than a block sitting on it. The change of material happens
   exactly where this site always changes state — on a room boundary — and the
   joint is made with the house's own instruments: a gold hairline at the weight
   the mark already uses above its Arabic signature, and the page's own reading
   column continued as two ivory hairlines straight through the stone. The
   kicker sits ON the material, on the left column line, exactly where every
   kicker on this page sits. The figure keeps its masters and loses only its
   box: no background of its own, no border, no padding. The ground is the room.

   The carbon is the house's own `rgba(24,24,21,.982)` — the same ground as
   `#observes` at the top of this page — not the plinth's private #0B0B0B, so
   the page closes on the stone it opened with. Measured on the result: ivory on
   that ground is ~16:1 and the gold descriptor ~7.5:1.

   Two things were tried and rejected on the renders. A cream-to-carbon dissolve
   read as a photographic fade — it interpolates through a cold neutral grey
   that is off-palette here, and it is a tonal traverse the house has no
   precedent for. A raked perspective floor and scattered points inside the dark
   read as a starfield over a receding plane, which is a product-launch poster,
   and at 412 the plane was hard-cut by the footer into exactly the pasted
   rectangle this pass exists to remove. A tint between the two column lines was
   also rejected: it was above threshold, so the mark visibly sat inside a
   lighter rectangle, which is the card returning by the back door.

   One course, on the one page whose subject is the system, at the point where
   the room closes. Home and Cabinet are untouched: SYSTASYS stays a word there.
   The two masters keep their approved size relationship (wordmark 770 : emblem
   580 in the canonical cover, so emblem = 0.753 x wordmark) and their approved
   size — the field supplies the scale, so the mark does not need to grow.
   ══════════════════════════════════════════════════════════════ */

/* FIELD — the page changes material. The artifact is not ON the section;
   the section is the ground the artifact stands on. */
.room[data-species="field"]{
  /* the house's own carbon, as used by every .room--dark */
  --course-carbon:rgba(24,24,21,.982);
  /* the joint: --gold at the hairline weight the mark already uses for the
     rule above its Arabic signature — one instrument, two scales */
  --course-joint:rgba(181,142,79,.72);
  /* --light-rule: the hairline the house draws inside dark rooms */
  --course-column:rgba(251,248,241,.17);
  /* the page's own reading-column edge, resolved against the full-bleed room */
  --course-bay:calc(max(0px,(100% - var(--geo-reading))/2) + var(--geo-gutter));

  background-color:var(--course-carbon);
  /* the reading column, continued through the course as two hairlines. They are
     open top and bottom and the joints run past them to the page edges, so
     nothing in this section is enclosed on four sides. */
  background-image:
    linear-gradient(var(--course-column),var(--course-column)),
    linear-gradient(var(--course-column),var(--course-column));
  background-size:1px 100%,1px 100%;
  background-position:left var(--course-bay) top 0,right var(--course-bay) top 0;
  background-repeat:no-repeat;
  /* the joints must be a line BETWEEN the two materials, so the carbon is not
     allowed to paint under them */
  background-clip:padding-box;

  /* the two joints run to the page edges, so nothing is outlined */
  border-top:1px solid var(--course-joint);
  border-bottom:1px solid var(--course-joint);
  /* the house's own paper-to-carbon bleed, as on every .room--dark */
  box-shadow:0 -28px 96px rgba(24,24,21,.05),0 28px 96px rgba(24,24,21,.065);

  color:var(--chalk);
  /* a course, not a room: the plate cadence, not the chamber cadence */
  padding-block:clamp(55px,5.5vw,96px);
}

/* The column lines are only true where the reading column is actually a centred
   column. Nearer the page edges they would stop being structure and start being
   a frame, so below that width the course is plain stone. */
@media(max-width:77.99rem){
  .room[data-species="field"]{background-image:none}
}

/* the room's own rhythm, standing on the material */
.room[data-species="field"] .kicker{color:rgba(251,248,241,.62)}

/* The course carries the closing joint, so the footer must not draw a second
   rule one pixel below it. Where :has() is unsupported the only consequence is
   that faint second hairline. */
body:has([data-species="field"]) .footer{border-top-color:transparent}

.seal{
  --seal-ivory:#F2EFE6;
  --seal-gold:#C8A96A;
  --seal-w:clamp(216px,24vw,318px);
  display:grid;
  justify-items:center;
  /* no ground, no border, no padding: the room is the plinth now */
  background:none;
  border:0;
  padding:0;
  color:var(--seal-ivory);
  margin-top:clamp(var(--s4),5vw,var(--s6));
}
.seal__emblem{width:calc(var(--seal-w) * .753);height:auto}
.seal__wordmark{width:var(--seal-w);height:auto;margin-top:var(--s5)}
.seal__caption{display:block;text-align:center;margin-top:var(--s3)}
.seal__descriptor{
  display:block;
  font:500 var(--t-micro)/1.2 var(--mono);
  letter-spacing:.34em;
  text-indent:.34em;
  color:var(--seal-gold);
}
.seal__signature{
  display:block;
  width:calc(var(--seal-w) * .727);
  max-width:100%;
  margin:var(--s3) auto 0;
  padding-top:var(--s4);
  border-top:1px solid rgba(200,169,106,.5);
  font-family:"Noto Sans Arabic","Segoe UI","Tahoma","Arial Unicode MS",sans-serif;
  font-size:clamp(21px,2.2vw,27px);
  line-height:1.85;
  color:var(--seal-ivory);
}

@media(max-width:760px){
  .seal__wordmark{margin-top:var(--s4)}
}


/* ══════════════════════════════════════════════════════════════
   20. V2.6.5 · THE LANGUAGE CONTROL — reachable, native, answering.

   Hichem tested the frozen HEAD on a Samsung and reported the language
   toggle as not clickable. Reproduced, it was three faults wearing one coat.

   It was only in the footer: seven screens down on Home, seventeen on the
   Cabinet at 360px. A control you must fall the length of the page to reach
   is not a control. It now also sits in the topbar, on every route, above
   the fold.

   It gave no acknowledgement: tap highlight suppressed globally, and no
   :active or :focus-visible rule of its own. A tap that worked and a tap
   that did nothing looked the same. Both now answer.

   And it was a pair of buttons, which does not scale past two editions.

   V2.8: it is a native <details> disclosure over seven real routes. A <select>
   could only ever be a JS state toggle — the choice never reached the URL, so a
   browser that refuses localStorage lost it on the next navigation. Seven links
   put the choice in the address bar, where nothing can revoke it, and the
   platform's own disclosure keeps the control to one line and one tap without
   asking JavaScript for permission.
   ══════════════════════════════════════════════════════════════ */
.lang{position:relative;display:inline-flex;align-items:center;min-width:0}
.lang__select{
  display:inline-flex;align-items:center;white-space:nowrap;
  list-style:none;
  background-color:transparent;
  border:1px solid var(--rule);
  border-radius:0;
  color:var(--graphite);
  font:inherit;
  font-size:var(--t-micro);
  letter-spacing:.1em;
  line-height:1;
  padding:7px 26px 7px 10px;
  min-height:34px;
  cursor:pointer;
  touch-action:manipulation;
  /* A hairline chevron, inline, to match the rules the rest of the page draws.
     Filled triangles read heavier than anything else in the chrome. */
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='9' height='6' viewBox='0 0 9 6'%3E%3Cpath d='M1 1.2 4.5 4.6 8 1.2' fill='none' stroke='%23555148' stroke-width='1.1' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-position:calc(100% - 10px) 50%;
  background-size:9px 6px;
  background-repeat:no-repeat;
  transition:color .18s ease,border-color .18s ease,background-color .18s ease;
}
/* A summary draws a disclosure triangle on every engine. Three arms, because
   no single one of them covers Blink, WebKit and Gecko together. */
.lang__select::-webkit-details-marker{display:none}
.lang__select::marker{content:""}
.lang__select:focus-visible{outline:2px solid var(--oxide);outline-offset:2px;color:var(--ink)}
.lang__select:active{background-color:rgba(24,24,21,.07);color:var(--ink)}

/* Open is a state the reader has to be able to see on a borderless control. */
.lang[open]>.lang__select{
  border-color:var(--rule);color:var(--ink);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='9' height='6' viewBox='0 0 9 6'%3E%3Cpath d='M1 4.8 4.5 1.4 8 4.8' fill='none' stroke='%23555148' stroke-width='1.1' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

/* The seven editions. A column, not a row: seven endonyms across five scripts
   have no common width, and a row of them is a debug toolbar, not a control.

   The inset is PHYSICAL, and that is not an oversight. The masthead carries
   flex-direction:row-reverse in Arabic, so the control hugs the physical right
   edge in both directions — while inset-inline-end resolves to the LEFT in RTL
   and hung the menu 17px off the right of the screen at 390 and 412. A logical
   property cannot express "the edge nearer the viewport border" when the row it
   sits in has already reversed itself. Measured in both directions at 1440,
   412, 390 and 360. */
.lang__menu{
  position:absolute;top:calc(100% + 6px);right:0;z-index:60;
  max-width:calc(100vw - 24px);
  display:flex;flex-direction:column;min-width:max-content;
  padding-block:4px;
  background:var(--paper);
  border:1px solid var(--rule);
  box-shadow:0 12px 32px -20px rgba(24,24,21,.55);
}
.lang__menu a{
  display:flex;align-items:center;
  min-height:38px;padding-inline:18px;
  font-size:var(--t-micro);letter-spacing:.04em;line-height:1;
  text-transform:none;text-decoration:none;
  color:var(--graphite);
  transition:color .18s ease,background-color .18s ease;
}
/* The edition being read is marked, not removed: a control that hides where you
   already are cannot tell you where you are. */
.lang__menu a[aria-current]{color:var(--ink);box-shadow:inset 2px 0 var(--gold)}
.lang__menu a:focus-visible{outline:2px solid var(--oxide);outline-offset:-2px;color:var(--ink)}
.lang__menu a:active{background-color:rgba(24,24,21,.07);color:var(--ink)}

/* The edition load-failure note and its live region are gone, with the runtime
   switcher that was their only producer. A pre-rendered edition cannot fail
   halfway: either the URL served it, or the navigation did not happen. */

/* The topbar copy is uppercase mono; the code reads as a sibling of SYSTASYS. */
/* Endonyms, not codes: an option reading "AR" but tagged lang="ar" is announced
   as Arabic letters by a screen reader, which is a lie about its own content.
   The names are therefore written in their own script — and uppercase is dropped,
   because it would render "Français" as "FRANÇAIS" and is inert on the other four. */
.lang--top .lang__select{border-color:transparent;padding-inline:6px 26px;letter-spacing:.04em;text-transform:none}.lang--top .lang__select:focus-visible{border-color:var(--rule)}

/* Every other control the finger meets now answers it too. */
.prefs__toggle:active,.surface-dock a:active,.topbar__link:active,.quiet-button:active{background-color:rgba(24,24,21,.07)}
.room--dark .quiet-button:active{background-color:rgba(251,248,241,.09)}

/* Section 20 is appended after the earlier breakpoint blocks and a media query
   carries no extra specificity, so the finger-sized target has to be stated
   here, last, or source order quietly takes it back to 34px. */
@media (max-width:760px){
  .lang__select{min-height:44px;padding-block:0}
  .lang--top .lang__select{padding-inline:10px 26px}
  .lang__menu a{min-height:44px}
}

/* ══════════════════════════════════════════════════════════════
   21. V2.6.5 · THE ARABIC EDITION READS RIGHT TO LEFT.

   Direction is set on the document, so the layout mirrors by itself: the grid,
   the rules, the alignment. Measured at 1440 and 412, nothing overflows. Two
   kinds of content must refuse to mirror, for two different reasons.

   The archival plates reproduce public artifacts unchanged. That is the whole
   claim they make. A JSON receipt or a checklist re-flowed right to left is no
   longer the file it says it is, so the reproduced body keeps its own direction
   whatever the reader's language. The labels this site wraps around it are
   translated, so they are handed back to the page direction.

   Proper nouns are the second. In a right-to-left paragraph a neutral character
   at the edge of a Latin run takes the paragraph's direction, which is why
   "Sendable?" was drawn "?Sendable" — the question mark is part of the name.
   These get their own base direction while staying at the start of the line,
   which is the right edge.
   ══════════════════════════════════════════════════════════════ */
[dir="rtl"] .plate__body,
[dir="rtl"] .plate__doc,
[dir="rtl"] .plate__code,
[dir="rtl"] .plate__ascii,
[dir="rtl"] pre,
[dir="rtl"] code,
[dir="rtl"] .plate__origin{direction:ltr;text-align:left}

/* The labels this site wraps around a reproduced artifact are translated, so
   they read right to left — but they stay aligned with the block they introduce
   rather than drifting to the far edge away from it. */
[dir="rtl"] .plate__body [data-t],
[dir="rtl"] .plate__doc [data-t]{direction:rtl;text-align:left}

/* A Latin brand string inside Arabic prose is a foreign run, and the trailing
   "?" of "Sendable?" is bidi-NEUTRAL: without an isolate it takes the direction
   of the paragraph and is drawn on the left, so the mark reads "?Sendable".
   Measured with a DOM Range over the text node on /ar: 'S' at x=1126, '?' at
   x=1115. .now-mark was the one standalone placement missing from this list.

   This only reaches brand strings that are their own element. The ones embedded
   inside a translated sentence cannot be selected by CSS at all; those are
   isolated at build time with U+2066/U+2069 by tools/build-static-editions.mjs. */
[dir="rtl"] .door__name,
[dir="rtl"] .now-mark,
[dir="rtl"] .topbar__brand,
[dir="rtl"] .topbar__link,
[dir="rtl"] .lineage a,
[dir="rtl"] .cite a{direction:ltr;unicode-bidi:isolate}

/* This rule exists to protect the two pure-Latin URL exits, and it was catching
   the translated ones too — forcing an Arabic call to action to lay out
   left-to-right, which put its arrow on the far side of the phrase. Match only
   the exits that neither carry nor contain a translation key: those are the URLs. */
[dir="rtl"] .door__exit:not([data-t]):not(:has([data-t])){direction:ltr;unicode-bidi:isolate}
[dir="rtl"] .door__name{text-align:right}

/* Arabic sits on a taller body than Latin at the same size, and its ascenders
   and descenders need the room. This is leading, not a redesign. */
[dir="rtl"] body{line-height:1.72}
[dir="rtl"] .body-copy,[dir="rtl"] .lead,[dir="rtl"] .door__line{line-height:1.85}
[dir="rtl"] .statement,[dir="rtl"] .hero__claim,[dir="rtl"] .hero__title{line-height:1.24;letter-spacing:0}
[dir="rtl"] .kicker,[dir="rtl"] .meta,[dir="rtl"] .tag{letter-spacing:.06em}

/* ══════════════════════════════════════════════════════════════
   22. V2.6.5 · COMPOSITION FIXES THAT BELONG TO EVERY EDITION.

   Found while calibrating the seven editions, but none of these is a language
   matter — they are defects in the Latin baseline that the comparison exposed.

   The arrow that lost its space: .door__exit becomes inline-flex at the 44px
   touch breakpoint, and flex discards whitespace-only text nodes. The markup is
   <span data-t>Open the gate</span> → with an ordinary space between, so every
   primary call to action rendered "OPEN THE GATE→" on mobile. Proven by the
   control case in the same capture: arrows that live INSIDE the translated
   string kept their space. .7em restores the Cascadia Mono word space plus the
   .1em tracking that was riding on it.

   The underline that detached: the same 44px conversion centres the label in a
   44px box while border-bottom keeps painting at the bottom of that box, so the
   rule sat some 17-21px under the glyphs and read as a stray line. Moving it to
   text-decoration reattaches it to the text and keeps the target size.

   Widows: three of four section headings ended on a single word. These are
   two-clause headlines whose whole device is the parallel between the clauses.
   .hero__claim is deliberately NOT balanced — its three descending lines and
   .48em indent are an authored staircase, and balancing would flatten it.
   ══════════════════════════════════════════════════════════════ */
.door__exit{column-gap:.7em}

.statement,.statement--study,.door__name,.law-moment__line{text-wrap:balance}
.body-copy,.door__line,.plate__caption,.legend dd,.aperture__list li,
.aperture__legend-lead,.cite__q,.agent-card dd{text-wrap:pretty}

/* the only running text on the site with no measure, at 111 characters —
   40em is the value its own sibling .aperture__legend-lead already carries */
.legend dd{max-width:40em}

/* a proper-noun link label is one unit; it was breaking before its arrow */
.cite__who a,.cite a{white-space:nowrap}

@media (max-width:760px){
  .door__exit--primary,.quiet-link,.laws__exit a,.law-moment .quiet-link{
    border-bottom-color:transparent;
    text-decoration:underline;
    text-decoration-color:var(--rule);
    text-decoration-thickness:1px;
    text-underline-offset:4px;
  }
  /* the desktop hero separates its two sentences with a tonal step AND a .48em
     indent; the indent is dropped here, so the step needs air to survive */
  .hero__claim span:last-child{margin-top:.28em;display:inline-block}
}
@media (max-width:430px){
  .hall__routes a,.topbar__brand,.topbar__link,.lineage a{
    border-bottom-color:transparent;
    text-decoration:underline;
    text-decoration-color:var(--rule);
    text-decoration-thickness:1px;
    text-underline-offset:4px;
  }
}


/* ── V2.6.5 · RTL COMPOSITION, THE PARTS CSS CANNOT MIRROR BY ITSELF ────────
   Direction mirrors the box model. It does not mirror a background image, and
   it does not know that a piece of Latin is a brand rather than a sentence. */

/* The chevron is painted with a physical background-position, so it stayed at
   the physical right edge — which is the inline START in Arabic — while the
   padding reserved its clearance at the other end. It was drawn straight
   through the label. */
[dir="rtl"] .lang__select{
  background-position:10px 50%;
  padding-inline:22px 6px;
}
[dir="rtl"] .lang__menu a[aria-current]{box-shadow:inset -2px 0 var(--gold)}

/* The approved descriptor is a Latin brand string inside the identity plate, not
   prose. text-indent runs toward the inline start, so in Arabic the compensation
   for the trailing letter-space pushed the wrong way and the centred line sat
   off-centre by twice the tracking. It is an invariant object: give it its own
   direction and the indent lands where it was designed to. */
[dir="rtl"] .seal__descriptor{direction:ltr}


/* ── V2.6.5 · THE TOPBAR AT 400% ZOOM ──────────────────────────────────────
   Removing the endonym truncation cap fixed the labels and broke reflow: at
   1280 @ 400% — 320 CSS px, the WCAG 1.4.10 reflow target — brand + route link
   + a full-width select no longer fit on one row, and the select ran to 335px
   in a 320px viewport.

   Truncating again is not available: a language control that says "Engl…" is
   worse than one that wraps. Hiding the route link is not available either,
   even though the dock repeats it — the topbar is the only reachable route out
   on a page that may be fourteen thousand pixels long.

   So the row wraps. Nothing is hidden, nothing is abbreviated, and the control
   keeps its 44px target. Only below 380px, where the alternative is a scrollbar. */
@media (max-width:380px){
  .topbar__inner{flex-wrap:wrap;row-gap:6px}
  .lang--top{margin-inline-start:auto}
}

/* ── V2.6.5 · HOVER IS A CAPABILITY, NOT AN ASSUMPTION ─────────────────────
   25 :hover rules existed and not one capability query. On a touch device the
   last-tapped control kept its hover skin permanently — measured still matching
   :hover after scrolling 400px away. These are the hover arms only: every
   :focus-visible and every selected-state arm stayed where it was, because they
   shared selector lists with these and moving them would have taken keyboard
   focus and the active states with them. */
@media (hover: hover) and (pointer: fine){
  .quiet-link--light:hover{color:var(--gold);border-bottom-color:var(--gold)}
  .room--dark .quiet-link:hover{color:var(--gold);border-bottom-color:var(--gold)}
  .hall__routes a:hover b{color:var(--ink)}
  .hall__routes a:hover{border-bottom-color:var(--oxide)}
  .door__exit:hover{color:var(--oxide-text);border-bottom-color:var(--oxide)}
  .cite__who a:hover{border-bottom-color:var(--oxide)}
  .lineage a:hover{color:var(--oxide-text);border-bottom-color:var(--oxide)}
  .spectra-loop li:hover{background:none;box-shadow:none}
  .spectra-loop li>button:hover{background:rgba(251,248,241,.045);box-shadow:inset 2px 0 var(--gold)}
  [dir="rtl"] .spectra-loop li>button:hover{box-shadow:inset -2px 0 var(--gold)}
  .spectra-loop li>button:hover b{color:var(--gold)}
  .surface-dock>a:hover{background:rgba(24,24,21,.045);color:var(--ink)}
  .prefs__toggle:hover{color:var(--ink)}
  .lang__select:hover{color:var(--ink);border-color:rgba(24,24,21,.28)}
  .lang--top .lang__select:hover{border-color:var(--rule)}
  .lang__menu a:hover{color:var(--ink);background-color:rgba(24,24,21,.05)}
}

/* ── V2.6.5 · THE CONSTELLATION NODES ───────────────────────────────────────
   They are an SVG <g role="link" tabindex="0">, so Chromium's own ring reaches
   them through :focus and stayed painted after a mouse click and after a touch
   tap. The keyboard ring is kept and made the house's own; the pointer ring is
   the one that goes. Not a blanket outline:none. */
.systasys-constellation .hero-node:focus{outline:none}
.systasys-constellation .hero-node:focus-visible{outline:2px solid var(--oxide);outline-offset:6px}

/* The visible mark is 14-16px because that is the drawing. The target is not
   the drawing: a transparent 76x76 rect in the same SVG user space clears 44px
   at every rendered width without changing a single visible pixel. */
.systasys-constellation .hero-node rect.hero-node__hit{fill:none;stroke:none;transform:none;pointer-events:all}

/* 23. STATE HYGIENE — a control that cannot act must not look actionable.
   The motion toggle is force-disabled under prefers-reduced-motion, but kept
   the pointer cursor, so it still invited a press that could do nothing. */
button[disabled],
select[disabled]{cursor:default}
/* off must also LOOK off: the toggle read as live while it could not act */
.prefs__toggle[disabled]{opacity:.45}

/* 24. LANGUAGE CONTROL — PHYSICAL_STABLE (ASSO ruling, 2026-08-20).
   The language selector is global chrome, not directional page content: the
   control the reader just touched must not teleport to the far side of the bar
   because the document direction changed. It was moving 281px on a 412px
   viewport.

   This pins the topbar's LAYOUT, not its text. `direction` stays rtl, so البهو
   still renders right-to-left and every endonym keeps its own script — this is
   NOT the topbar forced to LTR. Only the physical order of the chrome is held.

   The auto margin has to be repinned as well: the base rule is
   margin-inline-end:auto, which resolves to the LEFT under rtl and, in a
   reversed row, flung the state word away from the brand and against the
   wayfinding pair. */
[dir="rtl"] .topbar__inner{flex-direction:row-reverse}
[dir="rtl"] .topbar__state{margin-inline:auto 0}

/* The footer carries the same meta-control and mirrored the same way: measured
   264px of travel at 412px and 664px at 1440px.

   The topbar's row-reverse does NOT work here — .footer__inner is a grid, and
   flex-direction is inert on a grid (measured: 264px of travel remained). An
   `order` swap only reaches 244px/101px because the two grid tracks are sized
   independently. Pinning the two CELLS is the only technique that holds, so
   `direction` is held on the container and immediately restored on every
   text-bearing child: the Arabic label and every endonym still compute
   direction:rtl. The row's placement is pinned; its text is not. */
[dir="rtl"] .footer__inner{direction:ltr}
[dir="rtl"] .footer__identity,
[dir="rtl"] .prefs__group{direction:rtl}

/* 25. RTL ARMS THAT NO LOGICAL PROPERTY CAN EXPRESS.
   box-shadow offsets are physical by specification — there is no logical form —
   so the gold selection bar needs an explicit mirror. Without it the marker sits
   on the far side from where the Arabic eye enters the control. */
[dir="rtl"] .region-list button[aria-checked="true"],
[dir="rtl"] .agent-tabs button[aria-checked="true"],
[dir="rtl"] .spectra-loop li>button[aria-checked="true"]{box-shadow:inset -2px 0 var(--gold)}

/* These arrows are DIRECTIONAL: they mean "proceeds to", so they follow the
   reading direction. Each sits alone in its own <i>, so nothing else flips.
   The exit links keep their glyph — those are Latin URL, brand and citation
   runs, which are not directional and must not mirror. */
[dir="rtl"] .region-laws i{transform:scaleX(-1)}

/* 26. BASELINE REGISTRATION — the reference edition.
   These are 2-6px misregistrations in the English baseline. They matter more
   than their size: every other edition is calibrated against this one, so a
   drift here is inherited seven times over. All are block-direction geometry,
   identical in every edition and in both directions. */

/* SYSTASYS arrow-link sat 2px above the wordmark and the language control — a
   quarter of the 8px cap height, in a row of three items on one baseline. */
.topbar__link{padding-top:4px}

/* .room__aside kept a padding-top:7px calibrated for an 11px aside after the
   aside was raised to 12px, leaving the two ends of the same rule-less row 6px
   out of register on every room head on all three pages. Guarded: below 761px
   the row stacks and the compensation would collide. */
@media (min-width:761px){
  .room__aside{padding-top:0;line-height:1.35}
  .room__aside > .tag{margin-top:-6px}
}

/* Two parallel hairlines 21px apart with dead space between them, the lower one
   twice as dark: the node list drew a closing rule and .readout drew its own. */
.home-map__inspector .node-list button:last-child{border-bottom:0}

/* 27. STATE LIFECYCLE — the states that were never drawn.

   PRESS: on a touch screen there is no hover to acknowledge a finger, so the
   press moment was invisible on every species. Coarse-pointer only. Selected
   chips are excluded — they carry an ink ground already, and washing it drops
   their own label to 1.24:1. */
@media (pointer:coarse){
  .segmented [role="radio"]:not([aria-checked="true"]):active,
  .judgment__tabs [role="radio"]:not([aria-checked="true"]):active,
  .node-list [role="radio"]:active,.agent-tabs [role="radio"]:active,
  .region-list [role="radio"]:active,.corpus-tabs [role="tab"]:active,
  summary:active,.door__exit:active,.quiet-link:active,
  .topbar__brand:active,.hero__routes a:active{background-color:rgba(24,24,21,.07)}
  .room--dark summary:active,.gate-controls button:active,
  .spectra-loop li>button:active{background-color:rgba(251,248,241,.09)}
}


/* ══════════════════════════════════════════════════════════════
   23. V2.7 · THE THRESHOLD — connective tissue at the page openings.

   The house was beautiful and the openings had no joint. The topbar already
   STATED the relationship in words — Hichem Benali · the room you are in ·
   SYSTASYS ↗ — but stated it in a mute material that belonged to nothing else
   on the page, and the page itself was the one box on the site with no entry
   edge, while every .room has one.

   Two motifs. That is the whole system. Both are geometry, both are drawn from
   vocabulary the house already owns, and neither adds a word, an element or a
   translation key.

   M1 · THE THRESHOLD RUN
        One 1px hairline at the foot of the chrome band, inset to the FRAME
        datum — the same left and right edges as the kicker, the claim and the
        hero drawing below it. It is the rhyme of
            .room{border-top:1px solid var(--rule)}
        the house's own "you are crossing into a room" edge, finally applied to
        the page itself. Identical on all three routes, so every route is
        entered across the same line, and for the first time the chrome and the
        content share a datum.

   M2 · THE TWO ANCHORS
        The diagrams' own notation, at micro scale, on the labels that already
        carry the relationship:
            .core   fill var(--ink), stroke var(--gold)   -> the person, the origin
            .node   fill var(--paper), stroke var(--ink)  -> the way out
        Two marks standing on the threshold, at the start of the words they
        belong to, with the room you are in named between them on the same axis.
        `.core` is already on all three routes inside the hero drawings, so this
        is a quotation, not an invention, and the gold is the one micro-accent
        at an opening — on the identity, where the house already puts it.

   Rejected on the renders, and named so they are not tried again: an inline
   open square before SYSTASYS read as an unchecked checkbox in a chrome bar,
   and an inline filled square placed BETWEEN the brand and the room name made
   the one device charged with joining them visually separate them. Re-weighting
   .room{border-top} across every seam of every page was a substrate restyle,
   not a joint at an opening. Register ticks descending from every seam put
   twenty corner marks down a single page, which is ornament.

   Anchoring. .topbar__inner is the topbar's only in-flow child and is a flex
   row with align-items:center, so the topbar's own 50% resolves to the same
   absolute y as every item's cross-axis centre at every width — measured
   identical at 1440, 900, 760, 560, 480, 430, 412 and 360, and the row never
   wraps. That is why one constant offset puts the run and both marks on the
   same line without a magic number per breakpoint, and why the marks stay on
   the line when the labels grow to a 44px touch target on mobile.
   ══════════════════════════════════════════════════════════════ */
.topbar{--thr-drop:22px}

/* M1 · the threshold run */
.topbar::after{
  content:"";
  position:absolute;
  inset-inline:max(
    var(--geo-gutter),
    calc((100% - var(--geo-frame)) / 2 + var(--geo-gutter))
  );
  top:50%;
  margin-top:var(--thr-drop);
  height:1px;
  background:var(--rule);
  pointer-events:none;
}

/* M2 · the two anchors */
.topbar__brand,
.topbar__link{position:relative}

.topbar__brand::after,
.topbar__link::after{
  content:"";
  position:absolute;
  inset-inline-start:0;
  top:50%;
  margin-top:calc(var(--thr-drop) - 3px);
  width:7px;
  height:7px;
  box-sizing:border-box;
  border:1px solid var(--ink);
  background:var(--paper);
  pointer-events:none;
}
/* the origin is the core: ink fill, gold stroke — .core, at 7px */
.topbar__brand::after{background:var(--ink);border-color:var(--gold)}
