/* ============================================================================
   DJ VON FRANK — SITE
   Components. Every value comes from tokens.css.

   BRAND OS v3.0 · ATLAS. Repointed 2026-08-13.

   Raw hex below this line: SEVEN, all of them inside @media print, all of
   them one-ink reproduction values rather than palette values. The Brand OS
   is explicit that the black master is "100K only" and that print loses the
   surface, the glass and the blur; Midnight Green is not black, so printing
   it as a token would be the wrong claim. Everything that renders on a
   screen is a token. There are no `var(--x, #hex)` fallbacks anywhere in
   this file — a fallback is a second copy of the palette that only ever
   fires when the first copy is missing, which is the one moment it would
   paint the previous brand.

   THE RHYTHM RULE — light-first, dark-punctuated:
   Paper White is true white now and the page beneath the cards is --page, a
   5% Surface Steel tint, so a white sheet has something to sit on. A page
   runs light and uses a dark band to mark a change of subject, roughly one
   band per two screens of scroll. Two dark bands in a row makes the second
   one furniture instead of punctuation. This stylesheet obeys its own rule.

   THE SIX:
     Midnight Green #00272C  ground + ink       white on it 15.8:1
     True North     #FF6B1C  the needle         on Midnight 5.6:1 / on white 2.8:1 FAILS
                                                 except .kflag + header CTA, ruled 2026-08-27
     Paper White    #FFFFFF  card, knockout     on Midnight 15.8:1
     Landfall       #09E85E  shipped / passing  on Midnight 9.6:1 / on white 1.7:1 FAILS
     Meridian       #279AF1  in progress / info on Midnight 5.3:1 / on white 3.0:1 large only
                                                 body links on --page 2.79:1, ruled 2026-08-27
     Surface Steel  #245D63  link, eyebrow      on white 7.4:1 / on Midnight 2.1:1 FAILS
   Ratios recomputed 2026-08-13 against these exact values, not carried over.
   ========================================================================= */

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; scroll-padding-top: calc(var(--hd-h) + 16px); }
body {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: 1.62;
  color: var(--ink);
  background: var(--page);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
img, svg, video { max-width: 100%; height: auto; display: block; }
/* Links are Meridian on light grounds. The 2026-08-25 ruling recorded 3.0:1,
   which is Meridian on pure white; body copy sits on --page, where it really
   measures 2.79:1. Re-ruled on the true number 2026-08-27: links stay
   Meridian, and tokens.css now publishes 2.79:1 instead of the law this rule
   used to contradict. The underline stays one pixel, three pixels clear of
   the baseline, and it is what carries the link
   where the color alone would not. Hover darkens to the ink. On dark grounds
   links are True North instead: see .band-dark a. */
a { color: var(--beacon); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--ink); }
hr { border: 0; border-top: 1px solid var(--hairline); margin: var(--section) 0; }

/* The focus ring is the one element never restyled per component: a 2px
   Surface Steel ring, never a glow. Steel measures 2.1:1 on Midnight Green
   and would vanish there, so on dark grounds the ring is True North (5.6:1)
   — the one colour legal on both sides of that line. */
#main:focus { outline: none; }
:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; border-radius: 3px; }
.hd :focus-visible,
.splith :focus-visible,
.proof :focus-visible,
.phero :focus-visible,
.band-dark :focus-visible,
.ft :focus-visible,
.code-pre:focus-visible { outline-color: var(--spark); }
.skip {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--ink); color: var(--paper); padding: 12px 18px; border-radius: 0 0 var(--r) 0;
}
.skip:focus { left: 0; }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---- LAYOUT -------------------------------------------------------------- */
.wrap { max-width: var(--wrap); margin-inline: auto; padding-inline: var(--gutter); }
.wrap--wide { max-width: var(--wrap-wide); }
/* .wrap--measured was called .wrap--narrow, and the rename is the point. It used to
   shrink the whole SECTION to 780px and centre it, which left its headings,
   notes and buttons inset from every other section on the site: a page
   alternating the two containers looked like the layout kept losing its
   nerve. That behaviour was removed, but the name stayed, and a class called
   "narrow" that narrows nothing is a trap for the next person reading the
   markup.

   2026-08-26, the caps came off entirely. The child caps (lists, notes and
   tables at --measure) were the last holders of the old left-pinned pattern:
   a 66ch block against the left rail of an 1180px wrap, which DJ called the
   side-margin problem across seven pages. The measure now lives where the
   writing articles put it, on reading COLUMNS (.art-col and the resources
   article grid), and everything else fills its wrap. The class is kept as a
   no-op so 34 uses of it across the markup stay valid; treat it as a plain
   .wrap and retire it from new markup. */
.wrap--measured { max-width: var(--wrap); }
.section { padding-block: var(--section); }
.section--tight { padding-block: calc(var(--section) * .55); }
.stack > * + * { margin-top: 1.1em; }
.grid { display: grid; gap: 18px; grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr)); }
/* .grid--2 means two columns. It used to say "as many 340px tracks as fit",
   which inside the 1092px content column resolves to THREE, so every four-card
   row on the site rendered 3+1 with the fourth card stranded beside two empty
   cells. Home's Selected Work and the brains index, the two rows whose whole
   job is to prove the work, were the worst of it. Declared by intended column
   count now, not by track minimum (2026-08-27). */
.grid--2 { grid-template-columns: minmax(0, 1fr); }
@media (min-width: 720px) { .grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.grid--tight { gap: 12px; }

/* ---- TYPE ---------------------------------------------------------------- */
h1, h2, h3, h4 { margin: 0 0 .5em; line-height: 1.14; font-family: var(--font-display); font-weight: 700; letter-spacing: -.018em; }
h1, h2 { font-weight: 800; }
h1 { font-size: var(--step-4); }
h2 { font-size: var(--step-3); }
h3 { font-size: var(--step-1); }
h4 { font-size: var(--step-0); }
/* THE MEASURE MOVED FROM THE PARAGRAPH TO THE CONTAINER (2026-08-26).
   Every <p> used to cap itself at 66ch, which inside an 1180px wrap pinned
   a 600px text block to the left rail and left the right half of the page
   empty. DJ called it the side-margin problem on seven pages running; the
   writing articles were fixed first by giving the COLUMN the measure
   (.art-col, 760px, centered) and letting paragraphs fill it, and that is
   now the sitewide architecture: containers own width, paragraphs fill
   containers. Long-form still reads at a book measure because long-form
   lives in columns; everything else fills the wrap it sits in. */
p { margin: 0 0 1.1em; }

.display {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: var(--step-5);
  line-height: 1.02;
  letter-spacing: -.02em;
}
.headline { font-size: var(--step-3); letter-spacing: -.022em; }
/* Eyebrows sit above, never below, and on a light ground they are Surface
   Steel: 7.4:1 on white. This used to be the bronze family, which v3 removes
   entirely. On dark the eyebrow is True North — see .band-dark .kicker. */
.kicker {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--primary);
  margin: 0 0 14px;
}
.lede { font-size: var(--step-1); line-height: 1.5; color: var(--muted); }
/* THE FULL-WIDTH LEDE (owner's ruling, 2026-08-25): section ledes run the
   width of their headline rather than stopping at the measure. It was thirty
   inline style="max-width:none" declarations; now it is one class, so the
   ruling has a name and a single off-switch. .mw-none is the generic escape
   for any other element the ruling reaches. Article BODY prose is the ruled
   exception and keeps its measure (see .art-col in writing.css). */
.lede--full, .mw-none { max-width: none; }
.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.tight { max-width: 54ch; }

/* ---- HEADER — dark glass, the kit's signature chrome ---------------------- */
/* Sticky chrome takes --blur-1; overlays take --blur-2. Two grades, because a
   third makes depth ambiguous. Where blur is unsupported the glass falls back
   to solid Midnight Green, not to a thinner blur. */
.hd {
  position: sticky; top: 0; z-index: 100;
  background: var(--glass-d);
  backdrop-filter: var(--blur-1); -webkit-backdrop-filter: var(--blur-1);
  border-bottom: 1px solid var(--hairline-d);
  color: var(--paper);
}
@supports not (backdrop-filter: blur(1px)) { .hd { background: var(--ground); } }
.hd-in {
  max-width: var(--wrap-wide); margin-inline: auto; padding: 14px var(--gutter); min-height: var(--hd-h);
  display: flex; align-items: center; gap: 28px;
}
.hd-mark { display: flex; align-items: center; gap: 11px; text-decoration: none; color: var(--paper); flex: 0 0 auto; }
.hd-mark svg { width: 30px; height: 30px; }
.hd-mark b { font-family: var(--font-display); font-weight: 800; font-size: 1.06rem; letter-spacing: -.02em; }
.hd nav { margin-left: auto; display: flex; gap: 4px; align-items: center; }
.hd nav a {
  font-size: var(--step--1); font-weight: 500; color: var(--dim-d);
  text-decoration: none; padding: 9px 13px; border-radius: var(--r-sm);
  transition: color var(--t-hover) var(--ease), background var(--t-hover) var(--ease);
}
.hd nav a:hover { color: var(--paper); background: var(--hairline-d); }
.hd nav a[aria-current="page"] { color: var(--paper); font-weight: 600; }
/* One True North button per view; the label on a True North fill is Midnight
   Green, 5.6:1. Paper White on it is 2.8:1 and is never used. Buttons are
   --pill in v3, and the hit target never drops below 44px. */
.hd-cta {
  font-size: var(--step--1); font-weight: 600; padding: 9px 17px !important;
  background: var(--spark); color: var(--ink) !important; border-radius: var(--pill);
}
.hd-cta:hover { background: var(--paper); }
.hd-burger {
  display: none; margin-left: auto; width: 42px; height: 42px; border-radius: var(--r-sm);
  border: 1px solid var(--hairline-d); background: transparent; cursor: pointer;
  align-items: center; justify-content: center; color: var(--paper);
}
@media (max-width: 900px) {
  .hd nav { display: none; }
  .hd nav.open {
    display: flex; flex-direction: column; align-items: stretch; gap: 2px;
    position: absolute; left: 0; right: 0; top: 100%;
    background: var(--ground); border-bottom: 1px solid var(--hairline-d);
    padding: 12px var(--gutter) 20px;
  }
  .hd nav.open a { padding: 13px 4px; font-size: var(--step-0); }
  .hd nav.open .hd-cta { text-align: center; margin-top: 8px; }
  .hd-burger { display: flex; }
}

/* ---- THE SPLIT HERO — the signature device ------------------------------- */
/* THE SURFACE lives behind it on the homepage: a canvas layer under a soft
   darkening scrim so the split copy keeps its contrast over the brightest
   chrome bands. No WebGL, no canvas: the --grad-ground flat fallback below
   simply shows and nothing structural is lost. */
.splith { background: var(--grad-ground); color: var(--paper); position: relative; overflow: hidden; }
.splith-fx { position: absolute; inset: 0; z-index: 0; }
.splith-fx canvas { width: 100%; height: 100%; display: block; }
.splith-fx::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--ink) 34%, transparent),
    color-mix(in srgb, var(--ink) 68%, transparent));
}
.splith-in, .splith > .wrap { position: relative; z-index: 1; }
.splith-in {
  max-width: var(--wrap-wide); margin-inline: auto; padding: clamp(48px, 7vw, 92px) var(--gutter) 0;
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: end; gap: clamp(20px, 4vw, 56px);
}
.splith-half { padding-bottom: clamp(40px, 6vw, 76px); text-decoration: none; color: inherit; display: block; }
.splith-half:last-of-type { text-align: right; }
.splith-half .kicker { color: var(--spark); }
.splith-half h2 {
  font-family: var(--font-display); font-weight: 800; font-size: var(--step-3);
  line-height: 1.08; letter-spacing: -.02em; color: var(--paper); margin-bottom: .35em;
  max-width: 15ch;
}
.splith-half:last-of-type h2 { margin-left: auto; }
.splith-half p { color: var(--dim-d); font-size: var(--step--1); max-width: 30ch; margin: 0; }
.splith-half:last-of-type p { margin-left: auto; }
.splith-half .go {
  display: inline-flex; align-items: center; gap: 7px; margin-top: 18px;
  font-family: var(--font-mono); font-size: var(--step--1); font-weight: 600;
  letter-spacing: .04em; color: var(--spark);
  transition: gap var(--t-hover) var(--ease);
}
/* Hover moves the affordance, not the whole half: the arrow's gap opens and
   nothing washes colour across the block. */
.splith-half:hover .go { gap: 13px; }

.splith-portrait { position: relative; align-self: end; width: clamp(180px, 22vw, 300px); }
.splith-portrait img,
.splith-portrait .ph-figure { width: 100%; display: block; }
.splith-name {
  position: absolute; left: 50%; transform: translateX(-50%); bottom: -1px;
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .22em;
  text-transform: uppercase; color: var(--dim-d); white-space: nowrap;
  background: var(--ink); padding: 0 12px;
}
.splith-in { position: relative; z-index: 1; }

@media (max-width: 860px) {
  .splith-in { grid-template-columns: 1fr; text-align: center; padding-top: 36px; }
  .splith-half, .splith-half:last-of-type { text-align: center; padding-bottom: 0; }
  .splith-half h2, .splith-half p { max-width: none; margin-inline: auto; }
  .splith-portrait { width: min(220px, 60vw); margin: 24px auto 0; order: -1; }
  .splith-half + .splith-portrait { order: 0; }
}

/* ---- PROOF STRIP — three to five figures, above the fold ----------------- */
/* Two looks thin, six looks padded. The figures are Paper White on Midnight
   Green at 15.8:1 and tabular, always — a column of numbers that ripples is
   a column of numbers nobody reads. */
.proof { background: var(--ink-deep); color: var(--paper); }
.proof-in {
  max-width: var(--wrap-wide); margin-inline: auto; padding: 30px var(--gutter);
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr)); gap: 26px;
}
.proof-n {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: var(--step-3); font-weight: 600; line-height: 1; color: var(--paper);
  letter-spacing: -.02em;
}
.proof-l { font-size: var(--step--1); color: var(--dim-d); margin-top: 7px; line-height: 1.35; }

/* ---- DARK BAND — the rhythm rule ---------------------------------------- */
.band-dark { background: var(--grad-ground); color: var(--paper); }
.band-dark h2, .band-dark h3, .band-dark .display { color: var(--paper); }
.band-dark .kicker { color: var(--spark); }
.band-dark p, .band-dark .lede { color: var(--dim-d); }
/* Links on a dark ground are True North: the owner's 2026-08-25 ruling,
   the pair of the Meridian-on-light rule above. 5.6:1 on Midnight, so this
   half of the pair clears its ratio outright. Hover lifts to Paper. */
.band-dark a { color: var(--spark); }
.band-dark a:hover { color: var(--paper); }
/* The ruling's edges: page heroes are dark grounds too, so their links take
   the spark half. The spark band is orange itself, where an orange link
   would vanish, so links there fall back to ink. Buttons everywhere carry
   their own colors and outrank these. */
.phero a { color: var(--spark); }
.phero a:hover { color: var(--paper); }
.band-spark a:not(.btn) { color: var(--ink); }
.band-sand { background: var(--band); }
/* THE STEEL BAND (2026-08-25 expansion): Surface Steel graduates from link
   and eyebrow duty to structural material. A deeper steel wash than --band,
   for section rhythm where sand and dark are already spoken for. Type on it
   stays ink/muted, which both clear their ratios on this ground. */
.band-steel { background: color-mix(in srgb, var(--chrome) 14%, var(--paper)); }
.band-steel .card { background: var(--card); }

/* ---- CARDS --------------------------------------------------------------- */
.card {
  background: var(--card); border: 1px solid var(--hairline); border-radius: var(--r);
  padding: 22px 22px 20px; text-decoration: none; color: inherit; display: block;
  transition: border-color var(--t-hover) var(--ease), transform var(--t-hover) var(--ease), box-shadow var(--t-hover) var(--ease);
}
/* The spark-glow family (2026-08-25 rollout): every linked card on the site
   hovers the same way the arc and diagnosis cards do. Spark border, 1px ring,
   14px bloom, 2px lift. The glow is the owner's sanctioned exception to the
   no-halo rule, scoped to this one hover family and nothing else. */
a.card:hover { border-color: var(--spark); transform: translateY(-2px); box-shadow: 0 0 0 1px var(--spark), 0 0 14px color-mix(in srgb, var(--spark) 30%, transparent); }
.card h3 { margin-bottom: .35em; font-size: var(--step-1); }
.card p { font-size: var(--step--1); color: var(--muted); margin-bottom: 0; }
.card .num {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: var(--step-2); font-weight: 600; color: var(--ink); display: block; margin-bottom: 6px;
}
.card .go {
  display: inline-flex; align-items: center; gap: 6px; margin-top: 14px;
  font-family: var(--font-mono); font-size: var(--step--1); font-weight: 600; color: var(--primary);
  transition: gap var(--t-hover) var(--ease);
}
a.card:hover .go { gap: 12px; color: var(--ink); }
/* A card on a dark band has no fill of its own. v3 has one dark and no
   elevated "riser" tier, so the card is drawn by its hairline. */
.band-dark .card { background: transparent; border-color: var(--hairline-d); box-shadow: none; }
.band-dark .card p { color: var(--dim-d); }
/* Same family on the dark band: spark reads on Midnight, and the glow reads
   better there than anywhere. */
.band-dark a.card:hover { border-color: var(--spark); box-shadow: 0 0 0 1px var(--spark), 0 0 14px color-mix(in srgb, var(--spark) 30%, transparent); }
.band-dark .card .go { color: var(--spark); }
/* The hover pair for the rule above (2026-08-26): `a.card:hover .go` sets
   ink for light cards at (0,3,1), which beat this class's (0,3,0) and put a
   midnight label on a midnight card. Same family as the a:hover note at
   .band-dark .btn:hover: the element selector in the generic rule is what
   wins the fight. (0,4,1) settles it. */
.band-dark a.card:hover .go { color: var(--paper); }

.card-media {
  aspect-ratio: 16 / 10; border-radius: calc(var(--r) - 4px); overflow: hidden;
  margin: -4px -4px 16px; background: var(--band);
}
.card-media img, .card-media svg { width: 100%; height: 100%; object-fit: cover; }

/* ---- BADGES + CHIPS ------------------------------------------------------ */
/* P02 STATUS CHIPS. The law: the dot carries the colour on light, the label
   carries it only on dark. Landfall is 1.7:1 on white and Meridian is 3.0:1
   there (2.79:1 on --page), so neither may ever set this 10.5px label on a
   white card. The dot is a fill, and a fill is legal. The 2026-08-27 link
   ruling does not reach this: it licensed underlined body links, not chips. On Midnight Green the pair measures 9.6:1 and
   5.3:1, so there the label itself may take the colour.
   The three states stay separable in a greyscale print without changing
   shape: Landfall 0.59, Meridian 0.30, Midnight 0.02 of 1. */
.badge {
  display: inline-flex; align-items: center; gap: 7px;
  font-family: var(--font-mono); font-size: 10.5px; font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase; padding: 3px 9px; border-radius: var(--pill);
  border: 1px solid var(--hairline); background: transparent; color: var(--muted);
  vertical-align: middle;
}
.badge::before {
  content: ""; flex: 0 0 auto; width: 7px; height: 7px; border-radius: 50%;
  background: currentColor;
}
.badge.live::before { background: var(--signal); }   /* shipped / passing   */
.badge.demo::before { background: var(--beacon); }   /* in progress / info  */
.badge.conf::before { background: var(--ink); }      /* there is no red     */
.badge.soon::before { background: var(--faint); }
.badge.conf { border-color: var(--ink); color: var(--ink); }
.badge.soon { color: var(--faint); }
.band-dark .badge { color: var(--dim-d); border-color: var(--hairline-d); }
.band-dark .badge.live { color: var(--signal); }
.band-dark .badge.demo { color: var(--beacon); }
.band-dark .badge.conf { color: var(--paper); border-color: var(--paper); }
.band-dark .badge.conf::before { background: var(--paper); }
.band-dark .badge.soon { color: var(--dim-d); border-color: var(--hairline-d); }
/* The Landfall dot breathes (2026-08-25): live means running right now, so
   the dot carries a slow expanding ring. A fill animating, never type;
   removed entirely under reduced motion. */
.badge.live::before { animation: livePulse 2.6s var(--ease) infinite; }
@keyframes livePulse {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--signal) 45%, transparent); }
  70%  { box-shadow: 0 0 0 6px transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}
@media (prefers-reduced-motion: reduce) { .badge.live::before { animation: none; } }

.chip {
  font-family: var(--font-mono); font-size: var(--step--1); font-weight: 500;
  padding: 7px 14px; border-radius: var(--pill); border: 1px solid var(--hairline);
  background: transparent; color: var(--muted); cursor: pointer;
  transition: color var(--t-hover) var(--ease), border-color var(--t-hover) var(--ease), background var(--t-hover) var(--ease);
}
.chip:hover { border-color: var(--primary); color: var(--ink); }
.chip.on { background: var(--ink); border-color: var(--ink); color: var(--paper); }

/* ---- BUTTONS ------------------------------------------------------------- */
/* One True North button per view — .btn.spark is it. A second primary means
   the first one was not primary. Hit target never below 44px, radius is
   --pill, and hover is a border-colour change plus a 1px lift: never a
   scale, never a wash. There is no darker orange to hover into, because a
   seventh colour would be a seventh colour. */
.btn {
  display: inline-flex; align-items: center; gap: 8px; justify-content: center;
  font-family: var(--font-body); font-size: var(--step-0); font-weight: 600;
  padding: 13px 26px; border-radius: var(--pill); border: 1px solid transparent;
  background: var(--ink); color: var(--paper); text-decoration: none; cursor: pointer;
  min-height: 44px;
  transition: background var(--t-hover) var(--ease), transform var(--t-press) var(--ease), border-color var(--t-hover) var(--ease);
}
/* color is re-declared at hover because the global link hover (Steel to
   ink) otherwise outranks the button and inks the label into its own fill
   (the vanishing-label bug, found twice on 2026-08-25). */
.btn:hover { border-color: var(--spark); transform: translateY(-1px); color: var(--paper); }
.btn:active { transform: translateY(1px); }
.btn.quiet { background: transparent; border-color: var(--hairline); color: var(--ink); }
.btn.quiet:hover { border-color: var(--ink); background: transparent; color: var(--ink); }
.btn.spark { background: var(--spark); color: var(--ink); box-shadow: var(--sh-md); }
.btn.spark:hover { background: var(--spark); color: var(--ink); border-color: var(--ink); }
/* THE STEEL BUTTON (2026-08-25): the tertiary rung of the family, for
   actions that are structure rather than sale. Hollow steel at rest; on
   hover the state swaps — steel fill, Paper label — with the family glow
   in steel. Spark stays the only primary accent. */
.btn.steel { background: transparent; border-color: var(--chrome); color: var(--chrome); }
.btn.steel:hover {
  background: var(--chrome); border-color: var(--chrome); color: var(--paper);
  box-shadow: 0 0 0 1px var(--chrome), 0 0 14px color-mix(in srgb, var(--chrome) 40%, transparent);
}
/* Steel fails on Midnight at 2.1:1, so the dark-band variant lifts the steel
   toward Paper for both the border and the label. */
/* The background is re-declared, not inherited, and that is the whole point:
   `.band-dark .btn` fills every button on a dark band with Paper, so a steel
   variant that only sets border and label renders pale steel type on white
   and vanishes. Same family as the hover bug this file already fixed once.
   Declare all three properties or the variant is a trap. */
.band-dark .btn.steel { background: transparent; border-color: color-mix(in srgb, var(--chrome) 45%, var(--paper)); color: color-mix(in srgb, var(--chrome) 28%, var(--paper)); }
.band-dark .btn.steel:hover {
  background: color-mix(in srgb, var(--chrome) 45%, var(--paper)); color: var(--ink);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--chrome) 45%, var(--paper)), 0 0 14px color-mix(in srgb, var(--chrome) 30%, transparent);
}
.band-dark .btn { background: var(--paper); color: var(--ink); }
/* color is DECLARED here, and the reason is specificity, not caution: the
   dark-band link rule `.band-dark a:hover` carries an element selector, so
   at (0,2,1) it outranks `.band-dark .btn` at (0,2,0) and repainted this
   label Paper on a Paper pill. The earlier vanishing-label fixes patched
   .btn rules and never found it because the culprit was never a .btn rule.
   (0,3,0) settles it. If a label vanishes on a colored band again, look for
   an `a` in the winning selector before touching the button rules. */
/* The hero CTA's hover, verbatim (DJ 2026-08-26): a solid button on a dark
   band rests paper and fills spark on hover, white label, the house glow.
   Declaring color here is still load-bearing: .band-dark a:hover at (0,2,1)
   repaints anchor labels and this rule at (0,3,0) is what outranks it. */
.band-dark .btn:hover { background: var(--spark); color: var(--paper); border-color: transparent; transform: translateY(-1px); box-shadow: 0 0 0 1px var(--spark), 0 0 16px color-mix(in srgb, var(--spark) 55%, transparent), 0 0 34px color-mix(in srgb, var(--spark) 25%, transparent); }
.band-dark .btn.quiet { background: transparent; border-color: var(--hairline-d); color: var(--paper); }
.band-dark .btn.quiet:hover { border-color: var(--spark); color: var(--paper); }
.btnrow { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 26px; }

/* ---- TABLES -------------------------------------------------------------- */
/* P05: hairline row rules, no vertical rules, no zebra striping. Numbers
   right-aligned and tabular, always. */
.list-wrap { overflow-x: auto; border: 1px solid var(--hairline); border-radius: var(--r); background: var(--card); }
/* WIDE CONTENT SCROLLS INSIDE ITSELF, never past the page (2026-08-27).
   The brand-os colour-law table could not shrink under its own content, so on
   a 320px screen it pushed the whole document 20px sideways, and on 375 it
   squeezed the reason column into a 72px ribbon of one-word lines. A table
   with real columns has a legitimate minimum; the fix is to let it keep that
   minimum and scroll, not to crush it. min-width is what forces the scroll
   rather than the squeeze. */
.tablewrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.tablewrap > table { min-width: 460px; }

table.list { width: 100%; border-collapse: collapse; font-size: var(--step--1); }
table.list th {
  background: var(--band); text-align: left; padding: 11px 16px;
  font-family: var(--font-mono); font-size: 10.5px; font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase; color: var(--muted);
  border-bottom: 1px solid var(--hairline); white-space: nowrap;
}
table.list td { padding: 12px 16px; border-bottom: 1px solid var(--hairline); vertical-align: top; }
table.list tr:last-child td { border-bottom: 0; }
/* No row hover, deliberately (2026-08-26). Both tables using this class are
   non-interactive: the education rows on /experience/ and the brain file
   results, whose rows carry no links and no click handler. A hover wash on
   a row that does nothing is a false affordance, and on the dark education
   band it was worse than false: --band is a light wash and those cells set
   Paper type inline, so hovering painted white text onto near-white. If a
   clickable table.list ever exists, give IT a hover, not the class. */
table.list td.num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; white-space: nowrap; text-align: right; }

/* ---- NOTES --------------------------------------------------------------- */
.note {
  border-left: 3px solid var(--primary); background: var(--band);
  padding: 16px 20px; border-radius: 0 var(--r) var(--r) 0;
  font-size: var(--step--1);
}
.note p:last-child { margin-bottom: 0; }
/* A True North rule is a rule, so it is legal on a light ground. The label
   beside it is not orange, because orange is never type on white. */
.note.warn { border-left-color: var(--spark); }
/* Meridian is the information rung (2026-08-25): a note that reports state
   rather than warns carries the beacon edge over its own faint wash. The
   rule and the wash are fills, legal on light; the type stays ink/muted. */
.note.info { border-left-color: var(--beacon); background: var(--wash-beacon); }
/* THERE IS NO RED IN THIS PALETTE. The old .note.flag was the alert red and
   its 7% wash; both are deleted by law, not repointed. The T07 error pattern
   replaces them exactly: a 2px Midnight Green border, the glyph, and a Plex
   Mono line — never True North, which means action, not failure. */
.note.flag {
  border: 2px solid var(--ink); border-radius: var(--r);
  background: var(--card); padding: 15px 19px;
}
.note-label {
  font-family: var(--font-mono); font-size: 10.5px; font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase; color: var(--primary);
  display: block; margin-bottom: 6px;
}
.note.warn .note-label { color: var(--ink); }
.note.flag .note-label { color: var(--ink); }
.note.flag .note-label::before { content: "\2715"; margin-right: 8px; font-weight: 700; }

/* ---- STEPS --------------------------------------------------------------- */
.steps { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(min(230px, 100%), 1fr)); counter-reset: s; }
.step { border-top: 2px solid var(--hairline); padding-top: 16px; counter-increment: s; }
.step::before {
  content: counter(s, decimal-leading-zero);
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: var(--step--1); font-weight: 600;
  color: var(--primary); display: block; margin-bottom: 8px;
}
.step h3 { font-size: var(--step-0); margin-bottom: .3em; }
.step p { font-size: var(--step--1); color: var(--muted); margin: 0; }
.band-dark .step { border-top-color: var(--hairline-d); }
.band-dark .step::before { color: var(--spark); }
.band-dark .step p { color: var(--dim-d); }

/* ---- PILLARS ------------------------------------------------------------- */
.pillar { border-top: 2px solid var(--ink); padding-top: 18px; }
.pillar .n {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: var(--step--1); font-weight: 600;
  color: var(--primary); display: block; margin-bottom: 10px; letter-spacing: .08em;
}
.pillar h3 { font-size: var(--step-1); margin-bottom: .4em; }
.pillar p { color: var(--muted); font-size: var(--step--1); margin: 0; }
.band-dark .pillar { border-top-color: var(--hairline-d); }
.band-dark .pillar .n { color: var(--spark); }

/* ---- QUOTES / TESTIMONIALS ---------------------------------------------- */
.quote { border-left: 2px solid var(--primary); padding-left: 22px; }
.band-dark .quote { border-left-color: var(--spark); }
.quote blockquote {
  margin: 0 0 16px; font-family: var(--font-display);
  font-weight: 500; font-size: var(--step-1); line-height: 1.45; letter-spacing: -.012em;
}
.quote cite { font-style: normal; font-size: var(--step--1); color: var(--muted); display: block; }
.quote cite b { color: var(--ink); font-weight: 600; display: block; }
.band-dark .quote cite { color: var(--dim-d); }
.band-dark .quote cite b { color: var(--paper); }

/* ---- PLACEHOLDER — every one is visible and labelled -------------------- */
.ph {
  position: relative; display: grid; place-items: center; text-align: center;
  background:
    repeating-linear-gradient(-45deg, transparent 0 9px, var(--hairline) 9px 10px),
    var(--band);
  border: 1px dashed color-mix(in srgb, var(--spark) 45%, transparent);
  border-radius: var(--r); color: var(--primary);
  font-family: var(--font-mono); font-size: var(--step--1); font-weight: 600;
  letter-spacing: .06em; padding: 24px; min-height: 120px;
}
.ph small { display: block; font-weight: 400; color: var(--muted); letter-spacing: 0; margin-top: 6px; max-width: 34ch; }
.ph-figure { aspect-ratio: 4 / 5; }
.band-dark .ph { background: transparent; border-color: var(--hairline-d); color: var(--spark); }
.band-dark .ph small { color: var(--dim-d); }

/* ---- FOOTER -------------------------------------------------------------- */
.ft { background: var(--ink-deep); color: var(--dim-d); font-size: var(--step--1); }
.ft-in { max-width: var(--wrap-wide); margin-inline: auto; padding: 56px var(--gutter) 40px; }
.ft-grid { display: grid; gap: 32px; grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr)); }
.ft h4 {
  font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--paper); margin-bottom: 14px; font-weight: 600;
}
.ft a { color: var(--dim-d); text-decoration: none; display: block; padding: 5px 0; }
.ft a:hover { color: var(--spark); }
.ft-base {
  margin-top: 40px; padding-top: 24px; border-top: 1px solid var(--hairline-d);
  display: flex; flex-wrap: wrap; gap: 16px; justify-content: space-between; align-items: center;
}
.ft-build { font-family: var(--font-mono); font-size: 11px; color: var(--dim-d); max-width: 62ch; line-height: 1.6; }

/* ---- PAGE HERO (interior pages) ----------------------------------------- */
.phero { background: var(--grad-ground); color: var(--paper); }
.phero-in { max-width: var(--wrap); margin-inline: auto; padding: clamp(48px, 7vw, 92px) var(--gutter); }
.phero h1 { font-family: var(--font-display); font-weight: 800; letter-spacing: -.02em; color: var(--paper); }
.phero .lede { color: var(--dim-d); }
.phero .kicker { color: var(--spark); }

/* ---- PRINT --------------------------------------------------------------- */
/* One ink on stock. The black master is 100K only and the surface, the glass
   and every blur come off — so these are reproduction values, not palette
   values, and they are the only literal colours in this file. */
/* ---- the contact photo strip (2026-08-26, DJ's ask) ----------------------
   Four photographs on the one page whose job is being a person. Uniform
   crop height so four different orientations read as one strip; captions in
   the mono voice the site uses for facts, because that is what they are. */
.pgal { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin-top: var(--sp-5); }
.pgal figure { margin: 0; }
.pgal img { width: 100%; height: 300px; object-fit: cover; border-radius: var(--r); border: 1px solid var(--hairline); display: block; }
.pgal figcaption { margin-top: 8px; font-family: var(--font-mono); font-size: 11px; letter-spacing: .06em; color: var(--muted); }
@media (max-width: 900px) { .pgal { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 480px) { .pgal img { height: 200px; } }

@media print {
  .hd, .ft, .skip, .btnrow, .splith-fx { display: none !important; }
  body { background: #fff; color: #000; font-size: 10.5pt; }
  .band-dark, .phero, .proof, .splith { background: #fff !important; color: #000 !important; }
  .band-dark *, .phero *, .proof *, .splith * { color: #000 !important; }
  a { text-decoration: none; color: #000; }
  .card { border: 1px solid #ccc; break-inside: avoid; }
  .section { padding-block: 18pt; }
}

/* ---- ANNOTATED SOURCE EXCERPTS ------------------------------------------- */
/* The syntax palette was seven off-token colours measured against a ground
   that had already moved twice — one comment claimed #002B2B, another
   claimed #0D0F11, and the file rendered on neither. It is rebuilt here from
   the six, on one ground, with one set of numbers.

   THE GROUND is --ink-deep, which in v3 is Midnight Green #00272C. Every
   ratio below was computed against that exact value on 2026-08-13:

     plain    --paper    #FFFFFF  15.83:1  code, the default
     comment  --dim-d    #A8B6B7   7.57:1  66% white on Midnight, prose in source
     keyword  --beacon   #279AF1   5.26:1  Meridian
     string   --signal   #09E85E   9.59:1  Landfall
     number   --signal   #09E85E   9.59:1  a literal is a literal; they share
     regex    --spark    #FF6B1C   5.56:1  True North. The patterns ARE the
                                           argument in these excerpts, and this
                                           is the one ground where orange is
                                           legal as body-sized type.
     call     --paper    #FFFFFF  15.83:1  distinguished by WEIGHT, not by a
                                           seventh colour
     numbers  --dim-d    #A8B6B7   7.57:1  line numbers. The old value measured
                                           4.72:1; this one is not a nudge, it
                                           is the token that already existed.

   The signal pair is allowed here and nowhere else on a light page: the
   Brand OS clears it "inside a product demo or diagram frame only, where the
   frame makes clear it is not chrome." The .code-head names the source file,
   so the frame is doing exactly that job. */

.code {
  margin: 34px 0 0; padding: 0;
  border: 1px solid var(--hairline); border-radius: var(--r);
  overflow: hidden; background: var(--card);
}
.code-head {
  display: flex; flex-wrap: wrap; gap: 6px 18px; align-items: baseline;
  justify-content: space-between;
  padding: 12px 18px; background: var(--band);
  border-bottom: 1px solid var(--hairline);
}
.code-file { font-size: var(--step--1); font-weight: 600; color: var(--ink); word-break: break-all; }
.code-repo { font-size: 11px; letter-spacing: .10em; text-transform: uppercase; color: var(--faint); }
.code-cap {
  margin: 0; padding: 14px 18px; font-size: var(--step--1); line-height: 1.6;
  color: var(--muted); border-bottom: 1px solid var(--hairline); max-width: none;
}
.code-body {
  display: grid; grid-template-columns: minmax(0, 1fr) 300px;
  gap: 0; align-items: stretch;
}
@media (max-width: 1040px) { .code-body { grid-template-columns: minmax(0, 1fr); } }

.code-pre {
  margin: 0; padding: 18px 0; overflow-x: auto; background: var(--ink-deep);
  font-family: var(--font-mono); font-size: 13px; line-height: 1.62;
  color: var(--paper); tab-size: 2; font-variant-numeric: tabular-nums;
}
.code-pre code { display: block; min-width: max-content; }

/* The left inset gives the rail marker its own lane so it never crowds a
   two-digit line number. */
.ln { display: block; position: relative; padding: 0 18px 0 20px; }
.ln-n {
  display: inline-block; width: 3.2em; padding-right: 1.1em; text-align: right;
  color: var(--dim-d); user-select: none; -webkit-user-select: none;
}
.ln-c { white-space: pre; }
/* A marked line gets a rule and a tint, and carries the rail's number at the
   end so the pairing survives when the rail wraps underneath on a phone. */
.ln--mark { background: color-mix(in srgb, var(--spark) 13%, transparent); box-shadow: inset 3px 0 0 var(--spark); }
.ln--gap .ln-c { color: var(--dim-d); font-style: italic; }
/* The rail marker lives in the left gutter, beside the right-aligned line
   number. It was originally floated right and sticky, which kept it in view
   while the excerpt scrolled horizontally but sat it directly on top of the
   code. A marker that obscures the line it is pointing at has defeated itself.
   The disc is a True North fill and its digit is Midnight Green at 5.6:1 —
   it used to be Paper White on burnt orange, and white on True North is
   2.8:1. */
.ln-b {
  position: absolute; left: 1px; top: 2px;
  width: 16px; height: 16px;
  border-radius: 50%; background: var(--spark); color: var(--ink);
  font-size: 9.5px; font-weight: 700; line-height: 16px; text-align: center;
}

.code-rail {
  padding: 18px; background: var(--card);
  border-left: 1px solid var(--hairline);
}
@media (max-width: 1040px) { .code-rail { border-left: 0; border-top: 1px solid var(--hairline); } }
/* Self-contained so an excerpt can appear on a page that does not load
   brain.css. Same visual language as the brain-demo rail. */
.code-rail .anno { border-left: 2px solid var(--spark); padding: 2px 0 2px 14px; margin-bottom: 20px; position: relative; }
.code-rail .anno:last-child { margin-bottom: 0; }
.code-rail .anno-l {
  font-family: var(--font-mono); font-size: 10px; font-weight: 600; letter-spacing: .12em;
  text-transform: uppercase; color: var(--primary); display: block; margin-bottom: 5px;
}
.code-rail .anno p { font-size: var(--step--1); line-height: 1.55; color: var(--muted); margin: 0; max-width: none; }
.anno--num .anno-n {
  position: absolute; left: -10px; top: 0;
  width: 17px; height: 17px; border-radius: 50%;
  background: var(--spark); color: var(--ink);
  font-family: var(--font-mono); font-size: 10px; font-weight: 700;
  line-height: 17px; text-align: center;
}
.anno--num { padding-left: 20px; border-left: 0; }

@media print {
  .code-pre { background: #fff; color: #000; }
  /* Colour set on the token spans beats colour inherited from the <pre>, so
     without this the syntax palette prints light-on-white and the excerpt is
     effectively blank on paper. (This block once served the /resume/ page,
     which is gone; it stays because printed excerpts are still a real
     output.) */
  .code-pre [class^="t-"] { color: #000; }
  .ln--gap .ln-c { color: #444; }
  .ln-n { color: #666; }
  .ln--mark { background: #f0f0f0; box-shadow: none; }
  .code-body { grid-template-columns: 1fr; }
  .code, .code-pre { break-inside: avoid; }
}

/* ---- PRESS FEEDBACK, SITE-WIDE ------------------------------------------- */
/* Same asymmetry as the brain demo: acknowledge in --t-press, settle in
   --t-release. The card already lifts on hover, so on press it returns to the
   ground rather than lifting further. A thing you push should go down. */
.card, .btn, .go, .splith-half { transition-duration: var(--t-release); }
.card:active, .btn:active, .go:active { transition-duration: var(--t-press); }
.card:active { transform: none; border-color: var(--primary); }
.cl summary:active, details > summary:active { transition-duration: var(--t-press); }

/* ---- THE OTHER TWO PREFERENCES ------------------------------------------
   Reduced motion was handled from the start. These two were not, and the
   header is the reason they matter: it is a translucent layer over scrolling
   content, which is exactly the construct both preferences exist to opt out of.

   Neither is a hypothetical. `prefers-reduced-transparency` is what a reader
   with a vestibular or focus condition sets when blurred chrome makes text
   swim, and `prefers-contrast` is set by readers who need edges rather than
   suggestions. A site arguing that accessibility is a pass rather than an
   afterthought should answer all three signals, not the one that was easy.

   The Brand OS says the same thing about the glass: anyone who sets reduced
   transparency gets the solid, not a thinner blur.
   ------------------------------------------------------------------------ */
@media (prefers-reduced-transparency: reduce) {
  .hd {
    background: var(--ground);
    backdrop-filter: none; -webkit-backdrop-filter: none;
    border-bottom: 1px solid var(--hairline-d);
  }
  .bd-tabs { background: var(--paper); background-attachment: scroll; }
  .splith-fx { display: none; }
}

@media (prefers-contrast: more) {
  :root {
    /* Hairlines become visible edges, and the tertiary text tier stops being
       tertiary. --faint measures 5.1:1 on white, which passes and still reads
       as low contrast by design; at this setting that intent is wrong. */
    --hairline:   color-mix(in srgb, var(--ink) 42%, transparent);
    --hairline-d: color-mix(in srgb, var(--paper) 46%, transparent);
    --faint:      var(--muted);
    --dim-d:      color-mix(in srgb, var(--paper) 82%, transparent);
  }
  .hd { background: var(--ground); backdrop-filter: none; -webkit-backdrop-filter: none; }
  .card, .code, .bd-detail { border-width: 2px; }
  .btn { border-width: 2px; }
  a:not(.btn) { text-decoration: underline; text-underline-offset: 2px; }
  .bd-tab[aria-selected="true"] { border-bottom-width: 3px; }
}

/* The syntax colours documented above. Every one is a token; the ground they
   are measured against is --ink-deep, #00272C. */
.t-c { color: var(--dim-d); font-style: italic; }  /* comment   7.57:1  */
.t-k { color: var(--beacon); }                     /* keyword   5.26:1  */
.t-s { color: var(--signal); }                     /* string    9.59:1  */
.t-r { color: var(--spark); }                      /* regex     5.56:1  */
.t-n { color: var(--signal); }                     /* number    9.59:1  */
.t-f { color: var(--paper); font-weight: 600; }    /* call     15.83:1  */
.t-p { color: var(--paper); }                      /* plain    15.83:1  */

/* ---- MOBILE NAV ENTRANCE -------------------------------------------------
   The menu is a panel growing out of the header, so it enters from the edge
   it is anchored to: a short fade and settle downward, 200ms. It previously
   appeared with no bridge at all. Exit stays instant, deliberately: the
   panel is display-toggled, and a dismissal should never make the user wait.
   Reduced motion removes this via the global rule in tokens.css. */
@media (max-width: 900px) {
  .hd nav.open { animation: navIn var(--t-release) var(--ease); }
}
@keyframes navIn { from { opacity: 0; transform: translateY(-6px); } }


/* ---- THE LOOP STRIP (homepage) ------------------------------------------- */
/* The seven-step operating loop as one readable line. Scrolls in its own row
   on small screens, per the house rule that the page never scrolls sideways. */
.loop-strip { display: flex; gap: 0; overflow-x: auto; padding: 26px 0 10px; scrollbar-width: thin; }
.loop-step { flex: 1 0 130px; min-width: 130px; position: relative; padding: 0 18px 0 0; }
.loop-step + .loop-step { padding-left: 18px; border-left: 1px solid var(--hairline-d); }
.loop-k { font-family: var(--font-mono); font-size: 10.5px; font-weight: 600; letter-spacing: .14em; color: var(--spark); display: block; margin-bottom: 6px; }
.loop-t { font-weight: 600; font-size: var(--step--1); color: var(--paper); display: block; margin-bottom: 4px; }
.loop-d { font-size: 12.5px; line-height: 1.5; color: var(--dim-d); display: block; max-width: 24ch; }

/* ---- THE SIDEBAR SHELL ----------------------------------------------------
   Layout pivot, 2026-08-11, on DJ's direction: a fixed left rail in the manner
   of the Sidefolio template, with the split-persona hero kept from the Adham
   Dannaway lineage the original hero already followed. The brand tokens are
   unchanged on purpose: the references contribute ARCHITECTURE and air, not a
   new identity. Below 1024px the rail hands over to the existing top bar. */
.sb {
  position: fixed; inset-block: 0; left: 0; width: 264px; z-index: 90;
  display: flex; flex-direction: column; gap: 26px;
  padding: 30px 26px 26px; overflow-y: auto;
  background: var(--card); border-right: 1px solid var(--hairline);
}
.sb-mark { display: flex; gap: 12px; align-items: center; text-decoration: none; color: var(--ink); }
.sb-mark b { font-family: var(--font-display); font-weight: 800; font-size: 1.05rem; letter-spacing: -.02em; display: block; line-height: 1.15; }
/* THE NEEDLE, ON A WHITE GROUND.
   True North is never type on white at any size — 2.8:1, and the law is
   flat. The wordmark's period is therefore not set as a glyph here: the
   character is made transparent and a square takes its place, because on
   light this colour is a fill, a rule, or a shape and nothing else. On the
   dark header the glyph stands on its own at 5.6:1, so it needs no shape. */
.sb-mark b .dot { color: transparent; position: relative; }
.sb-mark b .dot::after {
  content: ""; position: absolute; left: .02em; bottom: .05em;
  width: .18em; height: .18em; border-radius: 1px; background: var(--spark);
}
.hd-mark b .dot { color: var(--spark); }
.sb-mark i { font-style: normal; font-size: 11.5px; color: var(--faint); display: block; margin-top: 2px; }
.sb-nav { display: flex; flex-direction: column; gap: 2px; }
.sb-nav a {
  font-size: .92rem; font-weight: 500; color: var(--muted); text-decoration: none;
  padding: 8px 10px; border-radius: var(--r-sm); position: relative;
  transition: color var(--t-hover) var(--ease), background var(--t-hover) var(--ease);
}
.sb-nav a:hover { color: var(--ink); background: var(--band); }
.sb-nav a:active { transition-duration: var(--t-press); background: var(--band); }
.sb-nav a[aria-current="page"] { color: var(--ink); font-weight: 600; background: var(--band); }
.sb-nav a[aria-current="page"]::before {
  content: ""; position: absolute; left: 0; top: 9px; bottom: 9px; width: 2.5px;
  border-radius: 2px; background: var(--spark);
}
.sb-nav--dim a { font-size: .85rem; color: var(--faint); }
.sb-sep { display: block; height: 1px; background: var(--hairline); }
.sb-foot { margin-top: auto; display: flex; flex-direction: column; gap: 14px; }
.sb-cta {
  width: 100%; font-size: var(--step--1); padding: 11px 18px; min-height: 44px;
  background: var(--spark); color: var(--ink); box-shadow: var(--sh-sm);
}
.sb-cta:hover { background: var(--spark); color: var(--ink); border-color: var(--ink); }
.sb-soc { display: flex; gap: 14px; }
.sb-soc a { font-size: .82rem; color: var(--muted); }
.sb-loc { margin: 0; font-family: var(--font-mono); font-size: 10.5px; color: var(--faint); }

.content { min-width: 0; }
@media (min-width: 1024px) {
  .hd { display: none; }
  .content { margin-left: 264px; }
  /* the fixed-position rail owns the left edge; wide wraps breathe less */
  .content .wrap--wide { max-width: 1240px; }
}
@media (max-width: 1023.9px) {
  .sb { display: none; }
}

/* Softer card language, from the references: a touch more radius and a resting
   shadow, lift kept subtle. Two shadow grades exist and there is no third:
   0 1px 3px at 5% for resting sheets, 0 12px 30px -14px at 22% for floating. */
.card { border-radius: var(--r); box-shadow: var(--sh-sm); }
.card:hover { box-shadow: var(--sh-md); }

/* ---- SIDEBAR v2: profile header, group labels, dropdowns ------------------ */
.sb { gap: 18px; }
.sb-ava { width: 44px; height: 44px; border-radius: 50%; object-fit: cover; flex: 0 0 auto; }
.sb-label {
  font-family: var(--font-mono); font-size: 10px; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase; color: var(--faint);
  padding: 10px 10px 0; border-top: 1px solid var(--hairline); margin-top: 6px;
}
.sb-dd summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; justify-content: space-between;
  font-size: .92rem; font-weight: 500; color: var(--muted);
  padding: 8px 10px; border-radius: var(--r-sm); user-select: none;
  transition: color var(--t-hover) var(--ease), background var(--t-hover) var(--ease);
}
.sb-dd summary::-webkit-details-marker { display: none; }
.sb-dd summary::after {
  content: ""; width: 7px; height: 7px; flex: 0 0 auto;
  border-right: 1.6px solid var(--faint); border-bottom: 1.6px solid var(--faint);
  transform: rotate(-45deg); transition: transform var(--t-hover) var(--ease); margin-right: 3px;
}
.sb-dd[open] summary::after { transform: rotate(45deg); }
.sb-dd summary:hover { color: var(--ink); background: var(--band); }
.sb-sub { display: flex; flex-direction: column; gap: 1px; padding: 2px 0 4px 12px; border-left: 1px solid var(--hairline); margin-left: 12px; }
.sb-sub a { font-size: .85rem !important; padding: 6px 10px !important; }

/* ---- TESTIMONIAL MARQUEE (home) ------------------------------------------ */
/* One slow horizontal loop of the seven cards, duplicated once for seamless
   wrap. Pauses on hover. Under reduced motion the loop is REMOVED, never
   slowed: the track becomes a scrollable row. */
.tmq { overflow: hidden; margin-top: 26px; }
.tmq-track { display: flex; gap: 16px; width: max-content; padding-inline: var(--gutter);
  animation: tmq 80s linear infinite; }
.tmq:hover .tmq-track { animation-play-state: paused; }
@keyframes tmq { from { transform: translateX(0); } to { transform: translateX(-50%); } }
.tmq-card {
  flex: 0 0 340px; margin: 0; background: var(--card); border: 1px solid var(--hairline);
  border-radius: var(--r); box-shadow: var(--sh-sm); padding: 22px;
}
.tmq-card blockquote { margin: 0 0 14px; font-size: var(--step--1); line-height: 1.6; color: var(--ink); }
.tmq-card figcaption { border-top: 1px solid var(--hairline); padding-top: 10px; }
.tmq-card figcaption strong { display: block; font-size: .9rem; }
.tmq-card figcaption span { font-size: 12px; color: var(--muted); }
@media (prefers-reduced-motion: reduce) {
  .tmq { overflow-x: auto; }
  .tmq-track { animation: none; }
}

/* ==== SYSTEM SCREENSHOT FIGURES (2026-08-26 image placement) ==============
   The frame is a link, so it needs the interactive treatment the rest of the
   site gives links: the spark-glow family on hover, and a real focus ring.
   The image is capped at 1000px because that is the widest any of these is
   legible inline, and the file behind it is 2000px so the cap is a 2x source
   on a retina screen rather than a smudge.

   The caption carries two things: what the figure shows, and, on the six
   reconstructions, the disclosure. The disclosure is set apart visually but
   NOT dimmed below the caption it sits in, because a disclaimer nobody can
   read is a disclaimer that was not made. */
.sfig { margin: var(--sp-6) 0; max-width: 1000px; }
.sfig--wide { max-width: none; }
.sfig-frame {
  display: block; border: 1px solid var(--hairline); border-radius: var(--r);
  overflow: hidden; background: var(--card); text-decoration: none;
  transition: border-color var(--t-hover) var(--ease), box-shadow var(--t-hover) var(--ease), transform var(--t-hover) var(--ease);
}
.sfig-frame img { display: block; width: 100%; height: auto; }
.sfig-frame:hover {
  border-color: var(--spark); transform: translateY(-2px);
  box-shadow: 0 0 0 1px var(--spark), 0 0 14px color-mix(in srgb, var(--spark) 30%, transparent);
}
.sfig-frame:focus-visible { outline: 2px solid var(--spark); outline-offset: 3px; }
.sfig figcaption {
  margin-top: var(--sp-3); font-size: var(--step--1); line-height: 1.55;
  color: var(--muted); max-width: var(--measure);
}
.sfig-recon { display: block; margin-top: var(--sp-1); font-family: var(--font-mono); font-size: 12px; line-height: 1.5; color: var(--muted); }
/* padding-block is the target, not decoration (2026-08-27). At 11.5px this
   link boxed out at 109x18, under the 24px floor, and it is a standalone
   control rather than a link inside a sentence, so the exemption does not
   reach it. The negative inline margin keeps it optically flush with the
   caption above while the hit area grows. */
.sfig-open {
  display: inline-block; margin-top: var(--sp-2); font-family: var(--font-mono);
  font-size: 11.5px; letter-spacing: .08em; text-transform: uppercase;
  padding-block: 5px; margin-inline: -2px; padding-inline: 2px;
}
.band-dark .sfig figcaption, .band-dark .sfig-recon { color: var(--dim-d); }
.band-dark .sfig-frame { border-color: var(--hairline-d); background: transparent; }

/* ---- PHOTOGRAPHS --------------------------------------------------------- */
.pfig { margin: var(--sp-6) 0; }
.pfig img { display: block; width: 100%; height: auto; border-radius: var(--r); }
.pfig figcaption { margin-top: var(--sp-3); font-size: var(--step--1); line-height: 1.55; color: var(--muted); }
.band-dark .pfig figcaption { color: var(--dim-d); }
/* The portrait crop earns a two-column layout rather than a full-width band:
   at full width a 3:4 image becomes a wall. The text column carries the
   argument and the picture sits beside it. */
.photo-two { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 320px); gap: var(--sp-7); align-items: center; }
.photo-two .pfig { margin: 0; }
@media (max-width: 720px) {
  .photo-two { grid-template-columns: minmax(0, 1fr); gap: var(--sp-5); }
  .photo-two .pfig { max-width: 320px; }
}
