/* Generated by packages/ui/tools/build.mjs from packages/ui/tokens/tokens.json. Self hosted faces. Inter (SIL OFL 1.1) and Space Grotesk (SIL OFL 1.1) carry the site; Montserrat (SIL OFL 1.1), Carlito (SIL OFL 1.1, metric compatible with Calibri) and IBM Plex Mono (SIL OFL 1.1) are kept because the films are set in them. Licences sit beside the files in fonts/. Do not edit by hand. */
@font-face {
  font-family: "Montserrat";
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url(fonts/Montserrat-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Montserrat";
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url(fonts/Montserrat-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Carlito";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/Carlito-400-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Carlito";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/Carlito-400-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Carlito";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(fonts/Carlito-700-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Carlito";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(fonts/Carlito-700-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/IBMPlexMono-400-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/IBMPlexMono-400-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(fonts/IBMPlexMono-500-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(fonts/IBMPlexMono-500-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(fonts/Inter-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(fonts/Inter-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Space Grotesk";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url(fonts/SpaceGrotesk-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Space Grotesk";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url(fonts/SpaceGrotesk-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}


/* Generated by packages/ui/tools/build.mjs from packages/ui/tokens/tokens.json. Design tokens. Do not edit by hand. */

:root {
  --teal: #3FBCB5;
  --teal-deep: #0C4140;
  --teal-dark: #195E67;
  --teal-mid: #2B9FAF;
  --cyan: #61CBD9;
  --cyan-light: #95CFD7;
  --pink: #E06EB7;
  --white: #FFFFFF;
  --paper: #F1F4F3;
  --paper-alt: #F8F8F8;
  --ink: #020C0C;
  --ink-lead: #3A4A4A;
  --ink-row: #2B3838;
  --ink-2: #4F5F5F;
  --rule: #D6DEDD;
  --bound: #75787B;
  --ok: #0A6B3D;
  --att: #8A5A00;
  --no: #B02B17;
  --wash-ok: #E8F2EC;
  --wash-att: #FDF3E2;
  --wash-no: #FBECEB;
  --wash-teal: #E6F4F3;
  --i-ground: #0C4140;
  --i-far: #061C1C;
  --i-panel: #0F3534;
  --i-rule: #1F5554;
  --i-ink: #F1F4F3;
  --i-ink-2: #A9BDBC;
  --i-teal: #3FBCB5;
  --i-ok: #7EDDB0;
  --i-att: #FFD37A;
  --i-no: #FFB3A6;
  --i-code-key: #61CBD9;
  --d-ground: #030910;
  --d-surface: #05101d;
  --d-card: #081524;
  --d-ink: #eaf2ff;
  --d-ink-2: #8ea3bd;
  --d-ink-lead: #aebdd2;
  --d-ink-row: #cddcee;
  --d-ink-nav: #c4d2e4;
  --d-rule: #4d6a89;
  --d-hairline: #18293a;
  --d-accent: #22d3ee;
  --d-accent-dim: #0e7f96;
  --d-ok: #35CC86;
  --d-no: #FA555C;
  --d-att: #F4A437;
  --d-wash-ok: #0B2A1E;
  --d-wash-att: #2C2210;
  --d-wash-no: #2E1418;
  --d-wash-teal: #06222c;
  --d-blue: #52a8ff;
  --d-violet: #9d8bff;
  --d-magenta: #35d9a4;
  --d-sand: #f5b93f;
  --d-slate: #7fd8e6;
  --d-accent-strong: #4fe3f2;
  --d-on-brand: #04222b;
  --d-faint: #5f748f;
  --muted: var(--ink-2);
  --on-brand: #020C0C;
  --sans: "Inter", "Segoe UI", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --display: "Inter", "Segoe UI", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --sans-film: "Calibri", "Carlito", "Segoe UI", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --mono: "IBM Plex Mono", "Monaco", "Andale Mono", "Menlo", "Consolas", monospace;
  --t-display: clamp(38px, 4.4vw, 56px);
  --t-display-line: 1.02;
  --t-display-weight: 700;
  --t-display-tracking: -0.035em;
  --t-h1: clamp(26px, 2.4vw, 32px);
  --t-h1-line: 1.2;
  --t-h1-weight: 700;
  --t-h1-tracking: -0.03em;
  --t-h2: 22px;
  --t-h2-line: 1.25;
  --t-h2-weight: 700;
  --t-h2-tracking: -0.02em;
  --t-h3: 20px;
  --t-h3-line: 1.4;
  --t-h3-weight: 600;
  --t-h3-tracking: normal;
  --t-body: 17px;
  --t-body-line: 1.55;
  --t-body-weight: 400;
  --t-body-tracking: normal;
  --t-small: 15px;
  --t-small-line: 1.5;
  --t-small-weight: 400;
  --t-small-tracking: normal;
  --t-label: 14px;
  --t-label-line: 1.4;
  --t-label-weight: 600;
  --t-label-tracking: normal;
  --t-mono: 14px;
  --t-mono-line: 1.65;
  --t-mono-weight: 400;
  --t-mono-tracking: normal;
  --t-figure: clamp(28px, 3vw, 40px);
  --t-figure-line: 1;
  --t-figure-weight: 400;
  --t-figure-tracking: normal;
  --measure-display: 24ch;
  --measure-body: 66ch;
  --measure-notes: 74ch;
  --s1: 4px;
  --s2: 8px;
  --s3: 12px;
  --s4: 16px;
  --s5: 24px;
  --s6: 32px;
  --s7: 48px;
  --s8: 64px;
  --s9: 96px;
  --s10: 128px;
  --page-max: 1280px;
  --gutter: clamp(20px, 4vw, 32px);
  --gutter: clamp(20px, 4vw, 32px);
  --page-max: 1472px;
  --read-max: 720px;
  --r-1: 4px;
  --r-2: 10px;
  --r-3: 14px;
  --pill: 999px;
  --shadow-masthead-rest: 0 1px 0 #D6DEDD;
  --shadow-masthead-scrolled: 0 6px 24px rgba(2, 12, 12, 0.08);
  --shadow-lift: 0 1px 0 rgba(255, 255, 255, 0.04) inset, 0 12px 32px rgba(0, 0, 0, 0.28);
  --m-drawer: 150ms;
  --m-copy-confirm: 1400ms;
  --m-wires-draw: 900ms;
  --m-wires-stagger: 40ms;
  --m-trust-path-hop: 300ms;
  --m-trust-path-max: 3000ms;
  --m-blast-node: 120ms;
  --arrow-right: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 15 10'%3E%3Cpath d='M0 5h13M9 1l4 4-4 4' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --focus-ring: var(--teal-deep);
  --focus-halo: var(--white);
}

@media (max-width: 700px) {
  :root { --t-body: 16px; }
}

/* The dark instrument variant. Scoped, never a site wide theme. */
[data-surface="instrument"] {
  --surface-ground: var(--i-ground);
  --surface-panel: var(--i-panel);
  --surface-rule: var(--i-rule);
  --surface-ink: var(--i-ink);
  --surface-ink-2: var(--i-ink-2);
  --surface-ok: var(--i-ok);
  --surface-att: var(--i-att);
  --surface-no: var(--i-no);
  --surface-teal: var(--i-teal);
  --focus-ring: var(--paper);
  --focus-halo: var(--teal-deep);
}

/* Generated by packages/ui/tools/build.mjs from packages/ui/tokens/tokens.json. The dark site. These values win everywhere that loads this file, the film pages included. Do not edit by hand. */

:root {
  --paper: #030910;  /* the page ground */
  --paper-alt: #05101d;  /* an alternate band, one step up from the page */
  --white: #081524;  /* a card or panel, the lightest ground anything sits on */
  --ink: #eaf2ff;  /* primary text */
  --ink-lead: #aebdd2;  /* a lead paragraph, one step between primary and secondary */
  --ink-row: #cddcee;  /* the value in a labelled row, beside a dimmer label */
  --ink-2: #8ea3bd;  /* secondary text */
  --ink-nav: #c4d2e4;  /* a navigation label at rest, brighter than secondary text on purpose */
  --rule: #4d6a89;  /* separators and the reference implementation stroke */
  --bound: #4d6a89;  /* the boundary of anything a person operates */
  --hairline: #18293a;  /* a decorative divider: a navigation row, a footer rule, a column separator */
  --ok: #35CC86;  /* proven, observed, admitted, active */
  --att: #F4A437;  /* in progress, pending, asserted */
  --no: #FA555C;  /* refused, withdrawn, stopped */
  --teal: #22d3ee;  /* the ownership marker, as a fill */
  --teal-deep: #22d3ee;  /* the action colour: one accent, as the references have it */
  --teal-dark: #22d3ee;  /* link text and the current navigation item */
  --teal-mid: #0e7f96;  /* graphic fill: figure shapes and the trust path stroke */
  --cyan: #22d3ee;  /* keyword tint and the active stepper bar */
  --brand-strong: #4fe3f2;  /* the brand, bright: a hover fill and the text on an outlined brand control */
  --slate: #7fd8e6;  /* a quiet brand tint, for an icon or a closing line beside brand text */
  --faint: #5f748f;  /* the faintest text, for a footer line */
  --wash-ok: #0B2A1E;  /* ground behind a proven word or row */
  --wash-att: #2C2210;  /* ground behind an in progress word or row */
  --wash-no: #2E1418;  /* ground behind a refused word or row */
  --wash-teal: #06222c;  /* ground behind an observer panel, a call to action, the current stage */
  --on-brand: #030910;  /* text on a product fill or any other brand coloured ground */
}

/* Component stylesheet. Hand written. Compiled with the fonts and tokens into apps/site/src/public/ui.css.
   Rules that a test enforces:
   only .treat[data-treat="product"] and .node[data-treat="product"] fill with var(--teal);
   var(--ok) appears only under .ev[data-ev="observed"], .state[data-state="ok"], .mark-ok and the blast list stays row;
   no outline: none without a replacement ring. */

/* 1. Base */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  font-family: var(--sans);
  font-size: var(--t-body);
  line-height: var(--t-body-line);
  font-weight: 400;
  color: var(--ink);
  background: var(--paper);
  font-variant-numeric: tabular-nums;
}
img, svg, video { max-width: 100%; display: block; }
[hidden] { display: none !important; }
h1, h2, h3, h4, p, ul, ol, dl, figure, table { margin: 0; }
ul, ol { padding: 0; }
a { color: var(--teal-dark); text-decoration: underline; text-underline-offset: 0.14em; text-decoration-thickness: 1px; }
a:hover { text-decoration-thickness: 2px; }
strong, b { font-weight: 600; }
code, kbd, samp, pre, .mono { font-family: var(--mono); font-size: var(--t-mono); line-height: var(--t-mono-line); }
/* A long identifier breaks where it must rather than running off the screen. `.mono` joins `code`
   here because the two carry the same content, entity identifiers and URLs and base64url segments,
   and only `code` had the rule: seventeen selectors across four stylesheets had since added
   `overflow-wrap: anywhere` one place at a time, and the eighteenth was an artefact drawer taking
   /governance to 826px at 390 wide. Inside a `pre` the declaration cannot act, because
   `white-space: pre` does not wrap, so the scrolling code blocks keep scrolling. */
code, .mono { overflow-wrap: anywhere; }

:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
  box-shadow: 0 0 0 2px var(--focus-halo), 0 0 0 4px var(--focus-ring);
}
:focus:not(:focus-visible) { outline: 2px solid transparent; outline-offset: 2px; }

.skip {
  position: absolute; left: var(--s4); top: -100px;
  padding: var(--s2) var(--s4); background: var(--teal-deep); color: var(--white);
  border-radius: var(--r-1); z-index: 100; text-decoration: none; font-weight: 600;
}
.skip:focus { top: var(--s4); }

.vh { position: absolute !important; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* 2. Type scale */
/* Weight and tracking come from the token, never from a number written here. tokens.json said the
   display weight was 400 and then 700 while this rule said 400 either way, so the token was
   decorative and the stylesheet was the real source. packages/ui/tests/stylesheet.test.ts now
   refuses a literal for either property on a scale class. */
.t-display, h1.t-display { font-family: var(--display); font-size: var(--t-display); line-height: var(--t-display-line); font-weight: var(--t-display-weight); letter-spacing: var(--t-display-tracking); max-width: var(--measure-display); }

/* The accented half of a page statement. The references spend about a third of the home page's
   accent on one line of the headline, and it is the line the reader leaves with. */
.t-display .accent { color: var(--teal-dark); }
.t-h1, h1, h2.t-h1 { font-family: var(--display); font-size: var(--t-h1); line-height: var(--t-h1-line); font-weight: var(--t-h1-weight); letter-spacing: var(--t-h1-tracking); }
.t-h2, h2 { font-family: var(--display); font-size: var(--t-h2); line-height: var(--t-h2-line); font-weight: var(--t-h2-weight); letter-spacing: var(--t-h2-tracking); }
.t-h3, h3 { font-family: var(--display); font-size: var(--t-h3); line-height: var(--t-h3-line); font-weight: var(--t-h3-weight); letter-spacing: var(--t-h3-tracking); }
.t-body { font-size: var(--t-body); line-height: var(--t-body-line); font-weight: var(--t-body-weight); }
.t-small, small { font-size: var(--t-small); line-height: var(--t-small-line); }
.t-label { font-size: var(--t-label); line-height: var(--t-label-line); font-weight: var(--t-label-weight); }
.t-figure { font-size: var(--t-figure); line-height: var(--t-figure-line); font-weight: var(--t-figure-weight); font-variant-numeric: tabular-nums; }
.measure { max-width: var(--measure-body); }
.measure-notes { max-width: var(--measure-notes); }
.ink-2 { color: var(--ink-2); }
.flow > * + * { margin-top: var(--s4); }
.flow > h2 + *, .flow > h3 + * { margin-top: var(--s3); }
.flow > * + h2 { margin-top: var(--s7); }
.flow > * + h3 { margin-top: var(--s5); }

/* 3. Layout */
/* THE MEASURE IS THE CONTENT WIDTH AND THE GUTTER SITS OUTSIDE IT, which is the one thing to know
   before reading a number off the reference. The reference writes `max-w-[1100px] px-8`: a BOX of
   1100 with 32px of padding inside it, so its content is 1036. --page-max here is the content, so
   the number to copy is the reference's box less 64.

   THREE FAMILIES, AND THEY WERE SEVEN. Each page that narrowed itself picked its own number and
   two of them read the reference's box as a measure, so /evidence and /why ran 64px wider than
   /how-it-works while all three copy the same reference page. The families now are:
     home and the wide routes   1472   (the reference's 1536 box)
     the use case pages         1216   (its 1280 box, confirmed against uc-02: its card's left edge
                                        lands at x=112 on a 1440 viewport, which is this number)
     the interior pages         1036   (its 1100 box: /how-it-works, /architecture, /evidence, /why) */
.wrap { width: min(100% - 2 * var(--gutter), var(--page-max)); margin-inline: auto; }
.read { width: min(100%, var(--read-max)); }
.band { padding-block: var(--s8); border-top: 1px solid var(--rule); }
.band-alt { background: var(--paper-alt); }
.band-white { background: var(--white); }
.band-first { border-top: 0; }
/* A band's opening block: eyebrow, heading, lead. Held to a readable measure and given room under
   it, so a section starts the same way on every page. */
.band-head { display: grid; gap: var(--s3); margin-bottom: var(--s6); }
.band-head > * { margin: 0; }
.band-foot { margin-top: var(--s5); }
/* A quiet forward link at the end of a band. */
/* 24px MINIMUM ON THE TARGET, and this class is the site's "one link at the end of a block" mark.
   It appears alone at the foot of a panel with no sentence around it, so neither exemption in WCAG
   2.2 clause 2.5.8 applies: not the inline one, because it is not in a sentence, and not the
   spacing one, because two of them sit side by side on /use-cases/across-the-boundary. Measured at
   768 and at 390: 147 by 22, 184 by 22 and 249 by 22 on three different routes. The floor is set on
   the component rather than on each page, because each page that reached for it was reaching for
   the same object. */
.more { display: inline-flex; align-items: center; min-height: 24px; font-weight: 600; }
@media (max-width: 700px) { .band { padding-block: var(--s7); } }
.cols-2 { display: grid; gap: var(--s6); grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; }
.cols-3 { display: grid; gap: var(--s5); grid-template-columns: repeat(3, minmax(0, 1fr)); align-items: start; }
@media (max-width: 1040px) { .cols-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 700px) { .cols-2, .cols-3 { grid-template-columns: minmax(0, 1fr); } }
.panel { background: var(--white); border-radius: var(--r-2); padding: var(--s5); }
.panel-rule { border: 1px solid var(--rule); }

/* Cards get a radius and a stroke. Without the stroke a panel on a dark ground has no edge at all,
   which is most of why the page read flat.

   THIS LIVES IN THE BASE SHEET, NOT IN site.css, and the difference is the whole point. site.css
   loads after ui.css and every component part is concatenated inside ui.css, so a rule here that
   sat there would beat every part at equal specificity from a file part authors must not edit. It
   did exactly that to figure.control-plane until 12 September. Here, a part overrides it the
   ordinary way. */
.panel, .figure, .hero-panel, .term-strip, .rail .stage, .resolve-seq .step {
  border-radius: var(--r-3); border: 1px solid var(--rule); box-shadow: var(--shadow-lift);
}
.rail .stage { border-top-width: 3px; }

/* Grid and flex children shrink below their content so a wide pre scrolls inside its box rather than widening the page. */
.cols-2 > *, .cols-3 > *, .stack-layout > *, .stack > *, .film-layout > *, .blast-layout > *, .explorer > *, .journey-head > *, .proof, .proof-body, .cmd, .raw, .wires > *, .figure { min-width: 0; max-width: 100%; }

/* 4. Buttons and controls */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  min-height: 48px; padding: 12px 26px;
  font: inherit; font-weight: 600; line-height: 1.2;
  border-radius: var(--r-1); border: 1.5px solid var(--teal-deep);
  background: var(--teal-deep); color: var(--white);
  text-decoration: none; cursor: pointer;
}
.btn:hover { background: var(--teal-dark); border-color: var(--teal-dark); }
/* The filled action carries an arrow, the quiet one does not, as the reference has it. Drawn with a
   pseudo element rather than a character in the markup, so the label a screen reader reads and the
   label a translator sees are both just the words. */
.btn:not(.btn-quiet):not(.btn-small)::after { content: ""; width: 15px; height: 10px; flex: none; background: currentColor; -webkit-mask: var(--arrow-right) center / contain no-repeat; mask: var(--arrow-right) center / contain no-repeat; }
/* THE QUIET PILL TAKES --brand-strong, WHICH IS THE OTHER PAIR'S VALUE AND THE TARGET'S.
 *
 * THIS SITE SHIPS TWO BUTTON PAIRS, MEASURED IN CHROME ON /films AT 1440 RATHER THAN READ OFF THE
 * SOURCE. `.btn`/`.btn-quiet` here, and `.rw-btn`/`.rw-btn-quiet` in packages/ui/src/parts/rw.css,
 * used by /films, /film, /working-session, /deployed and packages/ui/partials/av-artefact.ejs. They
 * differed in four ways: radius 14px against a full pill, 14px type against 15px, a 1.5px edge
 * against 1px, and the quiet label #22d3ee against #4fe3f2. CLAUDE.md states the target: a full
 * pill, brand ground with dark text filled, brand border with BRAND STRONG text outlined.
 *
 * ONE OF THE FOUR IS SETTLED HERE AND THREE ARE NOT, and the reason is worth writing down rather
 * than leaving as an inconsistency somebody rediscovers. The other three are set in
 * apps/site/src/public/site.css, which loads after this sheet and wins:
 *
 *     .btn { border-radius: var(--r-3); padding-inline: var(--s5); font-size: var(--t-label); }
 *     .btn-quiet { background: transparent; border-color: var(--teal-deep); }
 *
 * Deleting those two rules leaves one pair, because everything they override is already correct
 * here or in rw.css. Restating them at a higher specificity from this file would leave the same two
 * definitions and add a fight between them, which is worse than the split it pretends to fix.
 *
 * NO COLOUR VALUE MOVES. --brand-strong and --teal-deep are both declared and both already used;
 * this changes which of the two the quiet label names. */
.btn-quiet { background: var(--white); color: var(--brand-strong); }
.btn-quiet:hover { background: var(--wash-teal); color: var(--brand-strong); }
.btn[aria-disabled="true"], .btn:disabled { background: var(--paper); color: var(--ink-2); border-color: var(--bound); cursor: not-allowed; }
.btn-small { min-height: 36px; padding: 6px 12px; font-size: var(--t-small); }
[data-surface="instrument"] .btn-quiet { background: transparent; color: var(--surface-ink); border-color: var(--surface-ink-2); }
[data-surface="instrument"] .btn-quiet:hover { background: var(--surface-panel); }
.input, input[type="search"].input, input[type="text"].input {
  font: inherit; color: var(--ink); background: var(--white);
  min-height: 44px; padding: 8px 12px; border: 1.5px solid var(--bound); border-radius: var(--r-1); width: 100%;
}
.actions { display: flex; flex-wrap: wrap; gap: var(--s3); align-items: center; }
@media (max-width: 480px) { .actions-stack-phone .btn { width: 100%; } }

/* 5. Masthead: moved to src/parts/mast.css so it can be worked on alone. */

/* 6. Marks: the four silhouettes. Colour comes from the parent. */
.mark { display: inline-block; width: 1em; height: 1em; vertical-align: -0.15em; flex: none; }
.mark svg { width: 100%; height: 100%; display: block; }
.mark-ok { color: var(--ok); }
.mark-att { color: var(--att); }
.mark-no { color: var(--no); }
.mark-muted { color: var(--ink-2); }
[data-surface="instrument"] .mark-ok { color: var(--surface-ok); }
[data-surface="instrument"] .mark-att { color: var(--surface-att); }
[data-surface="instrument"] .mark-no { color: var(--surface-no); }
[data-surface="instrument"] .mark-muted { color: var(--surface-ink-2); }

/* 7. Treatments. One component, five values. */
.treat { display: inline-flex; align-items: center; gap: var(--s2); font-size: var(--t-label); font-weight: 600; line-height: var(--t-label-line); color: var(--ink); }
.treat .swatch { width: 12px; height: 12px; border-radius: var(--r-1); flex: none; display: inline-block; }
.treat[data-treat="product"] .swatch { background: var(--teal); }
.treat[data-treat="customer"] .swatch { background: var(--ink); }
.treat[data-treat="reference"] .swatch { background: var(--white); border: 1.5px solid var(--bound); }
.treat[data-treat="standard"] .swatch { background: transparent; border: 1px dotted var(--ink-2); }
.treat[data-treat="third"] .swatch { background: var(--white); border: 1.5px dashed var(--ink-2); }
.treat .host { font-size: var(--t-small); font-weight: 400; opacity: 0.8; margin-left: 12px; }
.treat .note { font-size: var(--t-small); font-weight: 400; color: var(--ink-2); }

.treat.chip { border-radius: var(--pill); padding: 5px 12px; min-height: 28px; flex-wrap: wrap; row-gap: 2px; max-width: 100%; }
.treat.chip .host { overflow-wrap: anywhere; }
.treat.chip .swatch { display: none; }
.treat.chip[data-treat="product"] { background: var(--teal); color: var(--on-brand); }
.treat.chip[data-treat="customer"] { background: var(--ink); color: var(--white); }
.treat.chip[data-treat="reference"] { background: var(--white); color: var(--ink); border: 1.5px solid var(--bound); }
.treat.chip[data-treat="third"] { background: var(--white); color: var(--ink); border: 1.5px dashed var(--ink-2); }
.treat.chip[data-treat="customer"] .host { opacity: 0.85; }
.treat.chip[data-treat="customer"] .note { color: var(--white); opacity: 0.85; }

/* An open standard marks a sentence, never a box. */
.std { text-decoration: underline dotted var(--ink-2); text-underline-offset: 0.18em; text-decoration-thickness: 1px; cursor: help; }

.treat-legend { display: flex; flex-wrap: wrap; gap: var(--s4) var(--s6); }
.treat-legend .item { display: grid; grid-template-columns: 12px 1fr; gap: 2px var(--s2); align-items: baseline; max-width: 260px; }
.treat-legend .item .swatch { width: 12px; height: 12px; border-radius: var(--r-1); position: relative; top: 1px; }
.treat-legend .item[data-treat="product"] .swatch { background: var(--teal); }
.treat-legend .item[data-treat="customer"] .swatch { background: var(--ink); }
.treat-legend .item[data-treat="reference"] .swatch { background: var(--white); border: 1.5px solid var(--bound); }
.treat-legend .item[data-treat="standard"] .swatch { background: transparent; border: 1px dotted var(--ink-2); }
.treat-legend .item[data-treat="third"] .swatch { background: var(--white); border: 1.5px dashed var(--ink-2); }
.treat-legend .label { font-size: var(--t-label); font-weight: 600; }
.treat-legend .note { grid-column: 2; font-size: var(--t-small); color: var(--ink-2); }
.treat-legend.compact { gap: var(--s3) var(--s5); }
.treat-legend.compact .note { display: none; }
.treat-legend-title { font-size: var(--t-label); font-weight: 600; margin-bottom: var(--s3); }
@media (max-width: 700px) { .treat-legend:not(.compact) { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* 8. Evidence marks */
.ev { display: inline-flex; align-items: center; gap: 6px; font-size: var(--t-label); font-weight: 600; line-height: var(--t-label-line); }
.ev .mark { width: 14px; height: 14px; }
.ev[data-ev="observed"] { color: var(--ok); }
.ev[data-ev="deployment"] { color: var(--ink); }
.ev[data-ev="deployment"] .mark { color: var(--ink-2); }
.ev[data-ev="capability"] { color: var(--att); }
/* NOT OBSERVED IS AN ABSENCE, NOT A REFUSAL, AND IT DREW IN THE REFUSAL COLOUR UNTIL 16 September
   2026. --no is declared for "Refused, withdrawn, stopped, gone, not found", which is a thing that
   happened; "not observed on this tenant" is a thing that has not been looked at here. Ralph read a
   trust mark card and asked why it was red, which is the right question: a reader cannot tell a
   withdrawal from an absence if both are painted the same. The cross glyph stays, so it is still
   distinct from Deployment evidence, which is primary ink with a hollow circle. */
.ev[data-ev="not-observed"] { color: var(--ink-2); }
.ev a { color: inherit; }

/* ---- the smallest a target is allowed to be ---------------------------------------------------
   WCAG 2.2 clause 2.5.8 sets the minimum at 24 CSS pixels in both directions, and exempts a target
   that sits inside a sentence, where the line sizes it rather than the designer. Everything below
   stands on its own: an evidence label under a heading, a claim key in a JSON reader, a row of
   links at the foot of a card, the wordmark. Each was sized by its line box alone and each came out
   between 20 and 23 px, which is the kind of miss that a stylesheet never shows you and a thumb
   finds immediately. `.cmd .copy` at 36 px and `.treat.chip` at 28 px were already doing this; these
   four were not. The height is a minimum, so a target that already clears it does not move, and
   centring the line inside it means nothing shifts except the four that were short. */
.ev a, .ev-claim-key, .actions > a, .actions > button, .masthead-brand {
  min-height: 24px;
}
.ev a, .actions > a, .actions > button, .masthead-brand { display: inline-flex; align-items: center; }
.ev .where { font-weight: 400; color: var(--ink-2); }
tr[data-ev="observed"] > td:first-child, .row[data-ev="observed"] { background: var(--wash-ok); }
tr[data-ev="deployment"] > td:first-child, .row[data-ev="deployment"] { background: var(--wash-teal); }
tr[data-ev="capability"] > td:first-child, .row[data-ev="capability"] { background: var(--wash-att); }
tr[data-ev="not-observed"] > td:first-child, .row[data-ev="not-observed"] { background: var(--wash-no); }
.ev-legend { display: flex; flex-wrap: wrap; gap: var(--s3) var(--s5); }

/* 9. State chips */
.state { display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px 3px 8px; border-radius: var(--pill); font-size: var(--t-label); font-weight: 600; line-height: var(--t-label-line); white-space: nowrap; }
.state .mark { width: 13px; height: 13px; }
.state[data-state="ok"] { color: var(--ok); background: var(--wash-ok); }
.state[data-state="att"] { color: var(--att); background: var(--wash-att); }
.state[data-state="no"] { color: var(--no); background: var(--wash-no); }
.state[data-state="muted"] { color: var(--ink-2); background: var(--paper); }
[data-surface="instrument"] .state[data-state="ok"] { color: var(--surface-ok); background: var(--surface-panel); }
[data-surface="instrument"] .state[data-state="att"] { color: var(--surface-att); background: var(--surface-panel); }
[data-surface="instrument"] .state[data-state="no"] { color: var(--surface-no); background: var(--surface-panel); }
[data-surface="instrument"] .state[data-state="muted"] { color: var(--surface-ink-2); background: var(--surface-panel); }

/* 10. Owner rules: a 3px top rule in the owner's treatment. Shared by the rail, the mini rail and cards. */
.owner-rule { border-top: 3px solid var(--rule); }
.owner-rule[data-owner="product"] { border-top-color: var(--teal); }
.owner-rule[data-owner="customer"] { border-top-color: var(--ink); }
.owner-rule[data-owner="reference"] { border-top-color: var(--bound); }
.owner-rule[data-owner="third"] { border-top-style: dashed; border-top-color: var(--ink-2); }
.owner-rule[data-owner="standard"] { border-top-style: dotted; border-top-color: var(--ink-2); }

/* 11. Stage rail */
.rail { list-style: none; display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--s4); counter-reset: stage; }
.rail .stage { background: var(--white); padding: var(--s4) var(--s4) var(--s5); border-radius: 0 0 var(--r-1) var(--r-1); display: grid; gap: 6px; align-content: start; }
.rail .stage.is-current { background: var(--wash-teal); }
.rail .stage .verb { font-size: var(--t-h3); font-weight: 600; line-height: var(--t-h3-line); display: flex; gap: var(--s2); align-items: baseline; }
.rail .stage .verb .n { font-weight: 400; color: var(--ink-2); font-size: var(--t-small); font-variant-numeric: tabular-nums; }
.rail .stage a.verb { color: inherit; text-decoration: none; }
.rail .stage a.verb:hover { color: var(--teal-dark); text-decoration: underline; }
.rail .stage .where { font-size: var(--t-small); color: var(--ink-2); }
.rail .stage .line { font-size: var(--t-small); margin-top: 4px; }
.rail-foot { margin-top: var(--s4); font-size: var(--t-small); color: var(--ink-2); }
@media (max-width: 1040px) { .rail { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 700px) {
  .rail { grid-template-columns: minmax(0, 1fr); gap: var(--s3); }
  .rail .stage { border-top: 0; border-left: 3px solid var(--rule); border-radius: 0 var(--r-1) var(--r-1) 0; }
  .rail .stage[data-owner="product"] { border-left-color: var(--teal); }
  .rail .stage[data-owner="customer"] { border-left-color: var(--ink); }
  .rail .stage[data-owner="reference"] { border-left-color: var(--bound); }
  .rail .stage[data-owner="standard"] { border-left-style: dotted; border-left-color: var(--ink-2); }
}

/* 12. Mini rail */
/* min-width: 0 on both, or overflow-x does nothing inside a flex or grid parent: a flex item's
   default min-width is its content, so the rail refuses to shrink and widens the card instead. It
   fitted by luck while the face was Carlito and pushed /use-cases 50px past a 390 wide screen the
   moment the site took the wider brand face. The same rule is stated for the other scrolling boxes
   further up this file. */
.rail-mini { display: flex; gap: var(--s5); overflow-x: auto; min-width: 0; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.rail-mini::-webkit-scrollbar { display: none; }
.rail-mini a, .rail-mini span.stage { flex: none; padding: 8px 0 10px; font-size: var(--t-small); font-weight: 600; color: var(--ink-2); text-decoration: none; }
.rail-mini a:hover { color: var(--teal-dark); text-decoration: underline; }
/* The state rules name the span form too. `.rail-mini span.stage` is one class more specific than
   `.rail-mini .is-current`, so on a rail rendered as spans, which is every journey card and every
   film card, the base colour won and each stage painted the same muted grey. Design 10 section 6.1
   asks for the covered stages in ink. */
.rail-mini .is-current, .rail-mini span.stage.is-current { color: var(--ink); }
.rail-mini .is-covered, .rail-mini span.stage.is-covered { color: var(--ink); }
/* The line above names the span form for colour and this one did not, so the teal wash landed on
   the current stage and its inset did not: `.rail-mini span.stage` sets `padding: 8px 0 10px`, the
   shorthand writes the inline padding to zero, and it is one class more specific than
   `.rail-mini .is-current`. Background is not in the shorthand, so the fill applied and the padding
   that was supposed to hold it off the glyphs did not, and every current stage on every page read
   as a word with a box cutting into both ends of it. The same trap, two lines apart, caught once. */
.rail-mini .is-current, .rail-mini span.stage.is-current { background: var(--wash-teal); padding-inline: var(--s2); margin-inline: calc(-1 * var(--s2)); border-radius: 0 0 var(--r-1) var(--r-1); }
.rail-mini-wrap { position: relative; min-width: 0; }
@media (max-width: 700px) {
  .rail-mini { gap: var(--s4); }
  .rail-mini-wrap::before, .rail-mini-wrap::after { content: ""; position: absolute; top: 0; bottom: 0; width: 24px; pointer-events: none; opacity: 0; }
  .rail-mini-wrap::before { left: 0; background: linear-gradient(to right, var(--paper), transparent); }
  .rail-mini-wrap::after { right: 0; background: linear-gradient(to left, var(--paper), transparent); }
  .rail-mini-wrap.can-scroll-start::before, .rail-mini-wrap.can-scroll-end::after { opacity: 1; }
}
.rail-mini.excerpt { gap: var(--s3); }
.rail-mini.excerpt .stage { font-size: var(--t-label); padding: 6px 0 4px; }

/* 13. Figures shared */
.figure { background: var(--white); border-radius: var(--r-2); padding: var(--s5); }
.figure-caption { font-size: var(--t-small); color: var(--ink-2); margin-top: var(--s3); }
.figure-title { font-size: var(--t-label); font-weight: 600; margin-bottom: var(--s3); }
.figure svg text { font-family: var(--sans); font-size: 14px; fill: var(--ink); }
.figure svg text.mono { font-family: var(--mono); font-size: 13px; }
.figure svg text.small { font-size: 12px; fill: var(--ink-2); }
/* Nodes on a figure: treatment fills. */
.node[data-treat="product"] { fill: var(--teal); stroke: var(--teal); }
.node[data-treat="customer"] { fill: var(--ink); stroke: var(--ink); }
.node[data-treat="reference"] { fill: var(--white); stroke: var(--bound); stroke-width: 1.5; }
.node[data-treat="third"] { fill: var(--white); stroke: var(--ink-2); stroke-width: 1.5; stroke-dasharray: 4 3; }
.node[data-treat="instance"] { fill: var(--white); stroke: var(--ink-2); stroke-width: 1.5; stroke-dasharray: 4 3; }
.node-label[data-treat="product"], .node-label[data-treat="reference"], .node-label[data-treat="third"], .node-label[data-treat="instance"] { fill: var(--ink); }
.node-label[data-treat="customer"] { fill: var(--white); }
/* An agent in the sprawl figure: stroked, never filled, so a filled node still means what the
   treatment vocabulary says it means. The stroke colour and the number both arrive inline, from one
   table in the partial. */
.node.agent { fill: none; stroke-width: 1.5; }
.wires svg text.agent-n { font-size: 12px; font-weight: 600; font-family: var(--mono); }
.wire { fill: none; stroke: var(--ink-2); stroke-width: 1; }
.wire-after { fill: none; stroke: var(--teal-mid); stroke-width: 1.5; }
.wire-standard { fill: none; stroke: var(--ink-2); stroke-width: 1.5; stroke-dasharray: 2 4; stroke-linecap: round; }
.wire-rule { fill: none; stroke: var(--rule); stroke-width: 2; }

/* 14. Wires before and after */
.wires { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s5); }
.wires .figure svg { width: 100%; height: auto; }
.wires .count { display: flex; align-items: baseline; gap: var(--s3); margin-top: var(--s3); }
.wires .count .t-figure { color: var(--ink); }
.wires .count .t-small { color: var(--ink-2); }
.wires-inputs { display: flex; flex-wrap: wrap; gap: var(--s4); align-items: end; margin-bottom: var(--s4); font-size: var(--t-small); }
.wires-inputs label { display: grid; gap: 4px; }
.wires-inputs input { width: 80px; min-height: 40px; }
.wires-note { font-size: var(--t-small); color: var(--ink-2); margin-top: var(--s3); }
@media (max-width: 600px) { .wires { grid-template-columns: minmax(0, 1fr); } }
.wires .draw { stroke-dasharray: 1000; stroke-dashoffset: 1000; }
.wires.is-drawn .draw, .wires:not([data-animate]) .draw { stroke-dashoffset: 0; }
.wires.is-drawing .draw { animation: wire-draw var(--m-wires-draw) ease forwards; animation-delay: calc(var(--i, 0) * var(--m-wires-stagger)); }
@keyframes wire-draw { to { stroke-dashoffset: 0; } }

/* 15. Resolve sequence */
.resolve-seq { list-style: none; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s4); counter-reset: step; }
.resolve-seq .step { background: var(--white); border-radius: var(--r-2); padding: var(--s4); display: grid; gap: var(--s2); align-content: start; }
.resolve-seq .step .name { font-size: var(--t-label); font-weight: 600; display: flex; gap: var(--s2); align-items: center; }
.resolve-seq .step .name .n { color: var(--ink-2); font-weight: 400; }
.resolve-seq .step .artefact { font-family: var(--mono); font-size: var(--t-mono); line-height: var(--t-mono-line); overflow-wrap: anywhere; display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: center; }
.resolve-seq .step .why { font-size: var(--t-small); color: var(--ink-2); }
.resolve-seq .notfound { color: var(--no); font-weight: 500; display: inline-flex; gap: 6px; align-items: center; }
.resolve-seq .checks { list-style: none; display: grid; gap: 4px; font-size: var(--t-small); }
.resolve-seq .checks li { display: flex; gap: 6px; align-items: center; }
.resolve-seq .chain { display: flex; align-items: center; gap: 6px; font-size: var(--t-small); flex-wrap: wrap; }
.resolve-seq .chain .hop { border-radius: var(--r-1); padding: 2px 8px; font-weight: 600; font-size: var(--t-label); }
.resolve-seq .chain .hop[data-treat="product"] { background: var(--teal); color: var(--on-brand); }
.resolve-seq .chain .hop[data-treat="customer"] { background: var(--ink); color: var(--white); }
.resolve-seq .chain .hop[data-treat="reference"] { border: 1.5px solid var(--bound); }
.resolve-seq .chain .hop[data-treat="third"] { border: 1.5px dashed var(--ink-2); }
.resolve-seq .chain .dots { color: var(--ink-2); letter-spacing: 2px; }
.resolve-seq .admitted { color: var(--ok); font-weight: 600; display: inline-flex; gap: 6px; align-items: center; }
@media (max-width: 900px) {
  .resolve-seq { grid-template-columns: minmax(0, 1fr); position: relative; padding-left: var(--s5); }
  .resolve-seq::before { content: ""; position: absolute; left: 6px; top: 8px; bottom: 8px; width: 2px; background: var(--rule); }
}

/* 16. Identity model */
.identity-model svg { width: 100%; height: auto; }
.identity-model .tiers { display: grid; gap: var(--s4); justify-items: center; }
.identity-model .tier { display: grid; gap: var(--s2); justify-items: center; text-align: center; }
.identity-model .tier-label { font-size: var(--t-label); font-weight: 600; }
.identity-model .box { padding: var(--s3) var(--s4); border-radius: var(--r-1); min-width: 180px; }
.identity-model .box[data-treat="customer"] { background: var(--ink); color: var(--white); }
.identity-model .box[data-treat="third"] { border: 1.5px dashed var(--ink-2); background: var(--white); }
.identity-model .box[data-treat="product"] { border: 2px solid var(--teal); background: var(--white); }
.identity-model .box[data-treat="instance"] { border: 1.5px dashed var(--ink-2); background: var(--white); min-width: 120px; }
.identity-model .box .sub { display: block; font-size: var(--t-small); font-weight: 400; margin-top: 2px; }
.identity-model .box[data-treat="customer"] .sub { opacity: 0.85; }
.identity-model .box .sub.mono { font-family: var(--mono); font-size: 13px; }
.identity-model .connector { width: 2px; height: var(--s5); background: var(--rule); }
.identity-model .instances { display: flex; flex-wrap: wrap; gap: var(--s3); justify-content: center; }
.identity-model .small-labels { display: flex; gap: var(--s4); font-size: var(--t-small); color: var(--ink-2); justify-content: center; flex-wrap: wrap; }

/* 17. Command block, raw artefact block, proof panel */
/* THE GROUND IS PINNED TO THE INSTRUMENT PALETTE, and it was --teal-deep until now.
   --teal-deep REMAPS on the dark site, to the bright accent, while --i-ink does not remap at all,
   so this block rendered near white on bright cyan at 1.66 to 1 wherever it appeared, which
   includes /estate through estate/entity-raw.ejs. It was designed as --i-ink on --i-ground, 10.28,
   and the contrast gate gates exactly that pair, so the gate reported a healthy pairing the
   stylesheet had stopped using. Same shape as the --on-brand defect: the token was gated and the
   usage was not. Every --i-* colour inside these two blocks was tuned against --i-ground, so
   pinning the ground restores all of them at once. */
.cmd { background: var(--i-ground); color: var(--i-ink); border-radius: var(--r-1); position: relative; }
/* THE COPY BUTTON STANDS IN ITS OWN GUTTER, AND IT USED TO STAND ON THE COMMAND.
 *
 * `.cmd pre` carried `padding-right: 84px` to hold the button off, and it never worked. A box with
 * `overflow-x: auto` does not honour its end padding: at scroll offset 0 the overflowing content
 * runs straight through that region, and the button is absolute over the top of it. Measured at the
 * edge on 24 September 2026, counting painted glyphs rather than boxes, at 1920 and at 1080: 8 and
 * 9 characters under the button on /architecture/deployment/evidence reading "nown/ope" out of
 * ".well-known/openid-federation", 24 and 27 on /governance/evidence, 16 and 16 on
 * /how-it-works/evidence, 88 and 99 on /use-cases/across-the-boundary/evidence, 32 and 36 on
 * /use-cases/find-and-trust/evidence. Every block on all nine routes that draw one.
 *
 * THE GUTTER MOVES TO THE PARENT, WHICH CAN HONOUR IT. `.cmd` does not scroll, so its padding is
 * real. The `pre` then ends 84px short and no command can reach the button at any scroll offset.
 * The button is absolute and positioned from the right, so it does not move.
 *
 * ONLY A BLOCK THAT HAS A BUTTON GIVES UP THE WIDTH. A response block is a second `.cmd` with no
 * button in it, and taking 84px off that one would be width lost for nothing. */
.cmd:has(.copy) { padding-right: 84px; }
.cmd pre { margin: 0; padding: var(--s4); overflow-x: auto; font-family: var(--mono); font-size: var(--t-mono); line-height: var(--t-mono-line); tab-size: 2; }
.cmd .prompt { color: var(--i-code-key); user-select: none; }
.cmd .key { color: var(--i-code-key); }
.cmd .ok { color: var(--i-ok); }
.cmd .no { color: var(--i-no); }
.cmd .copy { position: absolute; top: var(--s2); right: var(--s2); min-height: 36px; padding: 6px 12px; font: inherit; font-size: var(--t-label); font-weight: 600; background: var(--i-panel); color: var(--i-ink); border: 1px solid var(--i-rule); border-radius: var(--r-1); cursor: pointer; }
.cmd .copy:hover { background: var(--i-rule); }
.cmd + .cmd { margin-top: var(--s3); }
.raw { background: var(--i-ground); color: var(--i-ink); border-radius: var(--r-1); position: relative; }
/* The same shape as .cmd above, and the same correction. This block scrolls in both directions, so
   its end padding was honoured in neither. */
.raw:has(.copy) { padding-right: 84px; }
.raw pre { margin: 0; padding: var(--s4); overflow-x: auto; font-family: var(--mono); font-size: 13px; line-height: 1.6; max-height: 480px; overflow-y: auto; }
.raw .copy { position: absolute; top: var(--s2); right: var(--s2); min-height: 36px; padding: 6px 12px; font: inherit; font-size: var(--t-label); font-weight: 600; background: var(--i-panel); color: var(--i-ink); border: 1px solid var(--i-rule); border-radius: var(--r-1); cursor: pointer; }
.raw-fetch { margin-top: var(--s3); }
.raw-fetch .t-label { margin-bottom: var(--s2); }

.proof { background: var(--white); border-radius: var(--r-2); padding: var(--s5); display: grid; gap: var(--s4); }
.proof-head { display: grid; gap: var(--s2); }
.proof-head .claim { font-size: var(--t-h3); font-weight: 600; line-height: var(--t-h3-line); }
.proof-head .meta { display: flex; flex-wrap: wrap; gap: var(--s3) var(--s5); align-items: center; font-size: var(--t-small); color: var(--ink-2); }
.proof-body { display: grid; gap: var(--s3); }
.proof-body .label { font-size: var(--t-label); font-weight: 600; }
.proof-foot { font-size: var(--t-small); color: var(--ink-2); border-top: 1px solid var(--rule); padding-top: var(--s3); }
.diff { width: 100%; border-collapse: collapse; font-size: var(--t-small); }
.diff th { text-align: left; font-size: var(--t-label); font-weight: 600; padding: 8px 10px; border-bottom: 1px solid var(--rule); }
.diff td { padding: 8px 10px; border-bottom: 1px solid var(--rule); vertical-align: top; }
.diff td.name { font-family: var(--mono); font-size: var(--t-mono); }
.diff td.op { color: var(--ink-2); }
.diff tr[data-change="refused"] td { background: var(--wash-no); }
.diff .gone { text-decoration: line-through; color: var(--no); }
.diff .added { color: var(--ok); }
.diff .value { display: inline-flex; gap: 6px; align-items: center; }
.diff .value .mark { width: 13px; height: 13px; }
.diff .value .word { font-size: var(--t-label); font-weight: 600; }
@media (max-width: 620px) {
  .diff thead { display: none; }
  .diff tr { display: grid; grid-template-columns: 1fr; padding: var(--s2) 0; border-bottom: 1px solid var(--rule); }
  .diff td { border: 0; padding: 4px 0; }
  .diff td[data-col]::before { content: attr(data-col) ": "; color: var(--ink-2); font-size: var(--t-label); font-weight: 600; }
}

/* 18. Matrix and blast list */
.matrix-scroll { position: relative; overflow-x: auto; border: 1px solid var(--rule); border-radius: var(--r-1); background: var(--white); }
.matrix { border-collapse: separate; border-spacing: 0; min-width: 900px; width: 100%; font-size: var(--t-small); }
.matrix th, .matrix td { text-align: left; vertical-align: top; padding: 10px 12px; border-bottom: 1px solid var(--rule); background: var(--white); }
.matrix th { font-size: var(--t-label); font-weight: 600; }
.matrix th:first-child, .matrix td:first-child { position: sticky; left: 0; z-index: 1; box-shadow: inset -1px 0 0 var(--rule); }
.matrix tbody tr:last-child td { border-bottom: 0; }
.matrix-note { font-size: var(--t-small); color: var(--ink-2); margin-top: var(--s2); }
.matrix-wrap { position: relative; }
.matrix-wrap::after { content: ""; position: absolute; top: 0; bottom: 0; right: 0; width: 32px; pointer-events: none; background: linear-gradient(to left, var(--white), transparent); border-radius: 0 var(--r-1) var(--r-1) 0; }
@media (min-width: 1100px) { .matrix-note, .matrix-wrap::after { display: none; } }

.blast-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s5); }
.blast-list h3, .blast-list .head { font-size: var(--t-label); font-weight: 600; margin-bottom: var(--s2); }
.blast-list ul { list-style: none; display: grid; gap: 6px; }
.blast-list li { display: flex; gap: var(--s2); align-items: center; font-size: var(--t-small); }
.blast-list li .word { font-weight: 600; min-width: 4ch; }
.blast-list li[data-outcome="stays"] .word { color: var(--ok); }
.blast-list li[data-outcome="gone"] .word { color: var(--no); }
.blast-list li[data-outcome="gone"] .name { text-decoration: line-through; color: var(--ink-2); }
@media (max-width: 600px) { .blast-list { grid-template-columns: minmax(0, 1fr); } }

/* 19. Disclosure drawer */
.drawer { border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule); }
.drawer + .drawer { border-top: 0; }
.drawer > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: var(--s3); min-height: 48px; padding: 10px 0; font-size: var(--t-body); font-weight: 600; }
.drawer > summary::-webkit-details-marker { display: none; }
.drawer > summary .tri { width: 0; height: 0; border-top: 6px solid transparent; border-bottom: 6px solid transparent; border-left: 8px solid var(--teal-dark); transition: transform var(--m-drawer) ease; flex: none; }
.drawer[open] > summary .tri { transform: rotate(90deg); }
.drawer > summary:hover { color: var(--teal-dark); }
.drawer > .body { padding: var(--s3) 0 var(--s5); }
.drawer .drawer { margin-left: var(--s4); }
.drawer .drawer .drawer { margin-left: 0; }

/* 20. Launcher */
.launcher { display: grid; }
.launcher .group-head { font-size: var(--t-label); font-weight: 600; padding: var(--s3) 0 var(--s2); color: var(--ink-2); }
.launcher .row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--s3) var(--s5); padding: var(--s4) 0; border-top: 1px solid var(--rule); align-items: center; }
.launcher .row:last-child { border-bottom: 1px solid var(--rule); }
.launcher .row .title { font-size: var(--t-h3); font-weight: 600; line-height: var(--t-h3-line); }
.launcher .row:hover .title { text-decoration: underline; }
.launcher .row .line { font-size: var(--t-small); color: var(--ink-2); }
.launcher .row .host { font-family: var(--mono); font-size: var(--t-mono); overflow-wrap: anywhere; }
.launcher .row .actions { justify-content: flex-end; }
@media (max-width: 700px) { .launcher .row { grid-template-columns: minmax(0, 1fr); } .launcher .row .actions { justify-content: flex-start; } }

/* 21. Player
 *
 * THE FRAME IS DRAWN AND THE CONTROLS ARE THE BROWSER'S, and that split is a decision rather than
 * an omission. A buyer panel read /use-cases/across-the-boundary on 29 September 2026 and named the
 * player: a bare black rectangle with Chrome's own control bar across it. The frame answers that.
 * The controls do not move, because every film on this site ships a captions track and a chapters
 * track, and the native control bar is the only surface that reaches both from the keyboard. A
 * hand drawn bar would have to rebuild the captions menu, the volume control and the scrub keys
 * before it drew anything, and a player that looks better and captions worse is a worse player.
 *
 * WHAT THE FRAME ADDS. A brand hairline, an outer glow the same shape the hub card carries, and a
 * ground that is the page's rather than pure black, so the film sits on the page instead of
 * punching a hole in it. */
.player {
  border-radius: var(--r-2); overflow: hidden; aspect-ratio: 16 / 9; position: relative;
  background: var(--ink);
  border: 1px solid color-mix(in srgb, var(--teal-dark) 28%, transparent);
  box-shadow: 0 0 40px color-mix(in srgb, var(--teal-dark) 10%, transparent);
}
.player video { width: 100%; height: 100%; object-fit: contain; background: var(--ink); }
.player .unhosted { position: absolute; inset: 0; display: grid; place-content: end start; padding: var(--s5); color: var(--white); background: linear-gradient(to top, rgba(2, 12, 12, 0.85), transparent 60%); }
.player .unhosted img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: -1; }
.player .unhosted a { color: var(--white); }
.player-meta { display: flex; flex-wrap: wrap; gap: var(--s3) var(--s5); align-items: center; font-size: var(--t-small); color: var(--ink-2); margin-top: var(--s4); }
.player-meta a { overflow-wrap: anywhere; }

/* THE CHAPTER LIST IS A LIST, NOT A STACK OF LINKS.
 *
 * MEASURED, NOT REMEMBERED. Eight rows on /use-cases/across-the-boundary, every label brand cyan
 * and underlined, beside a mono timecode. Eight underlines in a 280px column read as a link farm,
 * and the only thing a reader can tell from the treatment is that all eight are the same. What a
 * reader wants from this column is the film's shape: when each part starts and what it covers.
 *
 * SO THE TIMECODE AND THE LABEL CARRY DIFFERENT JOBS AND DIFFERENT INK. The timecode is mono and
 * muted, because it is an index. The label is the page's own ink at reading weight, because it is
 * the content. Neither is underlined at rest. The row is the target and it lights on hover and on
 * focus, with a brand rail on its left edge, which says "this seeks the film" without spending a
 * link treatment on every line.
 *
 * THE SIZE HOLDS AT THE 14px FLOOR. The timecode was 13px and sat in the small font allow list of
 * packages/ui/tests/stylesheet.test.ts by name. It is running text in a reading column, so it takes
 * the floor and leaves the allow list. */
.chapters { list-style: none; display: grid; gap: 0; margin: 0; padding: 0; }
.chapters li { display: block; }
.chapters li + li { border-top: 1px solid var(--hairline); }
.chapters time {
  font-family: var(--mono); font-size: var(--t-label); font-variant-numeric: tabular-nums;
  /* --ink-2 AND NOT --faint. --faint is the faintest text token and reaches 4.17 against the page
     ground, under the 4.5 this system holds normal text to. At 13px in a decorative index that was
     arguable; at the 14px floor in a reading column it is running text, and packages/ui/src/parts/
     foot.css records the same correction for the same reason. */
  color: var(--ink-2); flex: 0 0 auto;
}
.chapters button {
  font: inherit; font-size: var(--t-label); line-height: 1.4; text-align: left;
  display: flex; align-items: baseline; gap: var(--s3);
  width: 100%; min-height: 40px; padding: var(--s3) var(--s3) var(--s3) var(--s2);
  background: none; border: 0; border-left: 2px solid transparent;
  color: var(--ink); text-decoration: none; cursor: pointer;
  transition: background 140ms ease, border-color 140ms ease;
}
.chapters-t { flex: 1 1 auto; min-width: 0; }
.chapters button:hover,
.chapters button:focus-visible { background: var(--wash-teal); border-left-color: var(--teal-dark); }
.chapters button:hover time,
.chapters button:focus-visible time { color: var(--teal-dark); }
@media (prefers-reduced-motion: reduce) { .chapters button { transition: none; } }
.transcript p + p { margin-top: var(--s3); }
.film-layout { display: grid; grid-template-columns: minmax(0, 1fr) 280px; gap: var(--s6); align-items: start; }
@media (max-width: 900px) { .film-layout { grid-template-columns: minmax(0, 1fr); } }
.film-saw { display: grid; gap: var(--s2); }
.film-saw .row { display: grid; grid-template-columns: auto 1fr; gap: var(--s4); padding: var(--s2) var(--s3); border-radius: var(--r-1); align-items: baseline; font-size: var(--t-small); }
.film-saw .row time { font-family: var(--mono); font-size: 13px; color: var(--ink-2); }
.film-saw .row .ev { margin-left: var(--s3); }

/* 22. Disclosure stack and the depth strip */
.stack-layout { display: grid; grid-template-columns: minmax(0, 1fr) 200px; gap: var(--s7); align-items: start; }
.stack { display: grid; gap: var(--s6); }
.stack > section { scroll-margin-top: 96px; }
.stack .layer-head { font-size: var(--t-h2); font-weight: 600; line-height: var(--t-h2-line); margin-bottom: var(--s3); }
.stack .drawer > summary { font-size: var(--t-h2); font-weight: 600; }
.depth { position: sticky; top: 88px; border-left: 2px solid var(--rule); padding-left: var(--s4); display: grid; gap: 4px; }
.depth .depth-title { font-size: var(--t-label); font-weight: 600; color: var(--ink-2); margin-bottom: var(--s2); }
.depth a { color: var(--ink-2); text-decoration: none; font-size: var(--t-small); font-weight: 600; padding: 6px 0; display: block; }
.depth a:hover { color: var(--teal-dark); text-decoration: underline; }
.depth a.is-current, .depth a[aria-current="true"] { color: var(--ink); }
@media (max-width: 900px) {
  .stack-layout { grid-template-columns: minmax(0, 1fr); }
  .depth { position: static; border-left: 0; padding-left: 0; display: flex; flex-wrap: wrap; gap: var(--s2) var(--s5); order: -1; border-bottom: 1px solid var(--rule); padding-bottom: var(--s3); }
  .depth .depth-title { width: 100%; margin: 0; }
}

/* 23. Instrument surface */
[data-surface="instrument"] { background: var(--surface-ground); color: var(--surface-ink); border-radius: var(--r-2); padding: var(--s5); }
[data-surface="instrument"] a { color: var(--surface-ink); }
[data-surface="instrument"] .ink-2, [data-surface="instrument"] .t-small { color: var(--surface-ink-2); }
[data-surface="instrument"] .i-panel { background: var(--surface-panel); border-radius: var(--r-1); padding: var(--s3) var(--s4); }
[data-surface="instrument"] .i-rule { border-color: var(--surface-rule); }
[data-surface="instrument"] .drawer { border-color: var(--surface-rule); }
[data-surface="instrument"] .drawer > summary .tri { border-left-color: var(--surface-teal); }
[data-surface="instrument"] .drawer > summary:hover { color: var(--surface-teal); }
[data-surface="instrument"] .cmd, [data-surface="instrument"] .raw { background: var(--i-far); }
[data-surface="instrument"] .wire-standard { stroke: var(--surface-ink-2); }
[data-surface="instrument"] .node[data-treat="reference"] { fill: var(--surface-panel); stroke: var(--surface-ink-2); }
[data-surface="instrument"] .node[data-treat="third"], [data-surface="instrument"] .node[data-treat="instance"] { fill: var(--surface-panel); stroke: var(--surface-ink-2); }
[data-surface="instrument"] .node[data-treat="customer"] { fill: var(--i-ink); stroke: var(--i-ink); }
[data-surface="instrument"] .node-label[data-treat="customer"] { fill: var(--i-ground); }
[data-surface="instrument"] .node-label[data-treat="reference"], [data-surface="instrument"] .node-label[data-treat="third"], [data-surface="instrument"] .node-label[data-treat="instance"] { fill: var(--surface-ink); }
[data-surface="instrument"] .figure svg text { fill: var(--surface-ink); }
[data-surface="instrument"] .figure svg text.small { fill: var(--surface-ink-2); }
[data-surface="instrument"] .state-line { color: var(--surface-ink-2); }
[data-surface="instrument"] .state-line.is-stale { color: var(--surface-att); }
[data-surface="instrument"] .wire-rule { stroke: var(--surface-rule); }

/* 24. Trust path */
.trust-path { display: grid; gap: var(--s4); }
.trust-path .path { display: flex; align-items: stretch; gap: 0; overflow-x: auto; }
.trust-path .hop { display: grid; gap: 6px; justify-items: center; text-align: center; min-width: 120px; flex: 1; position: relative; padding: 0 var(--s2); }
.trust-path .hop .node-box { padding: 8px 12px; border-radius: var(--r-1); font-size: var(--t-label); font-weight: 600; max-width: 100%; overflow-wrap: anywhere; }
.trust-path .hop .node-box[data-treat="product"] { background: var(--teal); color: var(--on-brand); }
.trust-path .hop .node-box[data-treat="customer"] { background: var(--ink); color: var(--white); }
.trust-path .hop .node-box[data-treat="reference"] { background: var(--white); color: var(--ink); border: 1.5px solid var(--bound); }
.trust-path .hop .node-box[data-treat="third"] { background: var(--white); color: var(--ink); border: 1.5px dashed var(--ink-2); }
.trust-path .hop .node-box[data-treat="standard"] { background: transparent; color: inherit; border: 1px dotted var(--ink-2); font-weight: 400; }
[data-surface="instrument"] .trust-path .hop .node-box[data-treat="customer"] { background: var(--i-ink); color: var(--i-ground); }
[data-surface="instrument"] .trust-path .hop .node-box[data-treat="reference"], [data-surface="instrument"] .trust-path .hop .node-box[data-treat="third"] { background: var(--surface-panel); color: var(--surface-ink); border-color: var(--surface-ink-2); }
[data-surface="instrument"] .trust-path .hop .node-box[data-treat="standard"] { border-color: var(--surface-ink-2); }
.trust-path .hop .kind { font-size: var(--t-small); color: var(--ink-2); }
[data-surface="instrument"] .trust-path .hop .kind { color: var(--surface-ink-2); }
.trust-path .hop .result { display: inline-flex; gap: 6px; align-items: center; font-size: var(--t-label); font-weight: 600; min-height: 20px; }
.trust-path .hop .result .mark { width: 14px; height: 14px; }
.trust-path .hop .result[data-result="ok"] { color: var(--ok); }
.trust-path .hop .result[data-result="no"] { color: var(--no); }
[data-surface="instrument"] .trust-path .hop .result[data-result="ok"] { color: var(--surface-ok); }
[data-surface="instrument"] .trust-path .hop .result[data-result="no"] { color: var(--surface-no); }
.trust-path .hop .n { font-size: var(--t-label); color: var(--ink-2); font-weight: 400; }
[data-surface="instrument"] .trust-path .hop .n { color: var(--surface-ink-2); }
.trust-path .hop + .hop::before { content: ""; position: absolute; left: -24px; top: 18px; width: 48px; border-top: 2px dotted var(--ink-2); }
[data-surface="instrument"] .trust-path .hop + .hop::before { border-top-color: var(--surface-ink-2); }
.trust-path[data-animate] .hop { opacity: 0; }
.trust-path[data-animate] .hop.is-shown { opacity: 1; transition: opacity var(--m-trust-path-hop) ease; }
.trust-path[data-animate] .hop .result { visibility: hidden; }
.trust-path[data-animate] .hop.is-checked .result { visibility: visible; }
.trust-path .reason { font-size: var(--t-small); color: var(--no); }
[data-surface="instrument"] .trust-path .reason { color: var(--surface-no); }
.trust-path .verdict { display: inline-flex; gap: var(--s2); align-items: center; font-weight: 600; }
.trust-path .verdict[data-result="ok"] { color: var(--ok); }
.trust-path .verdict[data-result="no"] { color: var(--no); }
[data-surface="instrument"] .trust-path .verdict[data-result="ok"] { color: var(--surface-ok); }
[data-surface="instrument"] .trust-path .verdict[data-result="no"] { color: var(--surface-no); }
.trust-path .hops-table { width: 100%; border-collapse: collapse; font-size: var(--t-small); }
.trust-path .hops-table th, .trust-path .hops-table td { text-align: left; padding: 6px 8px; border-bottom: 1px solid var(--rule); vertical-align: top; }
[data-surface="instrument"] .trust-path .hops-table th, [data-surface="instrument"] .trust-path .hops-table td { border-bottom-color: var(--surface-rule); }
.trust-path .hops-table td.mono { font-family: var(--mono); font-size: 13px; overflow-wrap: anywhere; }
@media (max-width: 700px) {
  .trust-path .path { flex-direction: column; overflow: visible; gap: var(--s4); }
  .trust-path .hop { justify-items: start; text-align: left; padding: 0 0 0 var(--s5); }
  .trust-path .hop + .hop::before { left: 6px; top: -28px; width: 0; height: 24px; border-top: 0; border-left: 2px dotted var(--ink-2); }
}

/* 25. Withdraw blast radius */
.blast { display: grid; gap: var(--s4); }
.blast .tree { display: grid; gap: var(--s5); justify-items: center; }
.blast .tree-row { display: flex; flex-wrap: wrap; gap: var(--s5); justify-content: center; }
.blast .subtree { display: grid; gap: var(--s4); justify-items: center; }
.blast .instances { display: flex; flex-wrap: wrap; gap: var(--s3); justify-content: center; }
.blast .bnode { display: inline-grid; grid-auto-flow: column; gap: 6px; align-items: center; padding: 6px 12px; border-radius: var(--r-1); font-size: var(--t-label); font-weight: 600; box-shadow: 0 0 0 2px transparent; }
.blast .bnode[data-treat="product"] { background: var(--teal); color: var(--on-brand); }
.blast .bnode[data-treat="customer"] { background: var(--i-ink); color: var(--i-ground); }
.blast .bnode[data-treat="reference"] { background: var(--surface-panel, var(--white)); color: inherit; border: 1.5px solid var(--surface-ink-2, var(--bound)); }
.blast .bnode[data-treat="third"] { background: var(--surface-panel, var(--white)); color: inherit; border: 1.5px dashed var(--surface-ink-2, var(--ink-2)); }
.blast .bnode[data-treat="instance"] { background: var(--surface-panel, var(--white)); color: inherit; border: 1.5px dashed var(--surface-ink-2, var(--ink-2)); font-weight: 400; }
.blast .bnode .mark { width: 13px; height: 13px; }
.blast .bnode[data-state="ok"] { box-shadow: 0 0 0 2px var(--surface-ok, var(--ok)); }
.blast .bnode[data-state="no"] { box-shadow: 0 0 0 2px var(--surface-no, var(--no)); opacity: 0.85; }
.blast .bnode[data-state="no"] .name { text-decoration: line-through; }
.blast .bnode[data-state="no"] .mark { color: var(--surface-no, var(--no)); }
.blast .bnode[data-state="ok"] .mark { color: var(--surface-ok, var(--ok)); }
.blast .bnode[data-treat="product"] .mark, .blast .bnode[data-treat="customer"] .mark { color: var(--ink); }
.blast .bnode[data-treat="customer"] .mark { color: var(--i-ground); }
.blast .bnode.is-changing { transition: box-shadow var(--m-blast-node) ease, opacity var(--m-blast-node) ease; }
.blast .edge { width: 2px; height: var(--s4); background: var(--surface-rule, var(--rule)); }
.blast .blast-list { padding-top: var(--s4); border-top: 1px solid var(--surface-rule, var(--rule)); }
.blast .blast-list .head { color: var(--surface-ink-2); }
.blast .blast-list li[data-outcome="stays"] .word { color: var(--surface-ok, var(--ok)); }
.blast .blast-list li[data-outcome="gone"] .word { color: var(--surface-no, var(--no)); }
.blast .blast-list li[data-outcome="gone"] .name { color: var(--surface-ink-2); }
.blast .controls { display: flex; flex-wrap: wrap; gap: var(--s3); justify-content: center; padding-top: var(--s3); border-top: 1px solid var(--surface-rule, var(--rule)); }
.blast .frames { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s4); }
.blast .frames .frame-title { font-size: var(--t-label); font-weight: 600; margin-bottom: var(--s2); }
@media (max-width: 600px) { .blast .frames { grid-template-columns: minmax(0, 1fr); } .blast .controls .btn { width: 100%; } }
.blast-layout { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); gap: var(--s5); align-items: start; }
@media (max-width: 900px) { .blast-layout { grid-template-columns: minmax(0, 1fr); } }

/* 26. Estate explorer */
.explorer { display: grid; grid-template-columns: 280px minmax(0, 1fr); gap: var(--s5); align-items: start; }
.explorer .list { background: var(--white); border-radius: var(--r-2); padding: var(--s4); display: grid; gap: var(--s3); }
.explorer .filters { display: flex; flex-wrap: wrap; gap: var(--s2); }
.explorer .filters a, .explorer .filters button { font: inherit; font-size: var(--t-label); font-weight: 600; padding: 6px 12px; min-height: 36px; border-radius: var(--pill); border: 1.5px solid var(--bound); background: var(--white); color: var(--ink); text-decoration: none; cursor: pointer; }
.explorer .filters [aria-pressed="true"], .explorer .filters [aria-current="true"] { background: var(--wash-teal); border-color: var(--teal-deep); color: var(--teal-deep); }
.explorer .entities { list-style: none; display: grid; gap: 2px; }
.explorer .entities li a { display: flex; gap: var(--s2); align-items: center; padding: 8px 6px; min-height: 40px; color: var(--ink); text-decoration: none; border-radius: var(--r-1); font-size: var(--t-small); }
.explorer .entities li a:hover { background: var(--paper); text-decoration: underline; }
.explorer .entities li a[aria-current="true"] { background: var(--wash-teal); }
.explorer .entities li.child a { padding-left: var(--s5); }
.explorer .record { background: var(--white); border-radius: var(--r-2); padding: var(--s5); display: grid; gap: var(--s4); }
.explorer .record .name { font-size: var(--t-h2); font-weight: 600; line-height: var(--t-h2-line); }
.explorer .record .id { font-family: var(--mono); font-size: var(--t-mono); overflow-wrap: anywhere; }
.explorer .record-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s4); }
.explorer .record-grid > div { border-top: 1px solid var(--rule); padding-top: var(--s2); font-size: var(--t-small); display: grid; gap: 4px; align-content: start; }
.explorer .record-grid .h { font-size: var(--t-label); font-weight: 600; }
.explorer .record-grid .mono { font-size: 13px; overflow-wrap: anywhere; }
.explorer .state-line { font-size: var(--t-small); color: var(--ink-2); display: inline-flex; gap: 6px; align-items: center; }
.explorer .state-line.is-stale { color: var(--att); }
.explorer .notice { background: var(--white); border-radius: var(--r-2); padding: var(--s5); font-size: var(--t-body); }
@media (max-width: 900px) { .explorer .record-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 700px) { .explorer { grid-template-columns: minmax(0, 1fr); } .explorer .record-grid { grid-template-columns: minmax(0, 1fr); } .explorer .graph-view { display: none; } }
.explorer .graph-note { display: none; font-size: var(--t-small); color: var(--ink-2); }
@media (max-width: 700px) { .explorer .graph-note { display: block; } }
.explorer .graph { background: linear-gradient(180deg, var(--i-far), var(--i-ground)); border-radius: var(--r-2); min-height: 360px; padding: var(--s4); }

/* 27. Journey card and journey header */
.journey-cards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s5); }
@media (max-width: 1040px) { .journey-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 700px) { .journey-cards { grid-template-columns: minmax(0, 1fr); } }
.journey-card { background: var(--white); border-radius: var(--r-2); padding: var(--s5); display: grid; gap: var(--s3); align-content: start; }
.journey-card .n { font-size: var(--t-small); color: var(--ink-2); font-variant-numeric: tabular-nums; }
.journey-card .title { font-size: var(--t-h3); font-weight: 600; line-height: var(--t-h3-line); }
.journey-card .title a { color: inherit; text-decoration: none; }
.journey-card:hover .title a { color: var(--teal-dark); text-decoration: underline; }
.journey-card .question { color: var(--ink-2); }
.journey-card .surfaces { font-size: var(--t-small); color: var(--ink-2); }
.journey-card .foot { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s4); align-items: center; font-size: var(--t-small); margin-top: var(--s2); }
.journey-head { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); gap: var(--s6); align-items: start; }
.journey-head .of { font-size: var(--t-small); color: var(--ink-2); }
.journey-head .chips { display: flex; flex-wrap: wrap; gap: var(--s2); }
.journey-head .side { display: grid; gap: var(--s4); }
@media (max-width: 900px) { .journey-head { grid-template-columns: minmax(0, 1fr); } }

/* 28. Call to action */
.cta { background: var(--wash-teal); border-radius: var(--r-2); padding: var(--s7) var(--s6); display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--s5); align-items: center; }
.cta .statement { font-size: var(--t-h2); font-weight: 600; line-height: var(--t-h2-line); max-width: 30ch; }
.cta .covers { font-size: var(--t-small); color: var(--ink-2); margin-top: var(--s2); }
@media (max-width: 700px) { .cta { grid-template-columns: minmax(0, 1fr); padding: var(--s6) var(--s5); } }
@media (max-width: 480px) { .cta .btn { width: 100%; } }

/* The footer: moved to src/parts/foot.css so it can be worked on alone. */


/* 30. Tables, generic */
.table { width: 100%; border-collapse: collapse; font-size: var(--t-small); background: var(--white); }
.table th, .table td { text-align: left; vertical-align: top; padding: 10px 12px; border-bottom: 1px solid var(--rule); }
.table th { font-size: var(--t-label); font-weight: 600; }

/* 31. Reduced motion: every animation off, every static equivalent on. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; scroll-behavior: auto !important; }
  .drawer > summary .tri { transition: none; }
  .drawer[open] > summary .tri { transform: rotate(90deg); }
  .wires .draw { stroke-dashoffset: 0 !important; animation: none !important; }
  .trust-path[data-animate] .hop { opacity: 1; }
  .trust-path[data-animate] .hop .result { visibility: visible; }
  .masthead { transition: none; }
}

/* 32. Print */
@media print {
  .masthead, .skip, .cmd .copy, .raw .copy, .blast .blast-list { padding-top: var(--s4); border-top: 1px solid var(--surface-rule, var(--rule)); }
.blast .blast-list .head { color: var(--surface-ink-2); }
.blast .blast-list li[data-outcome="stays"] .word { color: var(--surface-ok, var(--ok)); }
.blast .blast-list li[data-outcome="gone"] .word { color: var(--surface-no, var(--no)); }
.blast .blast-list li[data-outcome="gone"] .name { color: var(--surface-ink-2); }
.blast .controls { display: none; }
  body { background: var(--white); }
  .drawer[open] > .body, .drawer > .body { display: block; }
}

/* ---------------------------------------------------------------------------
   THE MARKETING SURFACE: the credibility strip, the four environments and the
   outcomes row. Three components the redesign added, used on the home page and
   reusable on the closing call to action.
   --------------------------------------------------------------------------- */

/* The credibility strip. Figures about Raidiam in production, with the line that
   says so directly under them. */
.credibility { margin-top: var(--s7); padding-top: var(--s5); border-top: 1px solid var(--rule); }
.credibility-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s5) var(--s8); }
.credibility .fig { display: grid; gap: 2px; }
/* THE FIGURE SIZE IS THE COMPONENT'S, AND IT IS STATED ONCE. It was stated three times: here, in
   hm.css for the home band and in why.css under `#proven`, and the id selector won on both routes
   whatever the other two said. Two files styling one block with different specificity is how a
   change lands on one page and not the other.
   24px, down from the h2 step, because the named ecosystems above this row now carry the large type.
   The CISO on the business panel of 16 September 2026: "the named ecosystems are set smaller than
   the four unattributable numbers directly above them. Swap the two credibility rows." A name a
   reader can verify in ten minutes outranks a number they take on trust. */
.credibility .fig .value { font-size: 24px; font-weight: 700; line-height: 1.1; color: var(--teal-dark); }
.credibility .fig .label { font-size: var(--t-label); color: var(--ink-2); }
.credibility .logos { margin-left: auto; display: flex; align-items: center; gap: var(--s5); }
.credibility .logos-lede { font-size: var(--t-label); font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-2); }
.credibility-note { margin: var(--s4) 0 0; font-size: var(--t-label); color: var(--ink-2); max-width: var(--measure-notes); }

/* The four environments. A four column row that becomes two, then one. */
/* The two column band the reference uses where a statement introduces a block of cards: the copy
   holds the left at about 0.8 and the cards take 1.2, and both stack at the tablet width. */
.band-split { display: grid; grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr); gap: var(--s6) var(--s8); align-items: start; }
.band-split > * { min-width: 0; }
.band-head-flush { margin-bottom: 0; }
@media (max-width: 1000px) { .band-split { grid-template-columns: minmax(0, 1fr); } }

/* TWO ACROSS, NOT FOUR. The reference puts the four cards in a 2x2 block beside the copy rather
   than in one row under it, which is what lets each card carry a 52px mark and four lines without
   the row going thin. The band that holds them supplies the two columns; see .band-split. */
.environments { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s4); }
.env-card {
  display: grid; align-content: start; gap: var(--s3);
  padding: var(--s5); background: var(--white); border: 1px solid var(--rule); border-radius: var(--r-3);
}
/* THE GLOSSY MARK, which is the reference's treatment rather than a plain image: a soft disc of the
   accent sits behind the artwork and the artwork's own edge is faded out with a radial mask, so a
   rendered icon with a hard square edge reads as lit from within rather than as a pasted sticker.
   The disc is a colour-mix of a token, so it names no colour and follows the palette.

   TWO CALLERS, ONE DECLARATION. The environment cards on / and the step cards on /how-it-works both
   draw this mark. The selector lists below name both rather than the part for /how-it-works copying
   the three rules, because two copies of one treatment drift and nothing here would go red when they
   did. A third caller adds a third selector; it does not add a fourth copy. */
.env-card .env-icon,
.hp-card .env-icon { position: relative; display: inline-flex; width: 52px; height: 52px; }
/* THE DISC IS A GRADIENT AND NOT A FLAT FILL, and that is the rule rather than a preference:
   packages/ui/tests/stylesheet.test.ts refuses a colour-mix in a flat background, because
   contrast.mjs gates token pairs by name and cannot see a mix at all, so text over one would be
   gated by nothing. A gradient is exempt because no text is laid on it. The first draft used a flat
   mix and the rule fired. */
.env-card .env-icon::before,
.hp-card .env-icon::before {
  content: ""; position: absolute; inset: 15%; border-radius: 50%;
  background: radial-gradient(circle, color-mix(in srgb, var(--teal-mid) 26%, transparent) 0%, transparent 70%);
  filter: blur(10px);
}
/* THE MASK IS BACK AND THE REASON IT IS NEEDED WAS MEASURED, not assumed. It was dropped on the
   reasoning that these renders carry their own alpha and the reference's mask was covering an edge
   that is not there. That was wrong: ffprobe reports rgba, but the corner pixel of
   icon-enterprise.png is 071424ff, fully opaque on a dark ground. So every mark drew a visible
   square against the card, which is one step lighter than the artwork's own ground. The reference
   masks for exactly this reason.
   IT FADES WITH A TOKEN RATHER THAN WITH BLACK. A mask reads alpha and ignores hue, so the colour
   named here is arbitrary; the colour rule refuses a literal, so it names --ink. Any opaque token
   produces the same mask. */
.env-card .env-icon img,
.hp-card .env-icon img {
  position: relative; width: 100%; height: 100%; object-fit: contain; display: block;
  -webkit-mask-image: radial-gradient(circle, var(--ink) 56%, transparent 74%);
  mask-image: radial-gradient(circle, var(--ink) 56%, transparent 74%);
}
.env-card h3 { margin: 0; }
.env-card ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s2); font-size: var(--t-small); color: var(--ink-2); }
@media (max-width: 1000px) { .environments { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .environments { grid-template-columns: minmax(0, 1fr); } }

/* The outcomes row. Numbered rather than iconned: a glyph invented for "less
   integration sprawl" would be decoration standing in for a thought. */
.outcomes { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s4); }
.outcome {
  display: grid; align-content: start; gap: var(--s2);
  padding: var(--s5) var(--s5) var(--s6); background: var(--white);
  border: 1px solid var(--rule); border-radius: var(--r-3);
}
.outcome .outcome-n { font-family: var(--mono); font-size: var(--t-label); color: var(--teal-dark); letter-spacing: 0.08em; }
.outcome h3 { margin: 0; }
.outcome p { margin: 0; color: var(--ink-2); }
.outcomes-closing { margin-top: var(--s5); }
@media (max-width: 1000px) { .outcomes { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .outcomes { grid-template-columns: minmax(0, 1fr); } }

/* ---- src/parts/ab.css ---- */
/*
 * /use-cases/across-the-boundary. `ab-` is this page's prefix and nothing else on the site uses it,
 * so this part cannot reach another component and another component cannot reach it. Checked
 * against every other file in src/parts and against apps/site/src/public/site.css, which loads
 * AFTER the bundle and would beat anything here at equal specificity: site.css carries .actions,
 * .btn, .eyebrow, .hero, .two-col and .people, and none of those names appears below.
 *
 * MEASURED ON 16 SEPTEMBER 2026 FROM THE RUNNING REFERENCE, http://127.0.0.1:4561/use-cases/03 at a
 * 1440 viewport, with getBoundingClientRect and getComputedStyle rather than from a picture. Source:
 * /tmp/claude-501/rw-live/app/use-cases/03/page.tsx.
 *
 *   band box            1280, gutters 32, so the content measure is 1216
 *   hero band           padding top 56
 *   hero grid           minmax(0, 460px) 1fr, gap 48, items centred, row height 460
 *   figure box          560 wide, 460 tall, centred in the second column
 *   eyebrow             13px / 600 / 0.28em, brand
 *   headline            52px / 700 / line 1.04 / tracking -0.03em, second sentence in brand
 *   lead                margin top 20, max width 440, 17px / line 1.6, #aebdd2
 *   actions             margin top 32, gap 16
 *   benefit band        padding top 64, then a hairline and 48 more
 *   benefit column      equal columns, padding inline 24, a hairline before each but the first
 *   benefit ring        56 by 56, 1px brand at 40 percent
 *   benefit title       margin top 16, 18px / 700
 *   benefit body        margin top 8, 14px / line 1.55, max width 260
 *   example band        padding top 64
 *   example panel       radius 16, 1px line, padding 40, grid 1fr auto, gap 40, items centred
 *   example eyebrow     12px / 600 / 0.24em          the chip 12px on a full pill
 *   example heading     margin top 20, 28px / 700 / line 1.15 / tracking -0.02em, max width 440
 *   example body        margin top 16, 15px / line 1.6, max width 520
 *   example link        margin top 24, 14px / 600
 *   example diagram     radius 12, 1px line, padding 32, on the alternate ground
 *   example box         48 by 48, radius 12, 1px
 *   summary band        padding top 24, padding bottom 16
 *   summary bar         radius 16, 1px line, padding 28 / 32, gap 20
 *   summary ring        48 by 48
 *   summary sentence    18px / line 1.375, the row ink, its first clause bold and primary
 *
 * WHERE THE REFERENCE GOES UNDER THE FLOOR, THIS HOLDS AT 14px. It sets 13px on the eyebrow and the
 * orb label, 12.5px on the chip and 12px on the diagram labels. A size below the floor is a
 * readability rule rather than a style choice and packages/ui/tests/stylesheet.test.ts enforces it
 * across the whole bundle, so every one of those is var(--t-label).
 *
 * THE COLOUR IS THE HOUSE TOKEN AND THE REFERENCE'S IS NOT COPIED. Reference 03 draws its filled
 * action in #2a7fff on a 12px radius, which is the blue this site used before the reset. CLAUDE.md
 * states the brand is cyan and the buttons are full pills, and the same reference build's own
 * components/use-case/use-case-hero.tsx draws the pill. site.css already implements it, so the two
 * actions in the hero carry no rule here at all.
 *
 * THE REFERENCE'S GREEN IS NOT USED ANYWHERE ON THIS PAGE, and that is an accuracy rule rather than
 * a taste one. Green means Observed on this site, an Observed mark links its artefact, and every
 * verdict the instrument prints is worked out from the estate declaration with nothing read on a
 * wire. packages/ui/tests/stylesheet.test.ts gates it: var(--ok) is permitted only under
 * data-ev="observed", data-state="ok" and four other selectors, and this file writes none of them.
 *
 * WHAT IS DRAWN INSTEAD is the treatment /live already uses for the same problem. Each verdict
 * carries a source chip reading Derived or Declared, a refusal takes var(--no) on a left border,
 * and a permitted row carries the WORD "Inside your ceiling" rather than a colour on its own.
 */

/*
 * A FLAT GROUND UNDER TEXT IS A PLAIN TOKEN AND NEVER A MIX. The reference writes bg-panel/50 and
 * bg-panel/40 on its panels, which is the panel colour at part opacity over the page ground.
 * packages/ui/tools/contrast.mjs enumerates TOKEN PAIRS BY NAME and can see nothing whatever about
 * a colour-mix, so text on one is gated by nothing at all, and packages/ui/tests/stylesheet.test.ts
 * refuses it. Every panel here therefore takes var(--white), the panel token, and the cards inside
 * a panel take var(--paper-alt), which is the same one step of separation the reference draws.
 * A mix stays where the test permits it: a border, a gradient and a shadow.
 */

/* ---- The page box -------------------------------------------------------------------------- */

/* THE MEASURE IS THE STANDARD PAGE'S, 1472, FROM THE SECOND PASS ON 29 SEPTEMBER 2026. It was the
   reference route's 1216, and the headline moved 80px sideways between this tab and
   /use-cases/your-own-assistant, whose .oa-page sets 1472, while the instrument lost 160px. */
.abp { --page-max: 1472px; }

/* THE BASE RULE IS NOT TOUCHED. `.band` is shared by seventeen routes and gives every one of them a
   top rule and 64px above and below. This page draws one rule only, over the benefit row, and each
   band sets its own top padding from the measurement table above. */
.wrap.abp > .band { border-top: 0; padding-block: var(--s8) 0; }
.wrap.abp > .abp-top { padding-block: 3.5rem 0; }
.wrap.abp > .abp-tail { padding-block: var(--s7) var(--s8); }
.wrap.abp > .band:last-child { padding-bottom: var(--s8); }

/* ---- 1. The hero: the copy, then the instrument ---------------------------------------------

   THE SHAPE IS /use-cases/your-own-assistant's, NOT THE REFERENCE ROUTE'S, from the second pass on
   29 September 2026. The copy sits on top and the crossing takes the full measure under it, so the
   figure fills the first screen at 1440. From 1100 up the copy is two columns, the headline beside
   the lead and the actions, which keeps the band above the figure short. Below 1100 it stacks.

   THE HEADLINE KEEPS THE SCALE'S SIZE AND ITS UNBROKEN ACCENT. `.t-display, h1.t-display` is one
   class and one element, so the selector carries two classes; the token resolves through
   packages/ui/src/parts/display-scale.css. A break inside "With trust." would leave one word alone
   on the last line, so the accent does not wrap. */
.abp-top { display: grid; gap: var(--s6); }
.abp-top-copy > * { margin: 0; }
.abp-eyebrow { font-size: var(--t-label); font-weight: 600; letter-spacing: 0.22em; text-transform: uppercase; color: var(--teal-dark); }
.abp-top-copy .abp-headline { margin-top: var(--s4); max-width: none; font-size: var(--t-display); line-height: 1.02; letter-spacing: -0.035em; }
.abp-top-copy .abp-headline .accent { white-space: nowrap; }
.abp-lead { margin-top: 20px; max-width: 34rem; font-size: 17px; line-height: 1.55; color: var(--ink-lead); text-wrap: pretty; }
.abp-lead > * { margin: 0; }
.abp-actions { margin-top: var(--s5); gap: var(--s4); }
.abp-top-figure { min-width: 0; display: grid; gap: var(--s5); }
@media (min-width: 1100px) {
  .abp-top-copy { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: var(--s7); grid-template-areas: "eyebrow eyebrow" "head lead" "head actions"; align-items: start; }
  .abp-top-copy .abp-eyebrow { grid-area: eyebrow; }
  .abp-top-copy .abp-headline { grid-area: head; }
  .abp-top-copy .abp-lead { grid-area: lead; margin-top: var(--s4); }
  .abp-top-copy .abp-actions { grid-area: actions; }
}

/* ---- 2. The benefit row -------------------------------------------------------------------- */

/*
 * packages/ui/partials/ab-outcomes.ejs draws it and every number below is the reference's. The
 * reference runs three columns, each centred, with a hairline down the left of every one but the
 * first, and it opens the band with a hairline and 48px of air. This estate declares four
 * mechanisms rather than three, and four is also what the same reference build's own benefit row
 * carries in components/use-case/use-case-benefits.tsx.
 *
 * AT 1216 FOUR COLUMNS ARE 304 WIDE, measured, which is wide enough for an 18px title on two lines
 * and a 260px body. The rule CLAUDE.md records is that copying the reference's absolute numbers at
 * 1440 left cards 155px wide and broke titles mid word; the proportion is copied here and the
 * measure is checked.
 */
.abp-ben { border-top: 0; }
.abo { border-top: 1px solid var(--hairline); padding-top: var(--s7); }
.abo-h {
  margin: 0 auto var(--s6);
  max-width: 24ch; text-align: center; text-wrap: balance;
  font: 700 28px / 1.15 var(--sans);
  letter-spacing: -0.02em;
  color: var(--ink);
}
.abo-row {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  margin: 0; padding: 0; list-style: none;
}
.abo-card {
  display: grid; justify-items: center; text-align: center;
  align-content: start;
  padding-inline: var(--s5);
}
/* The divider between columns is the reference's: a hairline on every column but the first. */
.abo-card + .abo-card { border-left: 1px solid var(--hairline); }
.abo-badge {
  display: grid; place-items: center;
  width: 56px; height: 56px; border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--teal-dark) 40%, transparent);
  color: var(--teal-dark);
}
.abo-badge svg { width: 28px; height: 28px; }
.abo-t { margin: var(--s4) 0 0; font: 700 18px / 1.5 var(--sans); letter-spacing: normal; color: var(--ink); text-wrap: balance; }
.abo-l { margin: var(--s2) 0 0; max-width: 260px; font-size: var(--t-label); font-weight: 400; line-height: 1.55; color: var(--ink-2); }

@media (max-width: 900px) {
  .abo-row { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: var(--s6); }
  .abo-card:nth-child(odd) { border-left: 0; }
}
@media (max-width: 560px) {
  .abo-row { grid-template-columns: minmax(0, 1fr); }
  .abo-card { border-left: 0; }
}

/* ---- 3. The gateway instrument, drawn on the evidence route ---------------------------------- */

/* The figure. A container query rather than a media query: the same component answers for its own
   width wherever it is drawn, and the viewport says nothing about that. */
.ab { container-type: inline-size; display: grid; gap: var(--s5); }

/* ---- The two controls ---------------------------------------------------------------------- */

.ab-controls { display: grid; gap: var(--s4); }

/* The scenario strip. One rounded box with hairline dividers.

   IT COUNTS ITS OWN TABS. This rule wrote `repeat(3, minmax(0, 1fr))` while the page declared three
   scenarios, so the strip was a three column grid and the content file decided whether the third
   column held a tab. The page declares two now, and a fixed third column drew a blank third of the
   box with a divider beside it, which reads as a control that failed to render. `grid-auto-flow`
   with equal auto columns lays out however many tabs the figure is given. */
.ab-tabs {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  border: 1px solid var(--hairline);
  border-radius: var(--r-2);
  background: var(--paper-alt);
  overflow: hidden;
}
.ab-tab {
  appearance: none;
  margin: 0;
  border: 0;
  border-left: 1px solid var(--hairline);
  padding: var(--s3) var(--s4);
  background: transparent;
  font: 600 var(--t-label) / var(--t-label-line) var(--sans);
  color: var(--ink-2);
  cursor: pointer;
  text-align: center;
}
.ab-tab:first-child { border-left: 0; }
.ab-tab:hover { color: var(--ink); }
.ab-tab[aria-selected="true"] {
  background: var(--wash-teal);
  color: var(--ink);
  box-shadow: inset 0 -2px 0 var(--teal-dark);
}
.ab-tab:focus-visible { outline: 2px solid var(--teal-dark); outline-offset: -2px; }

.ab-policy { margin: 0; border: 0; padding: 0; display: grid; gap: var(--s2); }
.ab-policy-legend { padding: 0; font-size: var(--t-label); font-weight: 600; color: var(--ink-2); }
.ab-policy-opts { display: flex; flex-wrap: wrap; gap: var(--s2); }
.ab-opt { display: inline-flex; }
.ab-opt-label {
  display: inline-block;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  padding: 8px 14px;
  background: var(--paper-alt);
  font-size: var(--t-label);
  font-weight: 600;
  color: var(--ink-2);
  cursor: pointer;
}
.ab-opt input:checked + .ab-opt-label { background: var(--wash-teal); border-color: color-mix(in srgb, var(--teal-dark) 45%, transparent); color: var(--ink); }
.ab-opt input:focus-visible + .ab-opt-label { outline: 2px solid var(--teal-dark); outline-offset: 2px; }

/* ---- The three columns --------------------------------------------------------------------- */

/* The instrument is the widest object on the page and it is the reason the band takes the full
   1216. The arrows between the columns are decorative, so they collapse first. */
.ab-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 24px minmax(0, 1.15fr) 24px minmax(0, 1fr);
  gap: var(--s4);
  align-items: start;
}
.ab-col {
  display: grid;
  align-content: start;
  gap: var(--s3);
  border: 1px solid var(--hairline);
  border-radius: var(--r-3);
  padding: var(--s5);
  background: var(--white);
}
.ab-col > * { margin: 0; }
.ab-col-h { font-size: var(--t-label); font-weight: 600; letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink-2); }

.ab-arrow { align-self: center; height: 1px; background: var(--hairline); }

/* The portrait. A glyph over a picture with a dotted link between them, which says in a shape what
   the facts below say in words: an organisation you do not run, and under it an agent it issued.

   THE BLEND AND THE MASK REMOVE THE JPEG'S SQUARE. The asset is a glowing robot on a near black
   ground, so it arrives as a visible square on any panel. Taken from wr-ring.css, which paid for it. */
.ab-portrait { position: relative; display: grid; justify-items: center; gap: var(--s2); padding-block: var(--s2); }
.ab-portrait-g { display: grid; place-items: center; width: 40px; height: 40px; color: var(--teal-dark); }
.ab-portrait-g svg { width: 32px; height: 32px; }
.ab-portrait-link { width: 1px; height: 18px; background: repeating-linear-gradient(to bottom, var(--rule) 0 3px, transparent 3px 6px); }
/* THE AGENT IS DRAWN, NOT PHOTOGRAPHED. This was a 96px circle holding /img/agent-robot.jpg, with a
   screen blend and a radial mask whose only job was to hide the square the JPEG arrived in. The
   image is gone and packages/ui/partials/ped.ejs stands the agent glyph in a pool of the column's
   own hue instead, so the blend and the mask went with it: there is no square left to hide. See the
   note at the call site in packages/ui/partials/ab-gateway.ejs. */
.ab-portrait-a { width: 100%; }
.ab-portrait-solo { padding-block: var(--s4); }

.ab-org { display: flex; align-items: center; gap: var(--s2); font-size: var(--t-h3); font-weight: 600; line-height: 1.3; color: var(--ink); }
.ab-i { display: grid; place-items: center; flex: none; color: var(--teal-dark); }
.ab-i svg { width: 20px; height: 20px; }

.ab-facts { display: grid; gap: var(--s3); margin: 0; padding: 0; list-style: none; }
.ab-facts li { display: flex; gap: var(--s2); align-items: start; }
.ab-fact-t { display: block; font-size: var(--t-label); color: var(--ink-2); }
.ab-fact-v { display: block; font-size: var(--t-label); font-weight: 600; line-height: 1.45; color: var(--ink-row); overflow-wrap: anywhere; }
.ab-brings { font-size: var(--t-label); line-height: 1.5; color: var(--ink-2); }

/* ---- The four checks ----------------------------------------------------------------------- */

.ab-checks { display: grid; gap: var(--s3); margin: 0; padding: 0; list-style: none; counter-reset: ab-check; }
.ab-check {
  border: 1px solid var(--hairline);
  border-radius: var(--r-2);
  padding: var(--s3) var(--s4);
  background: var(--paper-alt);
}
.ab-check-h { margin: 0 0 var(--s2); font-size: var(--t-label); font-weight: 600; color: var(--ink); }
.ab-verdict {
  margin: 0;
  border-left: 2px solid var(--rule);
  padding-left: var(--s3);
  font-size: var(--t-label);
  line-height: 1.5;
  color: var(--ink-lead);
}
/* A REFUSAL TAKES THE REFUSAL COLOUR AND A PASS TAKES NONE. There is no var(--ok) anywhere on this
   page: nothing here was read on a wire, so nothing here may wear the colour that means it was. */
.ab-verdict[data-state="no"] { border-left-color: var(--no); }
.ab-verdict[data-state="off"] { color: var(--ink-2); }
.ab-src {
  display: inline-block;
  margin-right: var(--s2);
  border: 1px solid var(--hairline);
  border-radius: 999px;
  padding: 1px 8px;
  font-size: var(--t-label);
  font-weight: 600;
  color: var(--ink-2);
  vertical-align: baseline;
}

/* ---- What it asked for, and what it may do ------------------------------------------------- */

.ab-asks { font-size: var(--t-label); color: var(--ink-2); }
.ab-reqs { display: grid; gap: var(--s2); margin: 0; padding: 0; list-style: none; }
.ab-req { border: 1px solid var(--hairline); border-radius: var(--r-2); padding: var(--s3); background: var(--paper-alt); }
.ab-req-h { margin: 0 0 6px; display: flex; flex-wrap: wrap; gap: var(--s2); align-items: baseline; font-size: var(--t-label); }
.ab-req-h code { font-size: var(--t-label); color: var(--ink-row); }
.ab-req-tool { font-size: var(--t-label); color: var(--ink-2); }
.ab-req-v { margin: 0; font-size: var(--t-label); font-weight: 600; color: var(--ink-lead); }
.ab-req-v[data-state="no"] { color: var(--no); }
.ab-req-v[data-state="off"] { color: var(--ink-2); }

/* THE LINE THE WHOLE FIGURE EXISTS TO PRODUCE. It takes the panel treatment of the summary bar at
   the foot of the page, because it is the same kind of statement: the one thing to leave with. */
.ab-effect {
  border: 1px solid color-mix(in srgb, var(--teal-dark) 35%, transparent);
  border-radius: var(--r-3);
  padding: var(--s4);
  background: var(--wash-teal);
}
.ab-effect-h { margin: 0 0 6px; font-size: var(--t-label); font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-2); }
.ab-effect-v { margin: 0; font-size: var(--t-h3); line-height: 1.35; color: var(--ink); overflow-wrap: anywhere; }
.ab-effect-v code { font-size: var(--t-label); color: var(--ink-row); }
.ab-effect-v[data-state="no"] { color: var(--ink-lead); }

.ab-note { margin: 0; font-size: var(--t-label); line-height: 1.5; color: var(--ink-2); }

/* THE NARROW STATE OF THE INSTRUMENT IS DESIGNED. Three columns of prose cannot hold their measure
   under about 900, so the arrows go and the columns read down the page in the order a platform
   performs them: what arrived, what you checked, what you allowed. */
@container (max-width: 900px) {
  .ab-grid { grid-template-columns: minmax(0, 1fr); }
  .ab-arrow { display: none; }
}

/* ---- The tail ------------------------------------------------------------------------------ */

/* The close, the handover and a limitation if the page declares one. The reference has none of
   these: it ends on the summary bar and then the footer. They are kept because a claim page with no
   way to the working session sells nothing, and because a limitation belongs beside the claim it
   qualifies rather than one link away. */
.abp-tail { border-top: 0; }

/* ---- The live panel, which this page no longer draws ---------------------------------------- */

/*
 * packages/ui/partials/ab-try.ejs is rendered by the gallery and by nothing else. The band it sat in
 * printed the two bounds the estate declares for the first pair and then linked /live, which the
 * instrument above already draws in all three control positions and which the first action in the
 * hero already links. It is styled here so the inventory shows the component rather than a pile of
 * unstyled text, and it should be deleted with its gallery example when the lead is ready.
 */
.abt { display: grid; gap: var(--s5); border: 1px solid var(--hairline); border-radius: var(--r-3); padding: var(--s6); background: var(--white); }
.abt-copy > * { margin: 0; }
.abt-h { color: var(--ink); }
.abt-actions { margin-top: var(--s4); }
.abt-card { display: grid; gap: var(--s2); justify-items: start; border: 1px solid var(--hairline); border-radius: var(--r-2); padding: var(--s4); background: var(--paper-alt); }
.abt-row { display: flex; gap: var(--s2); align-items: center; margin: 0; }
.abt-i { display: grid; place-items: center; flex: none; color: var(--teal-dark); }
.abt-i svg { width: 20px; height: 20px; }
.abt-row-b { display: grid; gap: 2px; min-width: 0; }
.abt-row-t { font-size: var(--t-label); font-weight: 600; color: var(--ink-row); }
.abt-row-s { font-size: var(--t-label); color: var(--ink-2); }
.abt-down { width: 1px; height: 16px; margin-left: 10px; background: repeating-linear-gradient(to bottom, var(--rule) 0 3px, transparent 3px 6px); }
.abt-bounds { display: grid; gap: var(--s3); margin: 0; }
.abt-bound { display: grid; gap: 2px; border-left: 2px solid var(--rule); padding-left: var(--s3); }
.abt-bound dt { font-size: var(--t-label); color: var(--ink-2); }
.abt-bound dd { margin: 0; font-size: var(--t-label); color: var(--ink-row); overflow-wrap: anywhere; }
.abt-src { display: inline-block; margin-right: var(--s2); border: 1px solid var(--hairline); border-radius: 999px; padding: 1px 8px; font-size: var(--t-label); font-weight: 600; color: var(--ink-2); }

/* ---- THE IDENTITY HUES ---------------------------------------------------------------------- */

/*
 * WHAT THIS SECTION IS. One place that says which of the four identity hues each set of peers on
 * this page carries, and which parts of each object read it. Three sets take one: the five parties
 * in the hero figure, the three columns of the gateway instrument, and the four cards in the
 * outcome row.
 *
 * WHY THE PAGE NEEDS IT. Measured at 1440 on 16 September 2026 with getComputedStyle over every
 * element in `main`, this route drew ZERO of the four, and twelve of twenty one routes drew none.
 * Ralph: "the entire site has gone blue monocromatic". The instrument is the object two of the four
 * business readers named as the thing they wanted to talk about, and its three columns were three
 * identical panels in one colour, so a reader had to read a heading to know which column they were
 * in.
 *
 * WHAT AN IDENTITY HUE IS, AND WHAT IT IS NOT. --d-blue, --d-violet, --d-magenta and --d-sand carry
 * no meaning anywhere in this system. They answer WHICH ONE of a set of peers this is. A STATE
 * colour answers what is TRUE of a thing and always sits beside the word that says it: green means
 * Observed, amber means in progress, red means refused. So the hues below land on a column head, an
 * icon and a lit top edge, and they never land on a verdict. The instrument's own refusal keeps
 * var(--no) on its left border with the refusal written beside it, which is unchanged.
 *
 * THE ASSIGNMENT IS POSITIONAL AND IT LIVES HERE. The three instrument columns take a hue by class
 * because the classes already name the three parties; the orbs and the outcome cards take one by
 * position, so a content file cannot pick a colour and no label is tied to one.
 *
 * CONTRAST, computed from packages/ui/tokens/tokens.json with the formula in
 * packages/ui/tools/contrast.mjs. All four are gated against the three dark grounds at the 4.5 TEXT
 * floor rather than the 3 of a graphic, so a column head may be set in one. On d-card, the lightest
 * ground and therefore the one that decides: d-blue 7.35, d-violet 6.62, d-magenta 10.16 and
 * d-sand 10.41.
 */

/* The three columns of the gateway instrument, in the order a platform performs them: what arrived,
   what you checked, what you allowed. */
.ab .ab-them { --hue: var(--d-blue); }
.ab .ab-decide { --hue: var(--d-violet); }
.ab .ab-yours { --hue: var(--d-sand); }

/* The panel lit from above by its own hue, which is the reference's card treatment: a hairline on
   three sides, the hue on the top edge, and the same hue as an inset highlight under it. The three
   other sides stay the hairline token, so the column is still one of a family. */
.ab .ab-col {
  border-top-color: var(--hue);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--hue) 35%, transparent);
}
.ab .ab-col .ab-col-h { color: var(--hue); }
/* Every mark inside a column belongs to that column: the organisation, the facts it brings, the
   surface it asks for. They were all one brand cyan, which is what made three columns read as one. */
.ab .ab-col .ab-i { color: var(--hue); }
.ab .ab-col .ab-portrait-g { color: var(--hue); }

/* The four cards in the outcome row. Each names a mechanism the instrument above draws, and the
   hues say four rather than one repeated four times. The ring keeps the reference's soft edge and
   the glyph inside it carries the colour. */
.abo .abo-card { --hue: var(--d-blue); }
.abo .abo-card:nth-child(2) { --hue: var(--d-violet); }
.abo .abo-card:nth-child(3) { --hue: var(--d-magenta); }
.abo .abo-card:nth-child(4) { --hue: var(--d-sand); }
.abo .abo-badge {
  border-color: color-mix(in srgb, var(--hue) 45%, transparent);
  color: var(--hue);
}

/* ---- src/parts/arch-deployment.css ---- */
/* /architecture/deployment. View: apps/site/src/views/deployed.ejs.

   WHAT THIS FILE IS. What this route adds to the shared architecture shape: the hero over its
   instrument, the lead that comes out of a markdown section, and the band of four answer cards.
   The instrument is dpx.css. The close is .ah- classes in architecture-pages.css, which the
   architecture routes share.

   THE FOUR HUES, AND WHAT THEY MEAN. --d-blue, --d-violet, --d-magenta and --d-sand mean nothing on
   their own. That is the whole reason this page can use them: the four answer cards are four peers,
   and a hue here says WHICH OF THE FOUR IS THIS and carries no grade, no status and no warning. A
   state colour answers what is TRUE of a thing and always sits beside a word; none of these does.
   Green and red are not in the set, because green means Observed on this site and an Observed mark
   links its artefact, and red means refused. The hue reaches a card as --hue and lands on two
   surfaces: the card's top edge, which is the reference build's environment card lit from above,
   and the ringed glyph, which is its benefits row. It reaches no card row and no word.

   WHERE THE MEASUREMENTS COME FROM. app/architecture/page.tsx and app/how-it-works/page.tsx in the
   reference build, and the two ported routes that copy them, packages/ui/src/parts/arch-page.css
   and hiw.css. The named numbers below are theirs:
     The benefits band: section pt-16, a rule, 40px, a 30px/700/-0.02em heading, 8px to a 15px line,
     32px to the row of ringed glyphs, a 52px ring, 16px to a 16px title, 4px to its line.
     A card: radius 16, padding 24, a 1px edge, a 17px/700 title and a 14px second line.
     A labelled row: a 14px term at secondary ink over a 14px value at row ink.
     A panel: radius 12, padding 24, a brand edge at low alpha and an uppercase 0.18em title.

   WHAT IT REFUSES TO DRAW. A hero photograph, a legend above the figure, a tab strip over the four
   answers, a disclosure of any kind, and a green tick on a card row. A card row carries no mark at
   all: the evidence for every claim this page makes is on /evidence, where the mark links its
   artefact. A hue on a row's value, for the reason stated above. A hued ground under any word,
   because the contrast gate reads a token pair by name and a hue is not one of the pairs it holds.

   EVERY SELECTOR STARTS .ad- AND SITS UNDER .ad-page, so nothing here can reach another route's
   markup.

   NO COLOUR LITERAL IS WRITTEN HERE, no size under 14px, and no colour-mix in a flat background
   under text. The contrast gate reads token pairs by name and can see through neither a mix nor a
   gradient, so every ground under a word below is a plain token.

   WHAT HAPPENS AT 1300, 1100, 1000 AND 700. The four cards drop from four columns to two and then to
   one, the hero copy drops to one column under 1100, and the instrument (dpx.css) stacks its two
   panels under 1000. A hue is set by position and survives every one of those, because a stacked
   card keeps its place in the list.
   ================================================================ */

/* THE MEASURE, stated once for this page. It was 1036px until 29 September 2026, set to match
   /architecture when that page took 1036. /architecture now takes 1472px (ax.css .ax-page), and a
   child route narrower than its parent read as a different section. The instrument is two panels
   of four tiles each, which needs the width. */
.ad-page { --page-max: 1472px; }

/* ================================================================
   The hero: the statement, the lead and the split figure.
   ================================================================ */

/* THE HERO. The copy takes two columns above 1100, the headline on the left and the lead and the
   actions on the right, over the full width instrument. It is the rhythm /architecture and
   /use-cases/your-own-assistant draw, so the section reads as one thing. */
.ad-page .ad-top { position: relative; padding-block: 3.5rem 0; }
.ad-page .ad-copy > * { margin: 0; }
.ad-page .ad-eyebrow { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s3); letter-spacing: 0.22em; }
.ad-page .ad-eyebrow-rule { width: 1px; height: 14px; background: var(--rule); }
.ad-page .ad-eyebrow-accent { color: var(--ink-2); }
.ad-page .ad-statement { margin-top: var(--s4); max-width: 22ch; text-wrap: balance; }
/* TWO SENTENCES, AND THE SECOND ONE CARRIES THE ACCENT on a line of its own, so the break falls at
   the full stop rather than wherever the measure runs out. */
.ad-page .ad-statement .accent { display: block; }
.ad-page .ad-side { margin-top: var(--s5); display: grid; gap: var(--s5); }
@media (min-width: 1100px) {
  .ad-page .ad-copy { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); column-gap: 64px; grid-template-areas: "eyebrow eyebrow" "head side"; align-items: start; }
  .ad-page .ad-eyebrow { grid-area: eyebrow; }
  .ad-page .ad-statement { grid-area: head; }
  .ad-page .ad-side { grid-area: side; margin-top: var(--s5); }
}

/* The lead is a rendered markdown section, so a paragraph arrives with its own margin. */
.ad-page .ad-lead > p { margin: 0; }
.ad-page .ad-lead > p + p { margin-top: var(--s3); }

/* ================================================================
   The four answers: the band a procurement reader came for.
   ================================================================ */

/* The band opens on a rule with 40px under it, which is the reference's benefits row exactly. The
   band's own top rule is removed so there is one line rather than two. */
.ad-page .ad-answers { padding-block: var(--s8) 0; border-top: 0; }
.ad-page .ad-answers-in { border-top: 1px solid var(--hairline); padding-top: 40px; }

.ad-page .ad-answers-h {
  margin: 0;
  font-size: 30px; line-height: 1.2; font-weight: 700; letter-spacing: -0.02em;
  color: var(--ink);
  max-width: 24ch;
}
.ad-page .ad-answers-lead {
  margin: var(--s2) 0 0;
  max-width: 56ch;
  font-size: var(--t-small); line-height: var(--t-small-line);
  color: var(--ink-lead);
}

/* FOUR COLUMNS ABOVE 1300, TWO BELOW, ONE BELOW 700. Inside the old 1036px measure four tracks left
   232px and "federation.directory.showcase.raidiam.io" broke in three places, so the band was two
   columns. At the 1472px measure four tracks leave about 320px at 1440, which holds that hostname
   on one line, and the four questions read as the reference's benefits row. */
.ad-page .ad-cards {
  list-style: none; margin: var(--s6) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s5);
  /* EACH CARD IS ITS OWN HEIGHT. The four carry three to five rows and two of them carry a note, so
     a stretched row sized both cards to the taller one and the shorter card held 180px of empty
     ground between its last row and its link. Measured at 1440 on 16 September 2026. A card is a
     separate object with its own hue and its own edge, so a ragged bottom edge reads as four cards
     rather than as a broken grid, which is what the void read as. */
  align-items: start;
}
/* ONE HUE PER CARD, BY POSITION. The four cards are the four questions and nothing separates them
   but which question they answer, so the hue is an identity and the order is the order of the list.
   It is set here rather than on a key, because a rule keyed to `where` or `region` would say the
   hue belongs to the subject: it does not, and the day a question is reworded the hue must stay
   where it is. A fifth card would take --d-blue a second time, so deployed.ejs throws on any
   number but four. */
.ad-page .ad-cards > .ad-card:nth-child(1) { --hue: var(--d-blue); }
.ad-page .ad-cards > .ad-card:nth-child(2) { --hue: var(--d-violet); }
.ad-page .ad-cards > .ad-card:nth-child(3) { --hue: var(--d-magenta); }
.ad-page .ad-cards > .ad-card:nth-child(4) { --hue: var(--d-sand); }

/* A COLUMN, so the blocks of a card stack at one rhythm. The link used to be pushed to the foot
   with an auto margin so the link rows lined up across a row; the cards size to their own content
   now, so there is no slack to push it through and the link sits under the last row.

   THE TOP EDGE CARRIES THE HUE AND THE OTHER THREE DO NOT. It is the reference build's environment
   card: a panel lit from above, with the top border tinted to the environment's hue and the rest of
   the edge left at the page rule. A full hue border on all four sides turns a card into a warning,
   which is the one thing an identity hue must never do. */
.ad-page .ad-card {
  min-width: 0;
  display: flex; flex-direction: column; gap: var(--s4);
  padding: var(--s5);
  border: 1px solid var(--rule);
  border-top-color: var(--hue, var(--rule));
  border-radius: 16px;
  background: var(--paper-alt);
  /* THE CARD IS LIT FROM ABOVE, which is the reference build's environment card. A 1px hue border
     on the top edge alone is one pixel against a dark ground and reads as nothing; the inset
     highlight under it is what makes the edge visible. It is a shadow rather than a background, so
     no word on this card sits on anything but the flat token above. */
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--hue, var(--rule)) 55%, transparent);
}
.ad-page .ad-card-head { display: flex; align-items: center; gap: var(--s4); }
/* THE RING AND ITS GLYPH TAKE THE CARD'S HUE. .rw-ring is the reference's 52px circle and it sets
   its own border and colour from the brand, so both are restated here from --hue. The glyph strokes
   with currentColor, so the colour on the ring is the colour of the drawing inside it and there is
   one declaration rather than two that can disagree.

   THE GLOW AND THE DROP SHADOW ARE THE REFERENCE'S PEDESTAL, flattened to a circle: an icon
   standing on light, in the light of its own hue. packages/ui/src/parts/arch-page.css draws the
   same two on .arc-chip and .arc-tile-i, at the same strengths. */
.ad-page .ad-card-ring {
  flex: none;
  border-color: var(--hue, var(--teal-dark));
  color: var(--hue, var(--teal-dark));
  box-shadow: 0 0 22px color-mix(in srgb, var(--hue, var(--teal-dark)) 22%, transparent);
}
.ad-page .ad-card-ring .sc-glyph { display: inline-flex; color: inherit; }
.ad-page .ad-card-ring svg { filter: drop-shadow(0 0 8px var(--hue, var(--teal-dark))); }
.ad-page .ad-card-q {
  margin: 0; min-width: 0;
  font-size: 17px; font-weight: 700; line-height: 1.3;
  color: var(--ink);
}
/* THE ANSWER IS THE SENTENCE A READER LEAVES WITH, so it is the largest text in the card after the
   question and it is set in the primary ink rather than a lead tone. */
.ad-page .ad-card-a {
  margin: 0;
  font-size: 16px; line-height: 1.5;
  color: var(--ink);
}

/* A LABELLED ROW IS STACKED HERE RATHER THAN JUSTIFIED. The other three architecture routes set a
   term at the left and its value at the right, which is right for a two word value. Four of the
   values in this band are hostnames of about forty characters and one is a whole sentence, and a
   justified row put each of them against the right edge with a ragged gap in the middle. The
   stacked form is the same pair of tokens and the same two sizes, and it is what every one of those
   routes already falls back to below 560. */
.ad-page .ad-card-rows {
  margin: 0;
  display: grid; gap: var(--s3);
  padding-top: var(--s4);
  border-top: 1px solid var(--hairline);
}
.ad-page .ad-card-row { display: grid; gap: 2px; min-width: 0; }
.ad-page .ad-card-row dt {
  font-size: var(--t-label); font-weight: 400; line-height: 1.4;
  color: var(--ink-2);
}
/* --ink-row IS THE COLOUR OF A VALUE beside a dimmer label, which is what every row here is.
   The value wraps rather than overflows: a hostname has no space in it, so a long one would push
   the card's track past the viewport without this. */
.ad-page .ad-card-row dd {
  margin: 0;
  font-size: var(--t-label); font-weight: 500; line-height: 1.45;
  color: var(--ink-row);
  overflow-wrap: anywhere;
}

.ad-page .ad-card-note {
  margin: 0;
  font-size: var(--t-label); line-height: 1.5;
  color: var(--ink-2);
}

/* The links out of a card, in the site's one arrow form. 24px minimum on each, because a link here
   sits alone with no sentence around it: neither exemption in WCAG 2.2 clause 2.5.8 applies. */
.ad-page .ad-card-more { margin: 0; display: flex; flex-wrap: wrap; gap: var(--s2) var(--s5); }
.ad-page .ad-card-more a {
  display: inline-flex; align-items: center; gap: var(--s2);
  min-height: 24px;
  font-size: var(--t-label); line-height: 1.4;
  color: var(--teal-dark); text-decoration: none;
}
.ad-page .ad-card-more a::before {
  content: ""; display: block;
  width: 16px; height: 11px; flex: none;
  background: currentColor;
  -webkit-mask: var(--arrow-right) center / contain no-repeat;
  mask: var(--arrow-right) center / contain no-repeat;
}
.ad-page .ad-card-more a:hover { text-decoration: underline; text-underline-offset: 0.14em; }

/* ================================================================
   /architecture/deployment/evidence, the working behind the claim.
   View: apps/site/src/views/deployed-evidence.ejs.

   IT TAKES THE CLAIM PAGE'S MEASURE. A reader here has followed a link to check something, so the
   page is a heading, a way back, a figure per claim with the claim as its caption, the rows and the
   reads. The figures are dpe.css.
   ================================================================ */

.ad-page.ad-ev .ad-ev-head { padding-bottom: 0; }
.ad-page.ad-ev .ad-ev-head .t-display { margin: var(--s3) 0 0; max-width: 20ch; }
.ad-page.ad-ev .ad-ev-lead {
  margin: var(--s4) 0 0; max-width: 58ch;
  font-size: var(--t-small); line-height: var(--t-small-line);
  color: var(--ink-lead);
}
.ad-page.ad-ev .ad-ev-back { margin: var(--s5) 0 0; }

.ad-page.ad-ev .ad-ev-band { padding-block: var(--s7) 0; border-top: 0; }
.ad-page.ad-ev .ad-ev-h { margin: 0 0 var(--s5); }
.ad-page.ad-ev .ad-ev-read { max-width: var(--measure-notes); margin-bottom: var(--s5); }

/* THE CLAIM PARAGRAPH IS THE FIGURE'S CAPTION: under it, at the lead's size, one measure wide. */
.ad-page.ad-ev .ad-ev-caption { margin-top: var(--s5); max-width: 78ch; }
.ad-page.ad-ev .ad-ev-caption > * { margin: 0; }
.ad-page.ad-ev .ad-ev-caption [data-claim] { font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-lead); }

/* ================================================================
   The narrow states.
   ================================================================ */

@media (max-width: 1299px) {
  .ad-page .ad-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 700px) {
  .ad-page .ad-cards { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 560px) {
  .ad-page .ad-card { padding: var(--s4); }
  .ad-page .ad-answers-h { font-size: 24px; }
}

/* ---- src/parts/arch-environment.css ---- */
/* /architecture/environment. View: apps/site/src/views/environment.ejs.

   WHAT THIS FILE IS. The page around the three instruments, which are styled in enm.css: the hero,
   the bands, the four drawers that hold the tables, a table that scrolls sideways rather than
   squeezing, and the list of limits. The hero is the shared .sc- shape the use case pages use.

   A TECHNICAL ROUTE, AND VISUAL FIRST SINCE 29 SEPTEMBER 2026. It was tables and numbered prose
   with no figure. The figures live in enm.css; this file keeps the tables, which are the rows the
   map is drawn from, and puts each one in a drawer.

   THE FOUR HUES DO IDENTITY WORK AND NOTHING ELSE, and they are set on the figures, not here. Green
   and red state colours are not used, because green means Observed on this site and this page makes
   no such claim.

   WHY THE TABLE SCROLLS RATHER THAN WRAPS. The agents table carries seven columns and the widest
   cell is an entity identifier. Squeezing it breaks an identifier mid word. .en-scroll is the one
   element allowed its own horizontal scroll; the page body never scrolls sideways.

   NO SIZE UNDER 14px. NO COLOUR LITERAL, and no colour-mix in a flat ground under text.

   EVERY SELECTOR STARTS .en- AND SITS UNDER .en-page, so nothing here reaches another route.
   ================================================================ */

.en-page {
  padding-block: 0 0;
}

.en-head {
  position: relative;
}

/* ABOVE 1100 THE COPY TAKES TWO COLUMNS: the headline on the left, the lead and the actions on the
   right, which is the rhythm /architecture and /use-cases/your-own-assistant draw over their
   instruments. */
@media (min-width: 1100px) {
  .en-copy {
    display: grid;
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    column-gap: 64px;
    grid-template-areas: "eyebrow eyebrow" "head side";
    align-items: start;
  }
  .en-copy > .sc-eyebrow { grid-area: eyebrow; }
  .en-headline { grid-area: head; }
  .en-side { grid-area: side; margin-top: 0; padding-top: 12px; }
}

.en-lead {
  max-width: 68ch;
}

/* THE LEAD SITS 20px UNDER THE HEADLINE WHEN THEY STACK. The two column rule below sets the gap only
   above 1100, and under it the headline's last line touched the lead. */
.en-side {
  margin-top: 20px;
}

.en-table code {
  font-size: 14px;
  overflow-wrap: anywhere;
}

/* ---- a band, its heading and its read line ---------------------------------------------- */

.en-band {
  padding-block: 48px 0;
}

.en-h {
  margin: 0 0 8px;
}

.en-sub,
.en-note {
  color: var(--ink-muted);
  font-size: 15px;
  line-height: 1.55;
  max-width: 68ch;
  margin: 0 0 20px;
}

.en-note {
  margin: 16px 0 0;
}

.en-read {
  max-width: 68ch;
  margin-bottom: 20px;
}

/* ---- the tables ------------------------------------------------------------------------- */

/* The one element on this page allowed to scroll sideways, and the page body still may not. */
.en-scroll {
  overflow-x: auto;
  border: 1px solid var(--rule);
  border-radius: 14px;
}

.en-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
  min-width: 860px;
}

.en-table th {
  text-align: left;
  color: var(--ink-faint);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.02em;
  padding: 12px 16px;
  border-bottom: 1px solid var(--rule);
  white-space: nowrap;
}

.en-table td {
  color: var(--ink-muted);
  padding: 12px 16px;
  border-bottom: 1px solid var(--rule);
  vertical-align: top;
  line-height: 1.5;
}

.en-table tbody tr:last-child td {
  border-bottom: 0;
}

.en-table td code {
  color: var(--ink);
}

/* The purpose a stand in serves, on its own line. Run on after the treatment it read as one
   sentence: "reference implementation stands in for a third party, a software publisher". */
.en-stands {
  display: block;
  color: var(--ink-faint);
  margin-top: 4px;
}

/* ---- the workload definitions ------------------------------------------------------------ */

.en-defs {
  display: grid;
  gap: 12px;
  margin: 0;
  padding: 20px;
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: 14px;
}

.en-defs > div {
  display: grid;
  grid-template-columns: 220px minmax(0, 1fr);
  gap: 16px;
}

.en-defs dt {
  color: var(--ink-faint);
  font-size: 14px;
}

.en-defs dd {
  color: var(--ink-muted);
  font-size: 14px;
  margin: 0;
  overflow-wrap: anywhere;
}

/* ---- the drawers that hold the tables ------------------------------------------------------ */

.en-drawer {
  border-top: 1px solid var(--rule);
}

.en-drawer:last-of-type {
  border-bottom: 1px solid var(--rule);
}

.en-drawer > summary {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 18px 0;
  cursor: pointer;
  list-style: none;
  color: var(--ink);
  font-size: 17px;
  font-weight: 600;
}

.en-drawer > summary::-webkit-details-marker {
  display: none;
}

.en-drawer > summary::before {
  content: "";
  width: 8px;
  height: 8px;
  flex: 0 0 auto;
  border-right: 2px solid var(--brand-strong);
  border-bottom: 2px solid var(--brand-strong);
  transform: rotate(-45deg);
  transition: transform 160ms ease;
}

.en-drawer[open] > summary::before {
  transform: rotate(45deg);
}

.en-drawer[open] {
  padding-bottom: 24px;
}

@media (prefers-reduced-motion: reduce) {
  .en-drawer > summary::before {
    transition: none;
  }
}

/* ---- the limits -------------------------------------------------------------------------- */

.en-limits {
  padding-bottom: 64px;
}

.en-limit-list {
  margin: 0;
  padding-left: 20px;
  display: grid;
  gap: 12px;
  max-width: 78ch;
}

.en-limit-list li {
  color: var(--ink-muted);
  font-size: 15px;
  line-height: 1.55;
}

@media (max-width: 1000px) {
  .en-defs > div {
    grid-template-columns: minmax(0, 1fr);
    gap: 4px;
  }
}

/* THE EYEBROW'S TWO HALVES, divided by a hairline rule as /architecture draws its own. The shared
   .sc-eyebrow sets them with a space only, and "ENVIRONMENT FOUR PLACES" read as one phrase. */
.en-page .en-copy .sc-eyebrow-n {
  display: inline-block;
  margin-left: 10px;
  padding-left: 14px;
  border-left: 1px solid var(--rule);
  color: var(--ink-muted);
}

/* ---- src/parts/arch-page.css ---- */
/* /architecture, the index of the section. View: apps/site/src/views/architecture.ejs. Partials:
   packages/ui/partials/arc-instrument.ejs and packages/ui/partials/arc-orbit.ejs.

   WHAT THIS FILE IS. The whole of one route, rebuilt on 16 September 2026 from Ralph's comp at
   /Users/ralphbragg/Downloads/arch+sec.png, whose left half is this page. It holds the two column
   hero with the globe, the four column instrument, the four destination cards and the closing band.

   WHAT IT REPLACED, AND WHY. A centred head over a strip of four controls, a stack of three cards
   and a panel of statement rows and labelled tables. Ralph read that page beside the comp and said
   two things. The first: "It's the colours which you've removed from nearly every site." This route
   measured ZERO of the four identity hues on 16 September, so every tile, every outcome and every
   card below carries one. The second: this is a marketing page. A claim page is a headline, one
   short explanation, the instrument, the outcome row and one call to action, and the four panels of
   procedure went to the technical routes that already carry them.

   THE FOUR IDENTITY HUES ARE THE DESIGN, AND THEY ARE NOT STATE COLOURS. --d-blue, --d-violet,
   --d-magenta and --d-sand mean nothing on their own, which is exactly what lets them separate four
   kinds of thing. Green means Observed on every surface of this site, amber means in progress and
   red means refused, so none of the three appears here. A hue arrives on an element as --hue, which
   is what the shared treatments in packages/ui/src/parts/rw.css read.

   THE TREATMENTS ARE PORTED RATHER THAN APPROXIMATED, and they come from rw.css: .rw-card is the
   environment card lit from above by its own hue, .rw-hub is the object every connector leaves,
   .rw-glow is the ambient pool that stops the ground reading flat. This file sets their sizes and
   the type inside them and draws nothing of its own that rw.css already draws.

   WHERE IT HOLDS AT 14px. The comp sets 12px and 13px on a tile label, on a column head and on its
   tracked lines. The floor is a readability rule rather than a style choice, so all of them are
   14px here and packages/ui/tests/stylesheet.test.ts enforces it.

   WHAT IT REFUSES TO DRAW. A green tick beside a row. A state colour anywhere. A card ground behind
   the hero copy. A second photograph: the closing band carries the one picture on this page that
   the hero does not.

   EVERY SELECTOR STARTS .arc- AND SITS UNDER .arc-page, .arc-flow OR .arc-orbit, so nothing here
   can reach the three child routes, whose classes start .arch-, .rt-, .as- or .ad-.

   WHAT HAPPENS AT 1180, AT 900 AND AT 560. The instrument turns its four columns into two rows of
   two and the arrows turn to point down. The hero drops to one column and the globe goes under the
   copy. The destination cards step to two columns and then to one. Every grid track is
   minmax(0, 1fr), so a long label cannot push a track past the viewport.
   ================================================================ */

/* ================================================================
   The hue cycle. One rule set, read by every hued thing on the page.

   IT IS POSITIONAL AND IT LIVES HERE RATHER THAN IN THE CONTENT FILE, so a label cannot be tied to
   a colour and a content edit cannot pick one. Four hues over a column of five repeat at the fifth,
   which is the only arrangement that keeps neighbours apart without spending a fifth meaning.
   ================================================================ */

.arc-page .arc-tile:nth-child(4n + 1),
.arc-page .arc-out:nth-child(4n + 1),
.arc-page .arc-card:nth-child(4n + 1),
.arc-page .arc-chip:nth-child(4n + 1) { --hue: var(--d-blue); }
.arc-page .arc-tile:nth-child(4n + 2),
.arc-page .arc-out:nth-child(4n + 2),
.arc-page .arc-card:nth-child(4n + 2),
.arc-page .arc-chip:nth-child(4n + 2) { --hue: var(--d-violet); }
.arc-page .arc-tile:nth-child(4n + 3),
.arc-page .arc-out:nth-child(4n + 3),
.arc-page .arc-card:nth-child(4n + 3),
.arc-page .arc-chip:nth-child(4n + 3) { --hue: var(--d-magenta); }
.arc-page .arc-tile:nth-child(4n + 4),
.arc-page .arc-out:nth-child(4n + 4),
.arc-page .arc-card:nth-child(4n + 4),
.arc-page .arc-chip:nth-child(4n + 4) { --hue: var(--d-sand); }

/* ================================================================
   1. The hero: copy beside the globe.
   ================================================================ */

/* THE TOP PADDING IS 64 RATHER THAN 48, and that is a measurement rather than taste. The figure
   column is taller than the copy column, so the three tracked lines sit at the top of the band, and
   at 48 they rendered under the masthead at 1440. */
.arc-hero { position: relative; overflow: hidden; padding-block: var(--s8) var(--s6); }

/* THE COPY COLUMN LEADS AND THE FIGURE FOLLOWS IT, at the comp's proportion rather than its pixels.
   The comp is drawn wider than 1440 and this site may not scroll sideways, so the split is stated
   as a ratio and the measure on the statement stops the headline running the whole track. */
/* THE TWO COLUMNS START TOGETHER RATHER THAN CENTRE TOGETHER. The figure is 560 tall and the copy
   is 435, so centring pushed the eyebrow 100px down the band and left the headline sitting in the
   middle of the page. Aligned to the start, the eyebrow and the three tracked lines share one line,
   which is the shape the comp draws. */
.arc-hero-in {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 0.82fr);
  gap: var(--s7); align-items: start;
}

.arc-hero-copy { min-width: 0; }

/* THE EYEBROW IS TWO WORDS WITH A RULE BETWEEN THEM: the section, then the subject of the page in
   the brand colour. */
.arc-eyebrow { margin: 0; letter-spacing: 0.24em; }
.arc-eyebrow-rule { margin: 0 var(--s2); color: var(--faint); }
.arc-eyebrow-accent { color: var(--teal-dark); }

/* THE STATEMENT. --t-display is the site's 54px step. The accent is its own block, so the sentence
   breaks at its comma rather than wherever the measure runs out, and both blocks are balanced
   because this headline is a whole sentence where the comp's is four words.

   19ch IS MEASURED, NOT CHOSEN. At 1440 the copy column is 721 wide. At 17ch the headline rendered
   619 wide over FIVE lines, and the white clause broke into three short ragged lines above two long
   brand ones. At 19ch it renders 692 wide over four, which is the shape the comp draws. The measure
   is in ch rather than px so it shrinks with the display step at narrower widths. */
.arc-page .arc-statement {
  margin: var(--s4) 0 0;
  max-width: 19ch;
  text-wrap: balance;
}
.arc-page .arc-statement .accent { display: block; text-wrap: balance; }
/* The accent carries the comp's bloom. It is a text shadow of a brand token at the strength the
   reference build sets, so it follows the palette and names no colour. */
.arc-page .arc-statement .accent { text-shadow: 0 0 28px color-mix(in srgb, var(--teal-mid) 50%, transparent); }

/* The lead is a rendered markdown section, so a paragraph arrives with its own margin.
   --ink-lead IS THE COLOUR, one step above secondary text. A lead set in --ink-2 reads as a
   caption, which is what every builder reached for before this token existed. */
.arc-lead {
  margin: 20px 0 0;
  max-width: 54ch;
  color: var(--ink-lead);
  font-size: var(--t-body); line-height: 1.6;
}
.arc-lead > p { margin: 0; }
.arc-lead > p + p { margin-top: var(--s3); }

/* TWO CONTROLS IN ONE ROW, WHICH IS ONE GESTURE. They stacked on the route this replaced because
   the copy column was too narrow to hold them side by side. */
.arc-hero .arc-actions { margin-top: var(--s6); }

.arc-hero-fig { min-width: 0; display: grid; justify-items: end; gap: var(--s4); }

/* THE THREE TRACKED LINES IN THE CORNER. The comp sets them above the globe, hard right. */
.arc-tagline {
  margin: 0;
  text-align: right;
  font-size: var(--t-label); font-weight: 600; line-height: 2;
  letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--ink-2);
}

/* ================================================================
   The globe and its chips. Partial: packages/ui/partials/arc-orbit.ejs.

   THE BOX IS SQUARE AND THE CHIPS ARE PLACED IN PERCENTAGES OF IT, so a chip and the part of the
   globe it names stay together at every width. A non square box would move the sphere under the
   chips without moving the chips.
   ================================================================ */

.arc-orbit { position: relative; width: 100%; max-width: 560px; aspect-ratio: 1 / 1; }
.arc-orbit-glow { top: 12%; width: 86%; height: 60%; }
.arc-orbit-globe {
  position: relative; z-index: 1;
  display: block; width: 100%; height: 100%;
  object-fit: contain;
}

.arc-orbit-chips { position: absolute; inset: 0; z-index: 2; list-style: none; margin: 0; padding: 0; }

/* THE CHIP. A pill on a flat token ground, because a label sits on it and packages/ui/tools/
   contrast.mjs gates a pair of tokens by name and can read nothing through a mix or a gradient. */
.arc-chip {
  position: absolute;
  display: inline-flex; align-items: center; gap: var(--s2);
  padding: 7px 14px 7px 10px;
  border-radius: var(--pill);
  border: 1px solid color-mix(in srgb, var(--hue, var(--teal-dark)) 45%, transparent);
  background: var(--white);
  box-shadow: 0 0 22px color-mix(in srgb, var(--hue, var(--teal-dark)) 22%, transparent);
  font-size: var(--t-label); font-weight: 600; line-height: 1.3;
  color: var(--ink);
  white-space: nowrap;
}
.arc-chip-i { display: inline-flex; color: var(--hue, var(--teal-dark)); }
.arc-chip-i svg { width: 17px; height: 17px; display: block; }

/* The five positions. The comp scatters them over the top and right of the sphere and lets two
   overhang its limb, which is what keeps the group from reading as a list. */
.arc-chip[data-at="nw"] { top: 17%; left: 2%; }
.arc-chip[data-at="ne"] { top: 26%; right: 0; }
.arc-chip[data-at="e"] { top: 47%; right: 4%; }
.arc-chip[data-at="w"] { top: 58%; left: 0; }
.arc-chip[data-at="se"] { top: 73%; right: 12%; }

/* ================================================================
   2. The instrument: four columns joined by arrows, in one panel.
   ================================================================ */

.arc-instrument-band { border-top: 0; padding-block: var(--s6) 0; }

.arc-flow { position: relative; }
.arc-flow-glow { top: 8%; width: 70%; height: 46%; }

/* THE PANEL. One border, one radius, a gradient ground. The gradient is allowed to carry a mix
   because a gradient is outside what the contrast gate can name either way; what the rule protects
   is the flat fill a paragraph lands on, and every one of those below is a plain token. */
.arc-flow-panel {
  position: relative; z-index: 1;
  border: 1px solid var(--hairline);
  border-radius: 18px;
  background: linear-gradient(180deg, color-mix(in srgb, var(--paper-alt) 92%, transparent) 0%, color-mix(in srgb, var(--paper) 92%, transparent) 100%);
  padding: var(--s6);
}

/* THE FOUR COLUMNS AT THE COMP'S PROPORTION. The environment column is the narrowest on the comp
   because its tiles carry one word each, and the outcome column is the widest because its rows
   carry two lines. The arrow tracks are fixed, so a wide viewport grows the columns and not the
   gaps between them. */
.arc-flow-in {
  display: grid;
  grid-template-columns: minmax(0, 1.12fr) 36px minmax(0, 1.06fr) 36px minmax(0, 0.82fr) 36px minmax(0, 1.14fr);
  gap: var(--s4);
  align-items: start;
}

.arc-col { min-width: 0; display: grid; align-content: start; gap: var(--s4); }

/* THE COLUMN HEAD. Tracked and uppercase, as the comp draws it, and at the 14px floor. */
.arc-col-h {
  margin: 0;
  font-size: var(--t-label); font-weight: 600; line-height: 1.5;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--ink-2);
}
/* THE SENTENCE UNDER A COLUMN IS THE BOUNDARY CLAIM, and it is the reason this figure is not a row
   of labelled boxes. It sits under the tiles rather than over them, so a reader meets the things
   first and then what Connect does and does not do to them. */
.arc-col-s {
  margin: 0;
  font-size: var(--t-label); line-height: 1.5;
  color: var(--ink-2);
}

/* The tiles. Two across in the agents column, one across in the narrower infrastructure column. */
.arc-tiles { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s3); }
.arc-tiles-tight { grid-template-columns: minmax(0, 1fr); gap: var(--s2); }

/* .rw-card carries the gradient, the hairline and the hue lit top edge. This sets the shape only. */
.arc-page .arc-tile {
  display: grid; justify-items: center; gap: var(--s2);
  padding: var(--s4) var(--s3);
  text-align: center;
}
.arc-page .arc-tiles-tight .arc-tile {
  grid-template-columns: auto minmax(0, 1fr);
  justify-items: start; align-items: center;
  text-align: left;
  padding: var(--s3) var(--s4);
}
.arc-tile-i { display: inline-flex; color: var(--hue, var(--teal-dark)); }
/* THE GLYPH IS LIT IN ITS OWN HUE, which is the fourth layer of the target's pedestal treatment
   reduced to what a tile this size can carry. A drop shadow takes no space and cannot be read by a
   contrast instrument, so nothing depends on it. */
.arc-tile-i svg { width: 22px; height: 22px; display: block; filter: drop-shadow(0 0 8px var(--hue, var(--teal-dark))); }
.arc-tile-t { font-size: var(--t-label); font-weight: 600; line-height: 1.35; color: var(--ink); }

/* THE STANDARDS BOX. The comp puts it under the identity column, and every name in it is a link to
   the route on this site that shows that standard doing something. */
.arc-std {
  border: 1px solid var(--hairline);
  border-radius: 12px;
  background: var(--paper-alt);
  padding: var(--s4);
}
.arc-std-h {
  margin: 0 0 var(--s3);
  font-size: var(--t-label); font-weight: 600; line-height: 1.4;
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--ink-2);
}
/* ONE NAME A ROW. Two across broke "OpenID Federation 1.0" and "SPIFFE and SPIRE" across two lines
   each inside a 130px track, which made a list of four names read as a block of eight fragments. */
.arc-std-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s2); }
/* 24px MINIMUM ON EACH NAME, because each one is a link with no sentence around it: neither
   exemption in WCAG 2.2 clause 2.5.8 applies. The mark before it is the brand dot every statement
   row on this site draws. */
.arc-std-item a {
  display: flex; align-items: center; gap: var(--s2);
  min-height: 24px;
  font-size: var(--t-label); line-height: 1.3;
  color: var(--ink-row); text-decoration: none;
}
.arc-std-item a::before {
  content: ""; flex: none;
  width: 6px; height: 6px; border-radius: var(--pill);
  background: var(--teal-dark);
}
.arc-std-item a:hover { color: var(--teal-dark); text-decoration: underline; text-underline-offset: 0.14em; }
.arc-std-item a:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 3px; border-radius: var(--r-1); }

/* THE HUB. .rw-hub is the target's recipe: a radial gradient from the top, a brand edge, an outer
   glow and an inset highlight. It is the only brand coloured object in the figure, because it is
   the only Raidiam product in it. */
.arc-col-hub { align-self: stretch; }
.arc-page .arc-hub {
  height: 100%;
  display: grid; align-content: start; justify-items: center; gap: var(--s2);
  padding: var(--s5) var(--s4) var(--s5);
  text-align: center;
}
.arc-hub-i {
  display: inline-grid; place-items: center;
  width: 48px; height: 48px; border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--teal-dark) 45%, transparent);
  color: var(--teal-dark);
  margin-bottom: var(--s2);
}
.arc-hub-i svg { width: 24px; height: 24px; display: block; }
.arc-hub-t { margin: 0; font-size: var(--t-h3); font-weight: 700; line-height: 1.2; color: var(--ink); }
.arc-hub-s { margin: 0; max-width: 30ch; font-size: var(--t-label); line-height: 1.5; color: var(--ink-2); }
.arc-hub-rows { list-style: none; margin: var(--s4) 0 0; padding: 0; width: 100%; display: grid; gap: var(--s2); }
/* A ROW IS A PLAIN TOKEN GROUND, not a mix, because its label sits on it and contrast.mjs gates a
   token pair by name. */
.arc-hub-row {
  display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: var(--s3);
  padding: 9px var(--s3);
  border: 1px solid color-mix(in srgb, var(--teal-dark) 28%, transparent);
  border-radius: 8px;
  background: var(--wash-teal);
  text-align: left;
}
.arc-hub-row-i { display: inline-flex; color: var(--teal-dark); }
.arc-hub-row-i svg { width: 17px; height: 17px; display: block; }
.arc-hub-row-t { font-size: var(--t-label); font-weight: 600; line-height: 1.3; color: var(--ink); }

/* THE OUTCOMES. A glyph in its own hue, a name and one line. The comp draws the same five rows in
   one colour; these carry four hues, because a column of five identical marks reads as a list and
   the point of the column is that the five are different things. */
.arc-outs { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s4); }
.arc-out { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--s3); align-items: start; }
.arc-out-i {
  display: inline-grid; place-items: center; flex: none;
  width: 36px; height: 36px; border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--hue, var(--teal-dark)) 45%, transparent);
  color: var(--hue, var(--teal-dark));
}
.arc-out-i svg { width: 18px; height: 18px; display: block; }
.arc-out-body { min-width: 0; display: grid; gap: 2px; }
.arc-out-t { font-size: var(--t-small); font-weight: 700; line-height: 1.3; color: var(--ink); }
.arc-out-l { font-size: var(--t-label); line-height: 1.45; color: var(--ink-2); }

/* THE ARROWS. A line that brightens toward its head and a filled triangle on the end, which is what
   the comp draws between its columns. They are decoration: the columns read left to right without
   them, and they carry aria-hidden in the markup. */
.arc-arrow {
  align-self: center;
  position: relative;
  height: 2px; width: 100%;
  background: linear-gradient(90deg, color-mix(in srgb, var(--teal-dark) 10%, transparent) 0%, var(--teal-dark) 100%);
  filter: drop-shadow(0 0 5px color-mix(in srgb, var(--teal-dark) 60%, transparent));
}
.arc-arrow::after {
  content: ""; position: absolute; right: -1px; top: 50%;
  transform: translateY(-50%);
  width: 0; height: 0;
  border-left: 9px solid var(--brand-strong);
  border-top: 6px solid transparent;
  border-bottom: 6px solid transparent;
}

/* THE LINE THAT CLOSES THE PANEL. The comp sets SAME PRINCIPLES. ANYWHERE IT RUNS. here, tracked
   and uppercase and centred. */
.arc-flow-foot {
  margin: var(--s5) 0 0;
  text-align: center;
  font-size: var(--t-label); font-weight: 600; line-height: 1.6;
  letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--teal-dark);
}

/* ================================================================
   3. Designed for the real world: four destination cards.
   ================================================================ */

.arc-real { border-top: 0; padding-block: var(--s8) 0; }
/* THE BAND EYEBROW KEEPS THE SITE'S BRAND COLOUR. .eyebrow already sets it, every other band on
   this site wears it, and the comp sets its section kicker in the brand too, so only the tracking
   and the space under it belong to this page. */
.arc-real-h { margin: 0 0 var(--s5); letter-spacing: 0.22em; }

.arc-cards { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s4); }
.arc-page .arc-card { padding: 0; }
.arc-card-link {
  display: grid; align-content: start; gap: var(--s3);
  padding: var(--s5);
  text-decoration: none; color: inherit;
  border-radius: 10px;
}
.arc-card-i {
  display: inline-grid; place-items: center;
  width: 44px; height: 44px; border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--hue, var(--teal-dark)) 45%, transparent);
  color: var(--hue, var(--teal-dark));
}
.arc-card-i svg { width: 22px; height: 22px; display: block; }
.arc-card-t { font-size: var(--t-small); font-weight: 700; line-height: 1.3; color: var(--ink); }
.arc-card-l { font-size: var(--t-label); line-height: 1.5; color: var(--ink-2); }
/* THE WHOLE CARD IS THE CONTROL, so the arrow is drawn on the title rather than on a second link
   under it. One link to one page, and the hit area is the card. */
.arc-card-t::after {
  content: ""; display: inline-block; vertical-align: -0.02em;
  width: 15px; height: 10px; margin-left: var(--s2);
  background: currentColor;
  -webkit-mask: var(--arrow-right) center / contain no-repeat;
  mask: var(--arrow-right) center / contain no-repeat;
}
.arc-card-link:hover .arc-card-t { color: var(--teal-dark); }
.arc-card-link:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 3px; }

/* ================================================================
   4. The closing band. The shared cta partial on the shared photograph treatment.
   ================================================================ */

.arc-close { border-top: 0; margin-top: var(--s8); }

/* ================================================================
   The narrow states.
   ================================================================ */

/* THE INSTRUMENT FOLDS AT 1180 RATHER THAN AT 1000. Four columns inside a 1376 measure leave the
   environment column at 242px, which is the narrowest track that keeps "Software as a service" on
   two lines. Below that the four become two rows of two, the arrow between the pairs turns to point
   down, and the arrow that would sit at the end of a row is taken out of the flow entirely. */
@media (max-width: 1180px) {
  .arc-flow-in {
    grid-template-columns: minmax(0, 1fr) 36px minmax(0, 1fr);
    gap: var(--s5) var(--s4);
  }
  .arc-arrow:nth-of-type(2) {
    grid-column: 1 / -1;
    justify-self: center;
    width: 2px; height: 36px;
    background: linear-gradient(180deg, color-mix(in srgb, var(--teal-dark) 10%, transparent) 0%, var(--teal-dark) 100%);
  }
  .arc-arrow:nth-of-type(2)::after {
    right: auto; top: auto; left: 50%; bottom: -1px;
    transform: translateX(-50%);
    border-left: 6px solid transparent;
    border-right: 6px solid transparent;
    border-top: 9px solid var(--brand-strong);
    border-bottom: 0;
  }
}

@media (max-width: 1000px) {
  .arc-hero-in { grid-template-columns: minmax(0, 1fr); gap: var(--s6); }
  .arc-hero-fig { justify-items: center; }
  .arc-tagline { text-align: center; }
  .arc-page .arc-statement { max-width: 22ch; }
  .arc-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* THE FOUR COLUMNS BECOME ONE AT 760, AND EVERY ARROW POINTS DOWN. Two columns of 1fr inside a 696
   measure leave 330 a column, which is enough for the tiles and not for the outcome rows beside
   them, so the whole figure becomes one column rather than two uneven ones. */
@media (max-width: 760px) {
  .arc-flow-panel { padding: var(--s5) var(--s4); }
  .arc-flow-in { grid-template-columns: minmax(0, 1fr); gap: var(--s5); }
  .arc-arrow,
  .arc-arrow:nth-of-type(2) {
    grid-column: auto;
    justify-self: center;
    width: 2px; height: 28px;
    background: linear-gradient(180deg, color-mix(in srgb, var(--teal-dark) 10%, transparent) 0%, var(--teal-dark) 100%);
  }
  .arc-arrow::after,
  .arc-arrow:nth-of-type(2)::after {
    right: auto; top: auto; left: 50%; bottom: -1px;
    transform: translateX(-50%);
    border-left: 6px solid transparent;
    border-right: 6px solid transparent;
    border-top: 9px solid var(--brand-strong);
    border-bottom: 0;
  }
  /* THE CHIPS COME OFF THE GLOBE AND STAND UNDER IT. At this width the sphere is small enough that
     five pills over it overlap each other, so they become a centred wrapped row and the globe keeps
     its own space above them. */
  .arc-orbit { max-width: 420px; aspect-ratio: auto; display: grid; gap: var(--s4); }
  .arc-orbit-globe { aspect-ratio: 1 / 1; height: auto; }
  .arc-orbit-chips { position: static; display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s2); }
  .arc-chip,
  .arc-chip[data-at="nw"], .arc-chip[data-at="ne"], .arc-chip[data-at="e"],
  .arc-chip[data-at="w"], .arc-chip[data-at="se"] { position: static; inset: auto; }
}

@media (max-width: 560px) {
  .arc-cards { grid-template-columns: minmax(0, 1fr); }
  .arc-hero .arc-actions .btn { width: 100%; }
}

/* ---- src/parts/arch-runtime.css ---- */
/* /architecture/runtime. View: apps/site/src/views/runtimes.ejs.
   Partials: rt-stage.ejs, rt-bench.ejs.

   WHAT THIS FILE IS. Everything this route adds to the shared architecture shape: the centred head,
   the stage in the hero, and the narrowing bench under it. The payoff row and the close are .ah-
   classes in architecture-pages.css, which all the /architecture routes share, so a correction to
   the shape lands on every one of them at once.

   WHAT CHANGED ON 16 SEPTEMBER 2026, AND WHY. docs/redesign-tracker.md measured this page at four
   of nine: 1036 wide where its parent is 1376, 829 words, no figure in its first band, and ZERO of
   the four identity hues. It now opens on the stage, at its parent's measure, with a hue on every
   runtime, its wire, its arrowhead and its outcome.

   THE FOUR HUES ARE IDENTITY AND NEVER STATE. --d-blue, --d-violet, --d-magenta and --d-sand carry
   no meaning anywhere in this system, which is what lets them answer WHICH runtime a card belongs
   to. Green means Observed on this site and an Observed mark links its artefact, amber means in
   progress, red means refused, and none of the three is used here for identity. The one green on
   this page is the mark under the bench, on the document that was read.

   THE HUE MAP MATCHES srl.css WHERE THE TWO PAGES DRAW THE SAME RUNTIME. /use-cases/same-software
   sets the operator's own service blue and the publisher's platform violet, and this page sets the
   same two the same way, so a reader crossing from one to the other meets one colour per runtime.
   The workstation and the cloud workload take magenta and sand, which that page spends on nothing.

   THE BENCH IS THE ONE THING ON THIS PAGE A READER OPERATES, so it is the only object here that
   takes a panel ground, a brand ring on selection and a transition. The stage above it is flat on
   the page ground, which is what leaves the bench looking like the instrument rather than a band.

   EVERY SELECTOR STARTS .rt-. Fourteen routes are rebuilt at once and a bare element selector here
   would land on somebody else's page. The rules that dress a shared class, the outcome ring and the
   state chip, are written inside a .rt- wrapper for the same reason.

   THIS FILE SORTS BEFORE architecture-pages.css AND LOSES A TIE. "arch-runtime.css" and
   "architecture-pages.css" share four characters and the fifth is "-" against "i", so the build
   concatenates this part first. Nothing here needs to beat that file: the two carry different
   classes, and where both reach one element this file adds rather than overrides.

   NO SIZE UNDER 14px AND NO COLOUR-MIX IN A FLAT BACKGROUND. Every ground below is a plain token,
   and the mixes are in borders and shadows, where the contrast gate has nothing to read.

   WHAT HAPPENS AT 1180, AT 900 AND AT 620. The stage steps to two runtime cards across and the wire
   fan is dropped, because a fan drawn to four columns lands on nothing once there are two. The
   bench puts its panel under the type rows at 900 and its three options in one column at 620.
   ================================================================ */

/* THE MEASURE, stated once for this page. It takes its parent's: /architecture is 1376 and this is
   its child. `.wrap` reads --page-max on the element it is set on. It was 1036, which is the
   interior step, and four runtime cards carrying three rows each need the width: at 1036 a card is
   241px and "A managed workstation" breaks mid word. */
.rt-page { --page-max: 1376px; }

/* ================================================================
   The head: left aligned, over the instrument rather than beside it.

   WHY LEFT AND NOT CENTRED. Screenshotted at 1440 on 16 September 2026 beside its three neighbours.
   /architecture, /security and /how-it-works all open with the eyebrow, the display line, the lead
   and the two pills hard left, and all three score nine. This page centred its head and read as a
   different site in its own section. The eyebrow, the display step, the lead measure and the pill
   pair are the ones those three already carry.

   WHY THE INSTRUMENT IS UNDER THE COPY AND NOT BESIDE IT. Those three put a figure in the right
   half of the head, and each of their figures is one object. This one is four cards carrying three
   rows each: in the 828px that is left beside a 500px copy column, a card is 190px and its title
   breaks mid word, which is the defect CLAUDE.md records from the last round. Full width under the
   copy gives every card 332px at 1440, measured.
   ================================================================ */

/* THE BAND IS THE GRID AND THE STAGE SETS display: contents, so the stage's hub, wire layer and
   four cards are items of THIS grid rather than of a box inside it. That is what puts the hub in
   the right half beside the copy and the four cards across the whole measure underneath, which is
   the composition /architecture, /security and /how-it-works all draw.

   THE COLUMNS AND THE GAP ARE PERCENTAGES ON PURPOSE. rt-stage draws the fan from a percent of the
   layer width, and it is given 76, which is the centre of the right hand track: 48 percent of the
   measure, plus the 4 percent gap, plus half of the other 48. With a track in px or a gap in px
   that number drifts as the viewport narrows and the fan starts beside the hub instead of under it.
   In percentages it holds at every width this layout is used at. */
.rt-page .rt-top {
  position: relative; padding-block: 56px 0;
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  column-gap: 4%; row-gap: var(--s5); align-items: center;
}
/* THE AMBIENT POOL KEEPS ITS OWN POSITIONING. This rule lifts the band's real children over it, and
   `position: relative` here outranks the `position: absolute` rw.css gives the glow, so the pool is
   excluded by name. Left in, it became an 820 by 420 grid item and opened a 440px hole between the
   controls and the instrument. Measured at 1440 on 16 September 2026. */
.rt-page .rt-top > *:not(.rw-glow) { position: relative; z-index: 1; }
/* The stage generates no box, so position and z-index on it would do nothing. Its three children
   take them instead. */
.rt-page .rt-hub,
.rt-page .rt-wires,
.rt-page .rt-envs { position: relative; z-index: 1; }
.rt-page .rt-glow { z-index: 0; }
/* text-align IS STATED RATHER THAN LEFT TO INHERIT. This rule replaced a `text-align: center` on
   the same selector, and a replacement that drops a property leaves the old value standing wherever
   the old sheet is still loaded. Measured: the head rendered centred with the grid already applied. */
.rt-page .rt-copy { grid-column: 1; grid-row: 1; display: grid; justify-items: start; text-align: left; align-content: center; }

/* The eyebrow is the section, a rule, and the subject of the page in the brand colour. */
.rt-page .rt-eyebrow { margin: 0; letter-spacing: 0.28em; }
.rt-page .rt-eyebrow-rule { margin: 0 var(--s2); color: var(--ink-2); }
.rt-page .rt-eyebrow-accent { color: var(--teal-dark); }

/* TWO SENTENCES, TWO LINES, AND THE SECOND ONE CARRIES THE ACCENT. The accent is its own block, so
   the break falls at the full stop rather than wherever the measure runs out, and both blocks are
   balanced: balancing the h1 alone leaves the accent ragged under a balanced first clause. */
.rt-page .rt-statement { margin: var(--s4) 0 0; max-width: 17ch; text-wrap: balance; }
.rt-page .rt-statement .accent { display: block; color: var(--teal-dark); text-wrap: balance; }

/* --ink-lead is one step above secondary text. The lead is a rendered markdown section rather than
   a front matter string, so the words are counted by apps/site/src/negatives.ts, and a section
   arrives as a paragraph with its own margin. */
.rt-page .rt-lead {
  margin: 20px 0 0; max-width: 46ch;
  color: var(--ink-lead);
  font-size: var(--t-body); line-height: 1.6;
}
.rt-page .rt-lead > p { margin: 0; }
.rt-page .rt-lead > p + p { margin-top: var(--s3); }

/* Two pills in one row. A stacked pair is a defect Ralph named on the home page, and it happens
   when the copy column is too narrow to hold them side by side. */
.rt-page .rt-actions {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--s4); margin-top: 36px;
}



/* ================================================================
   A HUE PER RUNTIME, AND IT LIVES HERE RATHER THAN IN THE CONTENT FILE.

   The content file names a `key` and this names the colour, so a page edit cannot tie a label to a
   colour and no colour literal appears in content. The card, its wire and its arrowhead read the
   same custom property, which is what makes a reader follow one line from the identity to the card
   it lands on.
   ================================================================ */

.rt-page .rt-env[data-rt="own"],
.rt-page .rt-wire[data-wire="own"],
.rt-page .rt-head[data-head="own"] { --hue: var(--d-blue); }
.rt-page .rt-env[data-rt="publisher"],
.rt-page .rt-wire[data-wire="publisher"],
.rt-page .rt-head[data-head="publisher"] { --hue: var(--d-violet); }
.rt-page .rt-env[data-rt="workstation"],
.rt-page .rt-wire[data-wire="workstation"],
.rt-page .rt-head[data-head="workstation"] { --hue: var(--d-magenta); }
.rt-page .rt-env[data-rt="workload"],
.rt-page .rt-wire[data-wire="workload"],
.rt-page .rt-head[data-head="workload"] { --hue: var(--d-sand); }

/* THE BENCH OPTION TAKES THE HUE OF THE RUNTIME IT IS ABOUT, not one of its own. Two of the three
   options are two evidence sets on the SAME workstation, so they share that runtime's colour: the
   hue answers which runtime, and giving each option its own would say there are three runtimes on
   a figure whose whole point is that one runtime has two rows. */
.rt-page .rt-opt[data-rt="workstation"] { --hue: var(--d-magenta); }
.rt-page .rt-opt[data-rt="workload"] { --hue: var(--d-sand); }

/* ================================================================
   The stage: one governed identity, four wires, four runtime cards.
   Partial: packages/ui/partials/rt-stage.ejs.
   ================================================================ */

.rt-page .rt-stage { display: contents; }
.rt-page .rt-stage-glow { z-index: 0; top: 0; }

/* THE HUB, rw.css treatment 3, and the one brand object on the figure. It is narrow on purpose: a
   hub as wide as the four cards under it reads as a fifth band rather than as the thing they hang
   from. */
.rt-page .rt-hub {
  /* ALIGNED TO THE BOTTOM OF THE ROW, NOT ITS MIDDLE. The copy column is the taller of the two, so
     a centred hub floats about fifty pixels above the row's foot and the fan below it starts in mid
     air. Measured at 1440 on 16 September 2026. */
  grid-column: 2; grid-row: 1; justify-self: center; align-self: end;
  width: min(100%, 460px); display: grid; justify-items: center; gap: var(--s2);
}
.rt-page .rt-hub-i { display: inline-flex; color: var(--teal-dark); }
.rt-page .rt-hub-i svg { width: 30px; height: 30px; display: block; }
.rt-page .rt-hub-eyebrow {
  margin: var(--s2) 0 0;
  font-size: var(--t-label); font-weight: var(--t-label-weight); line-height: var(--t-label-line);
  letter-spacing: 0.22em; text-transform: uppercase; color: var(--ink-2);
}
.rt-page .rt-hub-name { margin: 0; font-size: var(--t-h2); font-weight: 700; line-height: var(--t-h2-line); color: var(--ink); }
.rt-page .rt-hub-line { margin: 0; max-width: 42ch; font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-2); }

/* The wire layer. A fixed height, because the fan hangs between two objects that size themselves
   and a percentage height on an svg in a grid row resolves against a row that is sizing to it. */
.rt-page .rt-wires { grid-column: 1 / -1; grid-row: 2; width: 100%; height: 72px; margin: calc(var(--s5) * -1) 0 calc(var(--s5) * -1); }
.rt-page .rt-wires svg { width: 100%; height: 100%; display: block; overflow: visible; }

/* EVERY WIRE IS LIT AND EACH ONE CARRIES ITS RUNTIME'S HUE. rw.css draws a wire in the brand
   colour, which is right on a figure where one product reaches four environments; here the wire
   is the thing a reader follows from the identity to one card, so it takes the card's colour. */
.rt-page .rt-wire { stroke: var(--hue); opacity: 0.9; }

/* THE ARROWHEAD IS AN HTML ELEMENT, NOT AN SVG MARKER, because the layer scales x and y
   independently so a path coordinate is a percent of it, and a marker drawn in that space is
   squashed with it. srl-release.ejs draws its heads the same way. */
.rt-page .rt-heads { position: absolute; inset: 0; pointer-events: none; }
.rt-page .rt-head {
  position: absolute; bottom: -1px; transform: translateX(-50%);
  width: 0; height: 0;
  border-left: 5px solid transparent; border-right: 5px solid transparent;
  border-top: 7px solid var(--hue);
}

/* The four cards. Every track is minmax(0, 1fr), so a long value cannot push a track past the
   container. */
.rt-page .rt-envs {
  grid-column: 1 / -1; grid-row: 3;
  list-style: none; margin: 0; padding: 0; width: 100%;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s4);
}

/* .rw-card is treatment 2, the environment card lit from above by its own hue. This sets its size
   and the type inside it and draws nothing rw.css already draws, except the top edge: the treatment
   tints that border to 40 percent of the hue and this page draws it at full strength, because the
   edge is the card's half of the wire that lands on it. */
.rt-page .rt-env {
  display: grid; gap: var(--s2); align-content: start; min-width: 0;
  border-top-color: var(--hue);
  padding-top: var(--s2);
}

/* The pedestal, treatment 1: an icon standing on light, in the card's own hue. */
.rt-page .rt-ped { height: 84px; }
.rt-page .rt-ped .rw-ped-i svg { width: 38px; height: 38px; }

.rt-page .rt-env-t { margin: var(--s3) 0 0; font-size: var(--t-h3); font-weight: var(--t-h3-weight); line-height: var(--t-h3-line); color: var(--ink); }
.rt-page .rt-env-s { margin: 0; font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-2); }

/* THREE LABELLED ROWS ON THE FACE, which is the card the reference draws and the one Ralph read
   beside ours and preferred. A card that showed a title and a chip made a reader press something to
   learn anything. The label sits over its value rather than beside it, because a 320px card cannot
   hold a tracked label and a value on one line without breaking one of them. */
.rt-page .rt-env-rows { margin: var(--s3) 0 0; display: grid; gap: var(--s3); }
.rt-page .rt-env-row { display: grid; gap: 2px; padding-top: var(--s3); border-top: 1px solid var(--hairline); }
.rt-page .rt-env-row:first-child { padding-top: 0; border-top: 0; }
.rt-page .rt-env-k {
  font-size: var(--t-label); font-weight: var(--t-label-weight); line-height: var(--t-label-line);
  /* --ink-2, NOT --faint. --faint measured 4.17 to 1 on the card ground on 29 September 2026, under
     the 4.5 floor, and these labels name the three rows a reader came to the card for. */
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-2);
}
.rt-page .rt-env-v {
  margin: 0; overflow-wrap: anywhere;
  font-family: var(--mono); font-size: var(--t-mono); line-height: var(--t-mono-line); color: var(--ink-row);
}

/* THE ASSURANCE WORD TAKES THE CARD'S OWN WEIGHT AND NO STATE COLOUR. wr.css records the same rule
   for the same word: attested is not a pass and asserted is not a warning, so neither may wear a
   colour this site reserves for a verdict. The difference between them is the bench below. */
.rt-page .rt-env-v-strong {
  font-family: var(--sans); font-size: var(--t-h3); font-weight: 600; line-height: var(--t-h3-line);
  color: var(--ink);
}

/* ================================================================
   The bench: the heading, the lead and the note around it.
   ================================================================ */

.rt-page .rt-bench-band { display: grid; gap: var(--s6); }
.rt-page .rt-bench-head { display: grid; gap: var(--s4); }
.rt-page .rt-bench-h { margin: 0; max-width: 24ch; }

/* The lead is set at --ink-lead, which is the one step between primary text and secondary the
   reference puts on every lead. It carries the answer, so it is not allowed to read as a caption. */
.rt-page .rt-bench-lead {
  margin: 0;
  font-size: var(--t-body); line-height: var(--t-body-line);
  color: var(--ink-lead); max-width: 68ch;
}

/* The note under the bench: one sentence, when it was read, and the Observed mark on the document.
   The three sit on one line and wrap as one, because the read time belongs to the mark beside it. */
.rt-page .rt-bench-note {
  margin: 0;
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s2) var(--s3);
  font-size: var(--t-small); line-height: var(--t-small-line);
  color: var(--ink-2); max-width: var(--measure-notes);
}
.rt-page .rt-bench-read { color: var(--ink-2); }

/* ================================================================
   The bench itself: one control, five rows and one panel.
   ================================================================ */

.rt-page .rt-bench { display: grid; gap: var(--s5); }

/* The control. A fieldset carries no grid of its own in every engine, so the row is a child of it
   and the legend is taken out of the flow the fieldset gives it. */
.rt-page .rt-choice { margin: 0; padding: 0; border: 0; min-width: 0; }
.rt-page .rt-choice-legend {
  padding: 0; margin-bottom: var(--s4);
  font-size: var(--t-label); font-weight: var(--t-label-weight); line-height: var(--t-label-line);
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-2);
}
.rt-page .rt-choice-row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s3); }

/* AN OPTION IS A PANEL, NOT A PILL. Each one carries three lines: where the copy runs, what the
   attester verified, and the word the token then says. A pill cannot hold three lines, and the
   three lines are the whole question a reader is answering. This is the treatment the reference
   gives its four architecture tabs, which /security already ports.

   THE LEFT EDGE CARRIES THE RUNTIME'S HUE, which is how a reader joins an option to the card it is
   about. Two options are two evidence sets on one workstation and share one edge colour. */
.rt-page .rt-opt {
  display: grid; gap: 6px; align-content: start;
  padding: var(--s4);
  border: 1px solid var(--rule); border-radius: var(--r-3);
  border-left: 3px solid var(--hue, var(--rule));
  background: var(--paper-alt);
  cursor: pointer;
  transition: border-color 120ms ease, box-shadow 120ms ease, background-color 120ms ease;
}
.rt-page .rt-opt:hover { border-color: var(--bound); border-left-color: var(--hue, var(--bound)); }
.rt-page .rt-opt-where { font-size: var(--t-label); font-weight: var(--t-label-weight); line-height: var(--t-label-line); color: var(--ink); }
.rt-page .rt-opt-ev { font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-2); }

/* THE ASSURANCE WORD TAKES THE ACCENT AND NO STATE COLOUR. wr.css records the same rule for the
   same word: attested is not a pass and asserted is not a warning, so neither may wear a colour
   this site reserves for a verdict. The difference between them is the five rows below, not a hue. */
.rt-page .rt-opt-word {
  margin-top: 2px;
  font-size: var(--t-small); line-height: var(--t-small-line);
  font-weight: 600; color: var(--teal-dark);
}

/* The short form of the line that says a row is declared and not switched on here. It sits on the
   card, under the word it qualifies, because a reader scanning three options reads the words and
   not the panel, and two cards saying attested would otherwise say this deployment offers both. */
.rt-page .rt-opt-off { font-size: var(--t-label); line-height: var(--t-label-line); color: var(--att); }

/* SELECTION IS THE BRAND RING THE REFERENCE DRAWS, and it is carried by the radio's own checked
   state rather than by a class a script sets, so a reader without script still sees which option is
   selected while pressing the others.

   IT DEPENDS ON :has(), because the input is inside the label it dresses and no combinator reaches
   a parent. Chrome, Safari and Firefox have all shipped it since December 2023. An engine without
   it draws no ring, and selection is still carried by the native radio and by the panel beside the
   rows, so nothing becomes unreadable: the ring is the third signal rather than the only one. */
.rt-page .rt-opt:has(.rt-opt-in:checked) {
  border-color: var(--teal-dark);
  border-left-color: var(--hue, var(--teal-dark));
  background: var(--white);
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--teal-dark) 60%, transparent),
    0 0 40px -8px color-mix(in srgb, var(--teal-dark) 70%, transparent);
}

/* The input is clipped rather than removed, so it keeps its keyboard behaviour and its accessible
   name. The focus ring is drawn on the label, because the input has no box a reader can see.
   IT TAKES THE PAGE FONT rather than the browser's own control default, which is 13.33px. The
   control draws no text and the size changes nothing a reader sees, and a measured page carrying a
   size under the floor is a finding somebody has to spend time dismissing. */
.rt-page .rt-opt-in { font: inherit; }
.rt-page .rt-opt:has(.rt-opt-in:focus-visible) {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

/* ---- The result: five rows and one panel ---- */

.rt-page .rt-out { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: var(--s5); align-items: start; }

.rt-page .rt-types {
  display: grid; gap: var(--s4);
  padding: var(--s5);
  border: 1px solid var(--rule); border-radius: var(--r-3);
  background: var(--paper-alt);
}
.rt-page .rt-out-label {
  margin: 0;
  font-size: var(--t-label); font-weight: var(--t-label-weight); line-height: var(--t-label-line);
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-2);
}
.rt-page .rt-rows { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s3); }

/* A ROW IS THE TYPE, ITS DECLARED SENTENCE AND ONE VERDICT, and the verdict is right aligned so the
   five of them make one column a reader reads down. That column changing is the demonstration. */
.rt-page .rt-row {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 2px var(--s4); align-items: center;
  padding: var(--s3) 0;
  border-top: 1px solid var(--hairline);
}
.rt-page .rt-row:first-child { border-top: 0; padding-top: 0; }
.rt-page .rt-row-name {
  grid-column: 1; grid-row: 1;
  font-family: var(--mono); font-size: var(--t-mono); color: var(--ink);
}
.rt-page .rt-row-line {
  grid-column: 1; grid-row: 2;
  font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-row);
}
.rt-page .rt-v { grid-column: 2; grid-row: 1 / span 2; justify-self: end; }
/* KEPT IS A DECLARED VERDICT, NOT AN OBSERVED ONE, so it takes the brand and not the green state
   chip. Withheld takes the muted state chip for the same reason. */
.rt-page .rt-granted {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 2px 10px; border-radius: 999px;
  font-size: 14px; font-weight: 600; color: var(--brand-strong);
  border: 1px solid var(--teal-dark);
}
.rt-page .rt-granted svg { width: 14px; height: 14px; }

/* A WITHHELD ROW, OR ONE OUTSIDE THE ENVELOPE, GOES QUIET RATHER THAN RED. A kept row is ink over row
   ink; a quiet row steps each down one, to row ink over --ink-2, which is what makes five rows
   readable as a shape at a glance. The step stops at --ink-2 because --faint fails 4.5 to 1 here. */
.rt-page .rt-row:is([data-verdict="no"], [data-verdict="out"]) .rt-row-name { color: var(--ink-2); }
.rt-page .rt-row:is([data-verdict="no"], [data-verdict="out"]) .rt-row-line { color: var(--ink-2); }
.rt-page .rt-row .rt-row-name, .rt-page .rt-row .rt-row-line { transition: color 160ms ease; }

/* ---- The panel beside the rows ---- */

.rt-page .rt-panel {
  display: grid; gap: var(--s2);
  padding: var(--s5);
  border: 1px solid color-mix(in srgb, var(--teal-dark) 34%, transparent);
  border-radius: var(--r-3);
  background: var(--white);
}
.rt-page .rt-panel-label {
  margin: var(--s3) 0 0;
  font-size: var(--t-label); font-weight: var(--t-label-weight); line-height: var(--t-label-line);
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-2);
}
.rt-page .rt-panel-label:first-child { margin-top: 0; }
.rt-page .rt-panel-word { margin: 0; font-size: var(--t-h3); line-height: var(--t-h3-line); font-weight: 600; color: var(--teal-dark); }
.rt-page .rt-panel-runs { margin: 0; font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-row); }
.rt-page .rt-panel-reason { margin: 0; font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-row); }
.rt-page .rt-panel-lasts { margin: 0; font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-row); }

/* The line that says a row is declared and not switched on here. It sits directly under the word it
   qualifies, because a reader who takes the word away without it takes away a capability claim. */
.rt-page .rt-panel-off {
  margin: 0;
  font-size: var(--t-small); line-height: var(--t-small-line); color: var(--att);
}

/* ================================================================
   The payoff row: what the runtime leaves alone.

   FOUR CONSTANTS, FOUR HUES, AND THE HUE IS IDENTITY HERE TOO. One identity, one chain, one
   envelope, one lifecycle are four kinds of thing rather than four grades of one, so the ring takes
   a hue and nothing on the row takes a state colour. The order matches the stage's cycle so the
   page reads as one palette rather than two.
   ================================================================ */

.rt-page .rt-payoff .ah-outcome:nth-child(1) .rw-ring { color: var(--d-blue); border-color: color-mix(in srgb, var(--d-blue) 45%, transparent); }
.rt-page .rt-payoff .ah-outcome:nth-child(2) .rw-ring { color: var(--d-violet); border-color: color-mix(in srgb, var(--d-violet) 45%, transparent); }
.rt-page .rt-payoff .ah-outcome:nth-child(3) .rw-ring { color: var(--d-magenta); border-color: color-mix(in srgb, var(--d-magenta) 45%, transparent); }
.rt-page .rt-payoff .ah-outcome:nth-child(4) .rw-ring { color: var(--d-sand); border-color: color-mix(in srgb, var(--d-sand) 45%, transparent); }

/* ================================================================
   The narrow states.
   ================================================================ */

@media (max-width: 1180px) {
  /* ONE COLUMN, TWO CARDS ACROSS, AND THE FAN GOES. The wire layer ends its four paths on four
     column centres, so with two card columns three of the four land on nothing. A fan pointing at
     the wrong cards is worse than no fan, and the hue on each card carries the grouping without it.
     The hub drops under the copy and keeps its place above the cards it is the source of. */
  .rt-page .rt-top { grid-template-columns: minmax(0, 1fr); row-gap: var(--s7); }
  .rt-page .rt-hub { grid-column: 1; grid-row: 2; }
  .rt-page .rt-wires { display: none; }
  .rt-page .rt-envs { grid-column: 1; grid-row: 3; grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 900px) {
  /* The panel goes under the rows. It is the reading key to them, so it never goes above. */
  .rt-page .rt-out { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 620px) {
  .rt-page .rt-envs { grid-column: 1; grid-template-columns: minmax(0, 1fr); }
  .rt-page .rt-choice-row { grid-template-columns: minmax(0, 1fr); }
  .rt-page .rt-row { grid-template-columns: minmax(0, 1fr); }
  .rt-page .rt-v { grid-column: 1; grid-row: 3; justify-self: start; margin-top: 6px; }
}

@media (prefers-reduced-motion: reduce) {
  .rt-page .rt-opt,
  .rt-page .rt-row .rt-row-name,
  .rt-page .rt-row .rt-row-line { transition: none; }
}

/* ---- src/parts/arch-security.css ---- */
/*
 * /architecture/security. View: apps/site/src/views/security.ejs, every selector under .as-page.
 * Partials: as-ledger.ejs, as-questions.ejs, sec-shield.ejs, sec-stack.ejs and sec-routes.ejs.
 *
 * WHAT THIS FILE IS. The whole of one route, rebuilt on 16 September 2026 against the comp at
 * /Users/ralphbragg/Downloads/arch+sec.png, right half. The comp draws a hero with a lit shield, a
 * four item strip, a five plate instrument, three cards and a closing band on a photograph. This
 * file draws all five, and it carries the key ledger, which the comp has no equivalent of and which
 * is the fact this page exists for.
 *
 * COLOUR IS THE BRIEF. Ralph: "REmember to add colours (not monochromatic) and that this is a
 * marketing page!" The five plates run brand, magenta, blue, violet and sand, which is the whole of
 * the four environment hues plus the brand. A hue here is IDENTITY: it says which layer this is and
 * nothing about whether a thing is proven. State colour is the other vocabulary, it always sits
 * beside a word, and every mark on this page is rendered by the view from a capability row or an
 * evidence class rather than painted here.
 *
 * WHY THIS PART EXISTS BESIDE sec.css. sec.css draws the four tab instrument and every figure inside
 * it, and it is finished work. This file carries the comp's visual language over the same markup,
 * and it carries the hero, the strip, the plates, the cards, the close and the ledger. The two parts
 * do not edit each other, and no class declared here is declared there.
 *
 * SPECIFICITY IS DELIBERATE, NOT DECORATIVE. The component layer concatenates src/parts in sorted
 * order, so this file is read BEFORE sec.css and loses every tie at equal weight. Each override of a
 * sec.css rule therefore carries the .as-page scope, which is one class more than the rule it beats.
 * Removing the scope does not make a rule broader, it makes it silently inert.
 *
 * THE MEASUREMENTS THAT MOVED IN THIS PASS, each taken at 1440 rather than read off the code.
 *   The page measure was 1036, which is the reference build's interior page. The comp draws this
 *   route at the container's full width and the five plate figure and the five column ledger both
 *   want it, so the line that held it at 1036 is gone and the page takes the site default.
 *   The head was centred in that 1036. The comp puts an object beside the copy, so the band is two
 *   columns of 56 and 44 per cent above 1000 and one column below it.
 *   The ledger row is five tracks of 1.3, 0.95, 1.25, 1.3 and 0.95 on a 16px gutter. At the wider
 *   measure a value of about twelve words lands on three lines at 14px rather than four.
 *
 * WHAT THIS FILE REFUSES TO DRAW. A rule between stacked drawers. A green anything: green means
 * Observed on this site, an Observed mark links its artefact, and every mark on this page is
 * rendered by the view. A state colour used as a category: the two ledger groups are told apart by
 * their order, their heads and their counts, never by a hue, because a palette built out of state
 * tokens says a key is in progress or refused when it is neither.
 *
 * COLOUR. Every value is a token. The panel ground is a gradient from var(--paper-alt) to
 * var(--paper), which is legal in a background because no text pair is hidden by it: the contrast
 * gate reports ink on paper at 15.94 and ink-2 on paper at 6.33, and both ends of this gradient sit
 * between those two grounds, so text on the panel is at or above the lower reading whichever end it
 * lands on.
 */

/* ================================================================
   The hero: the copy on the left, the lit shield on the right.
   ================================================================ */

.as-page .as-top {
  position: relative;
  padding-block: 56px var(--s7);
  display: grid; grid-template-columns: minmax(0, 56fr) minmax(0, 44fr);
  align-items: center; gap: var(--s6);
}
/* THE TWO COLUMNS LIFT OVER THE GLOW, AND THE GLOW IS NAMED RATHER THAN REACHED FOR AS A CHILD.
   The rule here was `.as-top > *`, which set position: relative on every child. That is harmless in
   block flow and wrong in a grid: it took the glow's own `position: absolute` away, so the pool
   became the first grid item, the copy took the second column and the shield dropped to a row of its
   own underneath. Measured, not guessed: the hero rendered upside down at 1440. */
.as-page .as-copy,
.as-page .as-shield-slot { position: relative; z-index: 1; }
.as-page .as-glow { position: absolute; z-index: 0; top: 40px; }

/* THE EYEBROW IS ONE WORD AND THE COMP SETS IT IN THE BRAND. It read "Architecture | Security" while
   this route was a child of the architecture section. The comp puts Security in the masthead as a
   section of its own, so the kicker names the page and nothing else. */
.as-page .as-eyebrow { margin: 0; letter-spacing: 0.28em; }

/* THE STATEMENT SETS 56px AT 1440, WHICH IS THE REFERENCE BUILD'S INTERIOR DISPLAY STEP.
   tools/redesign/score.mjs reads that scale off /tmp/claude-501/rw-live and records it: 76 on the
   home page, 56 on how-it-works, architecture, evidence and live-demo, 52 on a use case, 44 on the
   index. The shared --t-display token stops at 54, which is one size for every page rather than a
   scale, so the interior step is set on the page that wants it. The clamp is the one
   .lvd-hero-statement already uses, because a flat 56 breaks a two word headline over four lines at
   400 wide.

   IT IS NOT BALANCED HERE: the accent is its own block and a two line headline beside an object
   wants the break where the clause ends. */
.as-page .as-statement {
  margin: var(--s4) 0 0; max-width: 16ch;
  font-size: clamp(38px, 4.4vw, 56px); line-height: 1.02; letter-spacing: -0.03em;
}
.as-page .as-statement .accent { display: block; color: var(--teal-dark); }

/* --ink-lead IS THE COLOUR, and it is one step above secondary text. The comp sets #aebdd2 on every
   lead it draws. Reaching for --ink-2 here, two steps down, makes a lead read as a caption. */
.as-page .as-lead {
  margin: 20px 0 0;
  max-width: 46ch;
  color: var(--ink-lead);
  font-size: var(--t-body); line-height: 1.6;
}
.as-page .as-lead > p { margin: 0; }
.as-page .as-lead > p + p { margin-top: var(--s3); }

/* TWO PILLS IN ONE ROW. Ralph named a stacked pair as a defect on the home page: the comp sets its
   two calls to action side by side and the pair reads as one gesture. */
.as-page .as-actions {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--s4);
  margin-top: 36px;
}

/* ---- The shield ---------------------------------------------------------
   THE OBJECT IS DRAWN AND NOT PHOTOGRAPHED. Four layers of svg under one published brand asset: a
   soft pool of brand behind the shape, a vertical gradient body, a lit radial over it, the edge, and
   an inner bevel. The wordmark is the same file the masthead draws.

   THE SHIELD SIZES ITSELF FROM THE COLUMN and stops at 340, which is its own drawing width. Larger
   than that the bevel and the wordmark separate and it reads as a badge rather than as an object. */
/* THE SLOT IS NAMED .as-shield-slot AND NOT .as-figure, which the ledger's two counted figures
   already own further down this file. One class, two objects, and the hero drew a bordered card
   around the shield. */
.as-page .as-shield-slot { display: flex; justify-content: center; align-items: center; }
.as-page .sec-shield { margin: 0; display: flex; align-items: center; gap: var(--s5); }
.as-page .sec-shield-art { position: relative; flex: 0 1 340px; max-width: 340px; }
.as-page .sec-shield-art svg { display: block; width: 100%; height: auto; }

/* The gradient stops. stop-color is a CSS property, so the palette stays where the colour gate can
   read it; a presentation attribute could not hold a token at all. */
.as-page .sec-shield-s1 { stop-color: var(--teal-mid); stop-opacity: 0.55; }
.as-page .sec-shield-s2 { stop-color: var(--paper-alt); stop-opacity: 0.9; }
.as-page .sec-shield-s3 { stop-color: var(--brand-strong); stop-opacity: 0.32; }
.as-page .sec-shield-s4 { stop-color: var(--teal-mid); stop-opacity: 0; }

.as-page .sec-shield-net { fill: var(--teal-mid); stroke: var(--teal-mid); stroke-width: 1; opacity: 0.35; }
.as-page .sec-shield-net path { fill: none; }
.as-page .sec-shield-pool { fill: var(--teal-mid); opacity: 0.5; filter: blur(34px); }
.as-page .sec-shield-edge { fill: none; stroke: var(--teal-dark); stroke-width: 2.5; }
.as-page .sec-shield-bevel { fill: none; stroke: var(--brand-strong); stroke-width: 1; opacity: 0.45; }

/* The mark sits on the waist of the shield, which is where the comp puts it. */
.as-page .sec-shield-mark {
  position: absolute; left: 50%; top: 45%; transform: translate(-50%, -50%);
  width: 52%; height: auto; display: block;
}

/* The two tracked lines beside the object. The comp sets them small, uppercase and widely tracked,
   at the shield's waist. */
.as-page .sec-shield-lines {
  display: grid; gap: 2px; margin: 0; white-space: nowrap;
  font-size: var(--t-label); font-weight: 600; line-height: 1.4;
  text-transform: uppercase; letter-spacing: 0.2em;
  color: var(--ink);
}

/* ================================================================
   The instrument: the four tab strip and the open panel.
   ================================================================ */

.as-page .as-instrument { padding-top: 36px; border-top: 0; }
.as-page .sec { gap: var(--s6); }

/* THE FOUR TABS ARE FOUR PANELS. sec.css draws them as one joined strip with a hairline between
   each, which is this site's older language; the reference draws every group of four as four
   separate panels with a gap. The strip keeps its roles, its roving tab order and its script, which
   belong to sec-tabs.ejs and are untouched. */
.as-page .sec-tabs {
  border: 0;
  border-radius: 0;
  background: transparent;
  overflow: visible;
  gap: var(--s3);
}

.as-page .sec-tab {
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
  background: var(--paper-alt);
  padding: var(--s4) var(--s4);
}

/* The joined strip needed a first child with no left rule. Four panels each need their own. */
.as-page .sec-tab:first-child { border-left: 1px solid var(--rule); }
.as-page .sec-tab:hover { border-color: var(--bound); }

/* THE SELECTED TAB TAKES THE REFERENCE'S RING: a one pixel brand ring and a wide, dim bloom under
   it. Selection is still carried by aria-selected and by the ground, so nothing here is the only
   signal. */
.as-page .sec-tab[aria-selected="true"] {
  border-color: var(--teal-dark);
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--teal-dark) 60%, transparent),
    0 0 40px -8px color-mix(in srgb, var(--teal-dark) 70%, transparent);
}

/* The underline the joined strip used to carry. A two pixel bar inside a radius reads as a mistake
   rather than as a selection, and the ring above says the same thing in the reference's own terms. */
.as-page .sec-tab[aria-selected="true"]::after { content: none; }

/* FOUR PANELS IN A ROW NEED A ROW TO SIT IN. sec.css sizes the strip at four equal columns at every
   width, which a joined strip survives and four separate panels do not: at 390 each tab is under
   80px and the label wraps to three lines. The query is a container query, not a media query,
   because .sec declares container-type: inline-size and the instrument's own width decides this. */
@container (max-width: 900px) {
  .as-page .sec-tabs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* The open panel is the reference's large panel: a radius, a rule, a ground one step up from the
   page and the system's own lift. */
.as-page .sec-panel {
  padding: var(--s6);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
  background: linear-gradient(180deg, var(--paper-alt) 0%, var(--paper) 100%);
  box-shadow: var(--shadow-lift);
}

/* Inside that panel the smaller grounds move up a step, so a card on a panel still has an edge. */
.as-page .sec-party { background: var(--paper-alt); }
.as-page .sec-custody-line { background: var(--white); }
.as-page .sec-model-tab { border-radius: var(--r-2); }

/* ================================================================
   The ledger: the band this rebuild exists for.
   ================================================================ */

.as-page .as-ledger-band { padding-top: var(--s8); border-top: 0; }
.as-page .as-ledger { display: block; }

.as-page .as-ledger-h { margin: 0; color: var(--ink); max-width: 20ch; }
.as-page .as-ledger-lead {
  margin: var(--s3) 0 0; max-width: 72ch;
  font-size: var(--t-body); line-height: 1.6; color: var(--ink-lead);
}

/* THE HEAD ROW: the counted figures and the disclosure on the left, the questionnaire panel on the
   right.

   TWO EQUAL COLUMNS, AND THE 320 THE REFERENCE DRAWS ITS SIDE PANELS AT IS WRONG HERE. Measured at
   1440 with the panel at 320 and three rows on it: the panel ran to 788px against a left column of
   565, so the band carried 223px of empty ground and the panel read as a narrow gutter of small
   print rather than as the answer a partner's security team takes away. At two equal columns of 508
   the panel renders near 420 and the left column near 530, the band is 258px shorter, and the two
   halves balance.
   The reference's 320 is right for a panel beside a FIGURE, which is what it draws; this one sits
   beside a column of sentences. */
.as-page .as-ledger-head {
  margin-top: var(--s6);
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s6);
  align-items: start;
}
.as-page .as-ledger-main { min-width: 0; display: grid; gap: var(--s5); }
.as-page .as-ledger-aside { min-width: 0; }

/* THE TWO COUNTED FIGURES. Each one is the length of a group list, so a key row added to the content
   file moves both. The unit is a kind of key rather than a key: five rows below are plural. */
.as-page .as-figures {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s5);
}
.as-page .as-figure {
  min-width: 0;
  padding: var(--s5);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
  background: var(--white);
}
.as-page .as-figure-n {
  margin: 0;
  font-size: var(--t-figure); line-height: var(--t-figure-line);
  font-weight: 700; letter-spacing: -0.03em;
  color: var(--ink);
}
/* "of 16" rides the numeral at reading size, so the pair is one value rather than two figures. */
.as-page .as-figure-of { font-size: var(--t-body); font-weight: 400; color: var(--ink-2); letter-spacing: 0; }
.as-page .as-figure-u {
  margin: var(--s2) 0 0;
  font-size: var(--t-label); line-height: var(--t-label-line);
  text-transform: uppercase; letter-spacing: 0.14em;
  color: var(--ink-2);
}
.as-page .as-figure-l {
  margin: var(--s3) 0 0;
  font-size: var(--t-small); line-height: var(--t-small-line);
  color: var(--ink-row);
}

/* THE DISCLOSURE. The two places Raidiam holds a private half, each an @claim paragraph carrying the
   matrix status chip. It takes the reference's side panel treatment because it is a reading key to
   the rows under it rather than a card in its own right. */
.as-page .as-ledger-note {
  border-radius: 12px;
  border: 1px solid color-mix(in srgb, var(--teal-dark) 20%, transparent);
  background: linear-gradient(180deg, color-mix(in srgb, var(--paper-alt) 75%, transparent) 0%, color-mix(in srgb, var(--paper) 75%, transparent) 100%);
  padding: var(--s5);
}
.as-page .as-exception-body { font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-2); }
.as-page .as-exception-body > * { margin: 0; }
.as-page .as-exception-body [data-claim] { display: block; }
.as-page .as-exception-body [data-claim] + [data-claim] {
  margin-top: var(--s4); padding-top: var(--s4);
  border-top: 1px solid var(--hairline);
}
/* The claim chip sits at the end of its own paragraph, on its own line, so a reader meets the words
   before the class rather than a mark interrupting the sentence it belongs to. */
.as-page .as-exception-body .ev { margin-top: var(--s2); }

/* ---- The panel a partner's security team reads --------------------------
   THE ROWS ARE DIVIDED BY --hairline AND NOT BY --rule. The divider is decorative: the rows read in
   any order and losing the lines costs a reader nothing, which is the definition this system gives
   --hairline. The panel's own edge keeps the brand border .rw-panel draws.

   CONTRAST. The term is teal-dark and the value ink-2. The panel ground is the .rw-panel gradient
   over the page, so both land on paper, and packages/ui/tools/contrast.mjs gates teal-dark and
   ink-2 on paper and on paper-alt at 4.5. */
.as-page .as-q-head {
  margin: 0 0 var(--s4);
  font-size: var(--t-h2); line-height: var(--t-h2-line); letter-spacing: var(--t-h2-tracking);
  font-weight: var(--t-h2-weight);
  color: var(--ink);
}
.as-page .as-q-rows { display: grid; gap: var(--s4); margin: 0; }
.as-page .as-q-row { display: grid; gap: var(--s2); }
.as-page .as-q-row + .as-q-row { padding-top: var(--s4); border-top: 1px solid var(--hairline); }
.as-page .as-q-term {
  margin: 0; color: var(--teal-dark);
  text-transform: uppercase; letter-spacing: 0.12em;
}
.as-page .as-q-value { margin: 0; display: grid; gap: var(--s3); justify-items: start; }
.as-page .as-q-value p {
  margin: 0; font-size: var(--t-label); line-height: 1.5; color: var(--ink-2);
}

/* ---- The filter tray ----------------------------------------------------
   Three toggles over one list, in the reference's own control tray: a rounded box on the alternate
   ground with the controls inside it. They are buttons carrying aria-pressed rather than tabs,
   because a tab controls one panel each and these three act on the same list. */
.as-page .as-ledger-tray {
  margin-top: var(--s7);
  display: flex; flex-wrap: wrap; gap: var(--s2);
  padding: 6px;
  border: 1px solid var(--hairline);
  border-radius: 12px;
  background: var(--paper-alt);
}
.as-page .as-filter {
  display: inline-flex; align-items: center; gap: var(--s2);
  border: 0;
  border-radius: 8px;
  padding: 10px 20px;
  font: inherit;
  font-size: var(--t-label); font-weight: 500; line-height: 1.5;
  color: var(--ink-nav); background: transparent;
  cursor: pointer;
  transition: color var(--m-drawer) ease, background-color var(--m-drawer) ease;
}
.as-page .as-filter:hover { color: var(--ink); }
/* THE PRESSED CONTROL. --wash-teal is this system's ground behind brand text, and the pair is gated
   by name. --teal is refused here: brand teal fills a Raidiam product marker and nothing else. */
.as-page .as-filter[aria-pressed="true"] {
  background: var(--wash-teal);
  color: var(--teal-dark);
  font-weight: 600;
}
.as-page .as-filter:focus-visible { outline: 2px solid var(--teal-dark); outline-offset: 2px; }
.as-page .as-filter-n {
  font-variant-numeric: tabular-nums;
  font-size: var(--t-label); font-weight: 600;
  color: var(--ink-2);
}
.as-page .as-filter[aria-pressed="true"] .as-filter-n { color: var(--teal-dark); }

/* ---- The rows -----------------------------------------------------------
   FIVE TRACKS, SET ONCE ON THE LIST AND INHERITED BY THE HEAD ROW AND BY EVERY ROW'S CELLS. The
   cells are a dl inside the row, and they take `subgrid` so a value lands under its column name
   rather than near it. Where subgrid is unavailable the declaration is dropped and the dl becomes a
   single column, which stacks the four labelled values under the key name and is still readable.

   THE FIRST TRACK IS THE WIDEST BECAUSE IT CARRIES A CHIP AS WELL AS A NAME. Measured at 1440 with
   the first track at 1.15fr: the cell rendered 196 and the "Not observed on this tenant" chip, which
   is 193 wide, wrapped to two lines on two rows and pushed both past their neighbours. At 1.3fr the
   cell renders 218 and every chip sits on one line. */
.as-page .as-ledger-list {
  --as-cols: 1.3fr 0.95fr 1.25fr 1.3fr 0.95fr;
  margin-top: var(--s5);
}

.as-page .as-heads {
  display: grid; grid-template-columns: var(--as-cols); gap: var(--s4);
  padding: 0 var(--s4) var(--s3);
  border-bottom: 1px solid var(--rule);
  font-size: var(--t-label); font-weight: 600; line-height: var(--t-label-line);
  text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--ink-2);
}

.as-page .as-group { display: block; }
.as-page .as-group-h {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s3);
  margin: var(--s6) 0 0;
  font-size: var(--t-h3); line-height: var(--t-h3-line); font-weight: var(--t-h3-weight);
  color: var(--ink);
}
.as-page .as-group-n {
  font-size: var(--t-label); font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase;
  font-variant-numeric: tabular-nums;
  color: var(--ink-2);
}
.as-page .as-group-l {
  margin: var(--s2) 0 0; max-width: 84ch;
  font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-2);
}

.as-page .as-rows { list-style: none; margin: var(--s4) 0 0; padding: 0; }
.as-page .as-row {
  display: grid; grid-template-columns: var(--as-cols); gap: var(--s4);
  padding: var(--s3) var(--s4);
  border-radius: var(--r-2);
}
/* A HAIRLINE BETWEEN ROWS AND NOT A BOX AROUND EACH. Sixteen boxed cards read as sixteen objects to
   decide between; a ruled list reads as one ledger to run an eye down, which is what it is. */
.as-page .as-row + .as-row { border-top: 1px solid var(--hairline); border-top-left-radius: 0; border-top-right-radius: 0; }
.as-page .as-row:hover { background: var(--paper-alt); }

.as-page .as-cell { min-width: 0; }
.as-page .as-cells {
  display: grid; grid-column: 2 / -1; grid-template-columns: subgrid;
  gap: var(--s4);
  margin: 0;
}
.as-page .as-row-t {
  margin: 0;
  font-size: var(--t-label); font-weight: 700; line-height: var(--t-label-line);
  color: var(--ink);
}
.as-page .as-row-mark { margin: var(--s2) 0 0; }

/* THE COLUMN NAME INSIDE EACH CELL IS FOR THE ACCESSIBILITY TREE ABOVE 900, where the head row
   carries it for everyone else, and it becomes visible below 900 where the head row goes. Clipping
   is written here rather than by reusing .vh, because .vh clips at every width and this one may
   not. */
@media (min-width: 900px) {
  .as-page .as-lab {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }
}
.as-page .as-lab {
  font-size: var(--t-label); font-weight: 600; line-height: var(--t-label-line);
  text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--ink-2);
}
.as-page .as-cells dd {
  margin: 0;
  font-size: var(--t-label); line-height: 1.5; color: var(--ink-row);
}

.as-page .as-ledger-after {
  margin-top: var(--s5); max-width: 72ch;
  font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-2);
}
.as-page .as-ledger-after > p { margin: 0; }
.as-page .as-ledger-after > p + p { margin-top: var(--s3); }

/* ================================================================
   /security/keys, the technical route. View: apps/site/src/views/security-keys.ejs.

   IT ADDS FOUR RULES AND NO NEW SHAPE. The ledger, the questionnaire panel, the closing band and
   the card row are the same objects /security drew until 16 September 2026, under the same .as-page
   scope, so the two routes are one page family rather than two designs. What this block adds is the
   head, which has no object beside it, and the rotation band, which is a table and a configuration
   panel that were inside a disclosure on the claim page.

   IT REFUSES TO RESTYLE THE LEDGER. A technical route that drew its rows differently from the claim
   page they came off would read as a second ledger rather than as the same one, moved.
   ================================================================ */

/* The head takes the interior display step, for the reason recorded on .as-statement above. It is
   .ah-copy rather than .as-copy because there is no shield beside it: the ledger is the figure. */
.as-page .as-keys-statement {
  margin: 0; max-width: 20ch;
  font-size: clamp(38px, 4.4vw, 56px); line-height: 1.02; letter-spacing: -0.03em;
}
.as-page .as-keys-statement .accent { color: var(--teal-dark); }

/* The rotation band and the operating band. Both are reading, so both take the ledger's measure. */
.as-page .as-rotation > .t-h1,
.as-page .as-operating > .t-h2 { margin: 0; max-width: 20ch; color: var(--ink); }
.as-page .as-rotation .sec-config { margin-top: var(--s5); max-width: 520px; }
.as-page .as-rotation .table-scroll { margin-top: var(--s6); }

/* ================================================================
   The strip under the hero: four ringed glyphs, a title and one line.
   ================================================================ */

/* THE COMP DRAWS ONE RULE ABOVE THIS ROW AND NOTHING ELSE AROUND IT: no boxes, no panel, and a
   hairline between the columns. The glyph sits BESIDE the words rather than over them, which is
   what keeps the row 84px tall instead of 150 and stops it competing with the hero above it. */
.as-page .as-strip { padding-block: var(--s6); border-top: 1px solid var(--hairline); }
.as-page .as-strip-row {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
}
.as-page .as-strip-item {
  display: flex; align-items: center; gap: var(--s4);
  padding-inline: var(--s5);
  min-width: 0;
}
.as-page .as-strip-item:first-child { padding-left: 0; }
.as-page .as-strip-item:last-child { padding-right: 0; }
.as-page .as-strip-item + .as-strip-item { border-left: 1px solid var(--hairline); }
.as-page .as-strip-item .rw-ring { width: 44px; height: 44px; }
.as-page .as-strip-item .rw-ring svg { width: 22px; height: 22px; }
/* A HUE ON EACH OF THE FOUR ITEMS, AND IT IS IDENTITY RATHER THAN STATE. The four facts are peers,
   and the hue says which of the four this is and nothing else. No item states a status, and the
   fourth one names the four evidence classes as words rather than as colours. The view sets --hue
   on the item, which is the mechanism sec-stack.ejs already uses for the five plates, so this route
   carries a hue one way rather than two. The fallback is the brand, so an item that declares none
   keeps the ring it had. The mix is a border colour and never a flat ground under text. */
.as-page .as-strip-item .rw-ring {
  border-color: color-mix(in srgb, var(--hue, var(--teal-dark)) 45%, transparent);
  color: var(--hue, var(--teal-dark));
}
.as-page .as-strip-body { display: grid; gap: 2px; min-width: 0; }
.as-page .as-strip-t { font-size: 15px; font-weight: 700; line-height: 1.3; color: var(--ink); }
.as-page .as-strip-l { font-size: var(--t-label); line-height: 1.45; color: var(--ink-2); }

/* ================================================================
   The instrument: the copy column and the five plates.
   ================================================================ */

.as-page .as-layers {
  padding-block: var(--s8);
  display: grid; grid-template-columns: minmax(0, 31fr) minmax(0, 69fr);
  align-items: center; gap: var(--s7);
  border-top: 0;
}
.as-page .as-layers-h { margin: var(--s4) 0 0; max-width: 16ch; }
.as-page .as-layers-h .accent { color: var(--teal-dark); }
.as-page .as-layers-lead {
  margin: var(--s4) 0 var(--s6);
  max-width: 44ch;
  font-size: var(--t-body); line-height: 1.6; color: var(--ink-lead);
}
.as-page .as-layers-fig { min-width: 0; }

/* ---- The five plates ----------------------------------------------------
   ONE ROW IS A PLATE AND ITS CONSEQUENCE. The plate is an svg slab with the label laid over it in
   HTML, so the words stay at the 14px floor at every width, stay selectable and stay in the reading
   order. The consequence sits at the end of a leader line, in its own column.

   THE ROWS OVERLAP BY A PERCENTAGE OF THE FIGURE'S WIDTH, not by a pixel count. A margin-top
   percentage resolves against the containing block's WIDTH, so the stack keeps the comp's
   proportions as the figure narrows: the slab is 190 tall on a 560 box, and -15.7% of the width
   leaves each plate 82 of its 190 showing, which is the comp's own pitch.

   WHERE THE LABEL SITS, AND IT IS MEASURED RATHER THAN CHOSEN. At 30 per cent from the left the
   slab's own back edge is at y=43 of 190 and the next slab's back edge crosses at y=125. The label
   is placed between those two, so it lands on its own plate's face and the plate below never covers
   it. Every label also outranks every slab in the stacking order, which is what the two z-indexes
   below are for: the rows carry no z-index of their own, so all ten elements compete in one context.
   ---------------------------------------------------------------------- */
.as-page .sec-stack { list-style: none; margin: 0; padding: 0; position: relative; }

.as-page .sec-layer {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 230px);
  align-items: center; gap: var(--s4);
  position: relative;
}
.as-page .sec-layer + .sec-layer { margin-top: -15.7%; }

.as-page .sec-layer-art { position: relative; min-width: 0; }
.as-page .sec-slab { display: block; width: 100%; height: auto; position: relative; z-index: 1; }

/* THE PLATE IS THE HUE. The face is the hue at low alpha over the page, the front edge the same hue
   darker, and the rim the hue at full strength: three steps of one colour is what makes a flat
   polygon read as a lit slab. --hue is set on the row by the partial. */
.as-page .sec-slab-face { fill: var(--hue); fill-opacity: 0.16; stroke: var(--hue); stroke-opacity: 0.55; stroke-width: 1.5; }
.as-page .sec-slab-edge { fill: var(--hue); fill-opacity: 0.32; stroke: var(--hue); stroke-opacity: 0.4; stroke-width: 1; }
.as-page .sec-slab-rim { fill: none; stroke: var(--hue); stroke-width: 2; }
/* The slab alone carries the shadow. On the row it would fall under the consequence text as well,
   which is the one thing on this figure that has to read as flat type on the page ground. */
.as-page .sec-slab { filter: drop-shadow(0 8px 20px rgba(0, 0, 0, 0.5)); }

.as-page .sec-layer-label {
  position: absolute; z-index: 2;
  left: 28%; right: 9%; top: 22%;
  margin: 0;
  display: grid; grid-template-columns: 34px minmax(0, 1fr); align-items: center;
  gap: 2px var(--s3);
}
.as-page .sec-layer-i { grid-row: 1 / 3; color: var(--hue); }
.as-page .sec-layer-i svg { width: 26px; height: 26px; display: block; }
.as-page .sec-layer-t {
  font-size: 15px; font-weight: 700; line-height: 1.2;
  text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--ink);
}
.as-page .sec-layer-l { font-size: var(--t-label); line-height: 1.4; color: var(--ink-row); }

/* THE CONSEQUENCE AND ITS LEADER LINE. The line is a hairline of the plate's own hue, so the eye
   carries the colour across the gap and lands on the sentence that belongs to it. */
.as-page .sec-layer-says { position: relative; z-index: 2; display: grid; gap: var(--s2); justify-items: start; padding-left: var(--s6); }
.as-page .sec-layer-lead {
  position: absolute; left: 0; top: 50%;
  width: var(--s5); height: 1px;
  background: var(--hue); opacity: 0.6;
}
.as-page .sec-layer-says-t { margin: 0; font-size: var(--t-label); line-height: 1.5; color: var(--ink-lead); }

/* ================================================================
   The three routes out.
   ================================================================ */

.as-page .as-routes { padding-block: var(--s7); border-top: 0; }
.as-page .as-routes-h { margin: 0 0 var(--s5); }
.as-page .sec-routes {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s5);
}
.as-page .sec-route {
  display: grid; align-content: start; gap: var(--s3);
  padding: var(--s5);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
  background: linear-gradient(180deg, var(--paper-alt) 0%, var(--paper) 100%);
}
.as-page .sec-route-t { margin: 0; font-size: 17px; font-weight: 700; line-height: 1.3; color: var(--ink); }
.as-page .sec-route-l { margin: 0; font-size: var(--t-label); line-height: 1.5; color: var(--ink-2); }
.as-page .sec-route-a {
  justify-self: start;
  font-size: var(--t-label); font-weight: 600; color: var(--brand-strong);
  text-decoration: none;
}
.as-page .sec-route-a:hover { text-decoration: underline; }
.as-page .sec-route-arrow { margin-left: var(--s2); }

/* ================================================================
   The close, on a photograph.
   ================================================================ */

/* THE BAND IS INSIDE THE PAGE MEASURE AND NOT FULL BLEED, because every band on this route is. So it
   takes a radius and clips the picture, which is the one change from the home page's closing band. */
.as-page .as-close {
  position: relative; overflow: hidden;
  border-top: 0; border-radius: var(--r-3);
  margin-top: var(--s7);
  padding: 0;
}
.as-page .as-close-bg { opacity: 0.65; object-position: right center; }
/* The veil fades the picture into the page ground from the left and the bottom, so the four lines
   sit on ground rather than on the bright part of the photograph. */
.as-page .as-close-veil {
  background:
    linear-gradient(to right, var(--paper) 0%, var(--paper) 30%, transparent 92%),
    linear-gradient(to top, var(--paper) 0%, transparent 60%);
}
.as-page .as-close-in {
  position: relative; z-index: 2;
  display: flex; align-items: center; justify-content: space-between; gap: var(--s6);
  padding: var(--s7);
}
.as-page .as-close-copy { max-width: 46ch; }
.as-page .as-close-h { margin: var(--s3) 0 0; max-width: 18ch; }
.as-page .as-close-h .accent { display: block; color: var(--teal-dark); }
.as-page .as-close-l { margin: var(--s4) 0 0; font-size: var(--t-body); line-height: 1.55; color: var(--ink-lead); }
.as-page .as-close-a { margin-top: var(--s6); }
.as-page .as-close-marks {
  margin: 0; display: grid; gap: 2px; text-align: right;
  font-size: var(--t-label); font-weight: 600; line-height: 1.4;
  text-transform: uppercase; letter-spacing: 0.18em;
  color: var(--ink-2);
}

/* ================================================================
   What is left behind a disclosure: the rotation model and the evidence rows.
   ================================================================ */

/* THE TRACK IS minmax(0, 1fr) AND NOT auto, WHICH IS WHAT KEEPS THIS BOX INSIDE THE VIEWPORT.
   A grid track sized `auto` takes the max-content width of what sits in it, and a single column
   grid with no template is exactly that. Something inside that will not wrap, a `pre` of one long
   line or a nowrap row, then makes the track wider than the box and the whole document scrolls
   sideways. Measured: this route at 768 wide took the document to 810px, with this track at 780
   inside a 707px wrap. `minmax(0, 1fr)` lets the track be narrower than its content, and the
   scrolling container inside it does its job. */
.as-page .as-depth { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s3); padding-top: var(--s7); }

.as-page .drawer {
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
  background: var(--paper-alt);
  padding-inline: var(--s5);
}

.as-page .drawer > summary { padding-block: var(--s3); }
.as-page .drawer[open] { background: var(--paper-alt); }

/* A drawer inside a drawer keeps the indent the base sheet gives it and drops back to the page
   ground, so two nested panels do not read as one. */
.as-page .drawer .drawer { background: var(--paper); }

/* ================================================================
   The narrow states.
   ================================================================ */

/* THE INSTRUMENT GOES TO ONE COLUMN FIRST, AT 1200 rather than at 1000, and the reason is the
   figure. The plates carry a title and a line on the face of each slab, and the label band is 43 per
   cent of the slab's height. Below a figure width of about 640 that band is under 60px and the line
   on a plate breaks to three. So the copy goes on top and the figure takes the whole measure, which
   is the same rule CLAUDE.md states for the home page instrument. */
@media (max-width: 1200px) {
  .as-page .as-layers { grid-template-columns: minmax(0, 1fr); gap: var(--s6); }
  .as-page .as-layers-h { max-width: 24ch; }
  .as-page .as-layers-lead { max-width: 72ch; }
}

/* THE HERO STACKS AT 1000, which is where the copy column falls under 520 and the display size
   starts breaking the headline to three lines beside an object it no longer has room for. */
@media (max-width: 1000px) {
  .as-page .as-top { grid-template-columns: minmax(0, 1fr); gap: var(--s6); }
  .as-page .as-statement { max-width: 20ch; }
  .as-page .as-shield-slot { justify-content: flex-start; }
  .as-page .as-ledger-head { grid-template-columns: minmax(0, 1fr); }
  .as-page .as-strip-row { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s5) 0; }
  .as-page .as-strip-item:nth-child(odd) { padding-left: 0; }
  .as-page .as-strip-item:nth-child(even) { padding-right: 0; }
  .as-page .as-strip-item:nth-child(odd) { border-left: 0; }
  .as-page .sec-routes { grid-template-columns: minmax(0, 1fr); }
  .as-page .as-close-in { flex-direction: column; align-items: flex-start; padding: var(--s7) var(--s6); }
  .as-page .as-close-marks { text-align: left; }
}

/* THE PLATES STOP CARRYING THEIR CONSEQUENCE BESIDE THEM AT 820, which is a designed narrow state
   rather than two squeezed columns. The consequence moves under the plate, the leader line goes with
   it, and the overlap drops from 15.7 per cent to 4 so the sentence has ground to sit on. Measured
   at 768: at the wide overlap the consequence of one plate landed under the slab of the next. */
@media (max-width: 820px) {
  .as-page .sec-layer { grid-template-columns: minmax(0, 1fr); }
  .as-page .sec-layer + .sec-layer { margin-top: -13%; }
  /* THE CONSEQUENCE MOVES ON TO THE PLATE, under the line it belongs to, and the stack keeps
     overlapping. The first narrow state put it in the row below the drawing and dropped the overlap
     to 4 per cent so it had ground to sit on: measured at 768, that made each plate 235px tall with
     28px of overlap, so the figure stopped reading as a stack and became five separate diamonds
     1825px long. On the plate, the pitch stays at 13 per cent of the width and the sentence lands
     between its own plate's lower edge and the top vertex of the plate below it. */
  .as-page .sec-layer-label { left: 24%; right: 6%; top: 26%; }
  .as-page .sec-layer-says {
    position: absolute; left: 24%; right: 6%; top: 50%;
    padding-left: 0;
  }
  .as-page .sec-layer-lead { display: none; }
}

/* THE WORDS COME OFF THE PLATE AT 620, because under that width they no longer fit on its face.
   Measured at 500: the title wrapped to two lines and the label ran 59px into a 151px drawing, so
   the label and the consequence under it overlapped by 23px. Below this width each plate keeps a
   light overlap and carries its title, its line and its consequence underneath, which is a column of
   five labelled plates rather than a stack with unreadable type on it. */
@media (max-width: 620px) {
  .as-page .sec-layer { gap: var(--s3); }
  /* The drawing stops growing with the column here. At 500 a full width slab ran 151px tall and the
     five rows ran 1340, which is a phone screen and a half of one figure. */
  .as-page .sec-layer-art { max-width: 340px; }
  .as-page .sec-layer + .sec-layer { margin-top: var(--s5); }
  .as-page .sec-layer-label {
    position: static; left: auto; right: auto; top: auto;
    margin-top: var(--s3);
  }
  .as-page .sec-layer-says { position: static; left: auto; right: auto; top: auto; }
}

/* THE ROWS STOP BEING A TABLE AT 900 AND BECOME A LIST OF LABELLED VALUES, which is a designed
   narrow state rather than five tracks squeezed. The head row goes, each cell shows its own name,
   and the key name takes a line of its own above the four values. Measured at 768: five tracks put
   "Certified or vouched by" on four lines and a value on eleven. */
@media (max-width: 900px) {
  .as-page .as-heads { display: none; }
  .as-page .as-row { grid-template-columns: minmax(0, 1fr); gap: var(--s3); padding-block: var(--s5); }
  .as-page .as-cells { grid-column: 1; grid-template-columns: minmax(0, 1fr); gap: var(--s3); }
  .as-page .as-row-t { font-size: var(--t-h3); font-weight: 700; }
  .as-page .as-lab { display: block; margin-bottom: 2px; }
  .as-page .as-figures { grid-template-columns: minmax(0, 1fr); }
}

/* TWO PAIRS TO A LINE WHILE THE ROW IS STILL WIDE ENOUGH TO CARRY THEM. Measured at 768 with the
   four pairs in one column: a row ran 350px and the sixteen rows ran 5600, which is a list nobody
   reaches the end of. The row is 660 wide there, so a value of about twelve words lands on two
   lines in half of it, and a row runs near 190. The rule sits after the 900 block and beats it on
   source order at the same weight, which is why it is written as a range rather than a floor. */
@media (min-width: 620px) and (max-width: 900px) {
  .as-page .as-cells { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s4); }
}

@media (max-width: 560px) {
  .as-page .sec-panel { padding: var(--s4); }
  /* THE STRIP BECOMES ONE COLUMN. Measured at 390: two columns left about 150px beside the 44px
     ring, so three of the four titles broke to three lines and one line ran to seven. */
  .as-page .as-strip-row { grid-template-columns: minmax(0, 1fr); gap: var(--s5); }
  .as-page .as-strip-item { padding-inline: 0; }
  /* Three classes, because the rule that draws the divider is `.as-strip-item + .as-strip-item` and
     a two class reset loses to it. Two stubs of hairline survived the first attempt. */
  .as-page .as-strip-item + .as-strip-item { border-left: 0; }
  /* THE THREE CONTROLS BECOME A COLUMN. Flowing, the first takes a row, the second and third share
     one, and the strip reads as two rows of different things. Three full width controls read as one
     list. */
  .as-page .as-ledger-tray { flex-direction: column; }
  .as-page .as-filter { width: 100%; justify-content: space-between; }
  .as-page .as-row { padding-inline: 0; }
  .as-page .as-row:hover { background: transparent; }
}

@media (prefers-reduced-motion: reduce) {
  .as-page .as-filter { transition: none; }
}

/* ---- src/parts/architecture-pages.css ---- */
/* The three pages under /architecture: runtime, security and deployment.
   Partials: key-custody.ejs.

   ONE BRAND ELEMENT PER FIGURE. Every rule that names var(--teal) sits under
   [data-treat="product"], so the one colour rule can see it and so a reader can see it. The
   customer's runtimes, the customer's keys and the customer's environment are all card grounds with
   a rule stroke and ink icons. Making any of them teal would say they are Raidiam.

   NO FIGURE HAS A CARD OF ITS OWN. .figure paints a card ground and a shadow, and with it the page
   carried four grounds stacked: page, figure card, band, tile. The bands are the objects here, so
   each figure is transparent and its bands sit on the page ground, where the product band's glow
   has somewhere to fall. This is the same decision control-plane.css records.

   THE RESET IS WRITTEN AT .figure.<name> RATHER THAN .<name>, one specificity step above the base
   rule. A plain class selector ties the reset to load order, and this rule has already moved once:
   it lived in site.css, which loads after every part, and moved into the base sheet on 12 September.
   Two classes win from either file, so the reset survives it moving back. Checked by computed style
   on all three routes rather than by reading the cascade: background transparent, border 0px,
   box-shadow none, padding 0px.

   NO TEXT SITS ON A COLOUR-MIX. packages/ui/tools/contrast.mjs enumerates token PAIRS BY NAME and
   never reads CSS, so a mix under a paragraph is gated by nothing at all. Every ground below is a
   plain token; the mixes are in borders, shadows and one gradient, where no text lands.

   WHAT HAPPENS AT 390. Three columns become one, and every grid track is minmax(0, 1fr) so a long
   word cannot push a track past the viewport. */

/* ================================================================
   Shared: the head, the payoff and the close of an architecture route.
   ================================================================ */

/* WHAT THIS REPLACED, AND WHY. The four routes each opened with a photograph, a bare display line
   and a lede, then ran six or seven bands of tables under it. A business panel scrolled past two of
   them. These classes give all four the shape the target build uses on its one page: an eyebrow, a
   two line display where the second line carries the accent, a lead of about 24 words, two pills,
   one instrument, four outcomes against a hairline, and one call to action.

   THE GROUND IS THE AMBIENT GLOW, NOT A PHOTOGRAPH. Treatment 5 in rw.css is the very large soft
   pool the target puts behind its figure, and it is what stops the page ground reading as flat. The
   photographs stay published; these four routes stopped drawing them, because a picture behind a
   reading instrument competes with it.

   WHAT THESE CLASSES REFUSE TO DRAW. A second heading over the instrument, a legend, a lifecycle
   strip and a band of section links. The display line states the proposition, the instrument states
   it as a picture, and a heading between them states it a third time. */

/* The hero. The copy column is 500px, which is the target's, and the instrument takes the rest.
   BELOW 1500 THE COPY GOES ON TOP AND THE INSTRUMENT TAKES THE FULL WIDTH. The target is drawn
   wider than 1440 and scrolls sideways there; this site may not, and four cards carrying three rows
   each need the width. Matching its proportion rather than its pixels is the rule CLAUDE.md sets. */
.ah-top { position: relative; display: grid; gap: var(--s7); align-items: start; }
.ah-top > * { position: relative; z-index: 1; }
.ah-glow { z-index: 0; }
.ah-copy { display: grid; gap: var(--s5); max-width: 500px; }
.ah-copy > * { margin: 0; }
.ah-copy .eyebrow { letter-spacing: 0.22em; }
.ah-copy .t-display .accent { color: var(--teal-dark); }
.ah-lead { font-size: var(--t-body); line-height: var(--t-body-line); color: var(--ink-2); max-width: 44ch; }
.ah-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s4); margin-top: var(--s2); }
@media (min-width: 1500px) {
  .ah-top { grid-template-columns: 500px minmax(0, 1fr); gap: var(--s8); align-items: center; }
}

/* The payoff. One line, then four outcomes of about ten words each, on the target's benefits row:
   a 52px ringed glyph, a 16px title, a 14px line, and a vertical hairline between columns. */
.ah-payoff { display: grid; gap: var(--s6); }
.ah-payoff-line { margin: 0; max-width: 30ch; }
.ah-outcomes {
  list-style: none; margin: 0; padding: var(--s6) 0 0;
  border-top: 1px solid var(--hairline);
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s6) 0;
}
.ah-outcome { display: flex; gap: var(--s4); padding-inline: var(--s6); }
.ah-outcome:first-child { padding-left: 0; }
.ah-outcome + .ah-outcome { border-left: 1px solid var(--hairline); }
.ah-outcome-body { display: grid; gap: var(--s2); align-content: start; }
.ah-outcome-t { margin: 0; font-size: var(--t-h3); font-weight: var(--t-h3-weight); line-height: var(--t-h3-line); color: var(--ink); }
.ah-outcome-l { margin: 0; font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-2); max-width: 26ch; }
.ah-outcome .rw-ring .sc-glyph { display: inline-flex; }
@media (max-width: 1100px) {
  .ah-outcomes { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ah-outcome:nth-child(3) { padding-left: 0; border-left: 0; }
}
@media (max-width: 620px) {
  .ah-outcomes { grid-template-columns: minmax(0, 1fr); }
  .ah-outcome { padding-inline: 0; }
  .ah-outcome + .ah-outcome { border-left: 0; }
}

/* The close and the handover. One call to action, then the link to the next page in the section. */
.ah-close { display: grid; gap: var(--s6); }

/* ================================================================
   /architecture/runtime: three runtimes above one Connect band.
   ================================================================ */

/* THE ROWS LINE UP ACROSS THE THREE CARDS, and that is the whole use of the figure: a reader
   compares one question across three runtimes, and can only do it when the answers sit on one line.
   Left to itself each card is its own grid, so a two line "runs" in the middle column pushed its
   assurance word a line below its neighbours' and the comparison stopped working.
   The card spans six rows of the outer grid and takes its track sizes from it, and the fact list
   spans the last three so the three questions line up too. Where subgrid is unsupported the cards
   fall back to their own tracks, which is the layout this replaces rather than a broken one. */

/* The facts are a definition list rather than three sentences, because the point of the row is that
   the SAME three questions have different answers in each column, and a reader compares across the
   row only when the labels line up. */
/* The assurance word is the one thing that differs by runtime and the one thing a reader should be
   able to find without reading. It is weighted, not coloured: green means observed and nothing
   else, and an attested copy is not an observation. */

/* ================================================================
   /architecture/security: where each private half stays.
   ================================================================ */

.figure.key-custody { background: transparent; padding: 0; border: 0; box-shadow: none; display: block; }
.key-custody .figure-caption { max-width: var(--measure-notes); }

/* The two columns are deliberately unequal: three custody models on the left against two Connect
   keys on the right. Equal tracks would read as a balance between the two, and the page's answer is
   that most of the estate's keys are not Raidiam's. */
.key-custody .kc-cols { display: grid; grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr); gap: var(--s4); align-items: start; }
.key-custody .kc-col { border-radius: var(--r-3); padding: var(--s5); }
.key-custody .kc-col[data-treat="customer"] {
  background: var(--paper-alt);
  border: 1px solid color-mix(in srgb, var(--rule) 30%, transparent);
}
.key-custody .kc-col[data-treat="product"] {
  background: var(--wash-teal);
  border: 1.5px solid var(--teal);
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--teal) 20%, transparent),
    0 0 40px -12px color-mix(in srgb, var(--teal) 50%, transparent);
}
.key-custody .kc-col-label {
  margin: 0; font-size: var(--t-label); font-weight: var(--t-label-weight); letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--ink-2);
}
.key-custody .kc-col[data-treat="product"] .kc-col-label { color: var(--teal-dark); }
.key-custody .kc-col-note { margin: var(--s2) 0 0; font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-2); }
.key-custody .kc-cards { list-style: none; margin: var(--s4) 0 0; padding: 0; display: grid; gap: var(--s3); }
.key-custody .kc-card {
  display: grid; gap: var(--s2);
  padding: var(--s4);
  border-radius: var(--r-2);
  background: var(--white);
  border: 1px solid color-mix(in srgb, var(--rule) 45%, transparent);
}
.key-custody .kc-col[data-treat="product"] .kc-card {
  background: var(--wash-teal);
  border-color: color-mix(in srgb, var(--teal) 34%, transparent);
}
.key-custody .kc-card > * { margin: 0; }
.key-custody .kc-model { font-size: var(--t-label); font-weight: var(--t-label-weight); line-height: 1.35; color: var(--ink); }
/* The lock sits on the HOLDER's line and nowhere else in the figure. That placement is the claim:
   the private half is inside this card, and there is no second lock inside the product band. */
.key-custody .kc-holder {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--s2); align-items: start;
  font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink);
}
.key-custody .kc-icon { display: grid; place-items: center; width: 18px; height: 18px; color: var(--ink-2); }
.key-custody .kc-icon svg { width: 100%; height: 100%; display: block; }
.key-custody .kc-public { font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-2); }

/* The crossing sentence is the connector. It is a sentence rather than an arrow because an arrow
   between a key card and a product band asserts that the key moves. */
.key-custody .kc-crossing {
  margin: var(--s5) auto; padding: var(--s3) var(--s5);
  max-width: 62ch; text-align: center;
  font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink);
  border-top: 1px solid color-mix(in srgb, var(--rule) 40%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--rule) 40%, transparent);
}

.key-custody .kc-publishes[data-treat="product"] {
  padding: var(--s5);
  border: 1.5px solid var(--teal);
  border-radius: var(--r-3);
  background: var(--wash-teal);
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--teal) 22%, transparent),
    0 0 22px -2px color-mix(in srgb, var(--teal) 40%, transparent),
    0 0 70px -10px color-mix(in srgb, var(--teal) 50%, transparent);
}
.key-custody .kc-publishes[data-treat="product"] .kc-band-label {
  margin: 0; font-size: var(--t-label); font-weight: var(--t-label-weight); letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--teal-dark);
}
.key-custody .kc-publishes[data-treat="product"] .kc-band-line {
  margin: var(--s2) 0 0; font-size: var(--t-small); line-height: var(--t-small-line);
  color: var(--ink-2); max-width: var(--measure-notes);
}
.key-custody .kc-publishes[data-treat="product"] .kc-items {
  list-style: none; margin: var(--s5) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s3);
}
.key-custody .kc-publishes[data-treat="product"] .kc-item {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--s3); align-items: start;
  padding: var(--s4);
  border: 1px solid color-mix(in srgb, var(--teal) 32%, transparent);
  border-radius: var(--r-2);
  box-shadow: inset 0 0 26px -12px color-mix(in srgb, var(--teal) 55%, transparent);
}
.key-custody .kc-publishes[data-treat="product"] .kc-item .kc-icon { color: var(--teal); width: 22px; height: 22px; }
.key-custody .kc-publishes[data-treat="product"] .kc-item-body { display: grid; gap: 2px; }
.key-custody .kc-publishes[data-treat="product"] .kc-item-label { font-size: var(--t-label); font-weight: var(--t-label-weight); line-height: 1.3; color: var(--ink); }
.key-custody .kc-publishes[data-treat="product"] .kc-item-line { font-size: var(--t-label); line-height: 1.45; color: var(--ink-2); }

@media (max-width: 1040px) {
  .key-custody .kc-cols { grid-template-columns: minmax(0, 1fr); }
  .key-custody .kc-publishes[data-treat="product"] .kc-items { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 560px) {
  .key-custody .kc-col { padding: var(--s4); }
  .key-custody .kc-publishes[data-treat="product"] { padding: var(--s4); }
  .key-custody .kc-crossing { padding: var(--s3) 0; }
}

/* THE DEPLOYMENT SPLIT FIGURE LEFT THIS FILE ON 29 SEPTEMBER 2026, with its partial. Its page draws
   packages/ui/partials/dpx-exit.ejs now, styled in dpx.css, and nothing else rendered the split. */

/* ================================================================
   All motion stops.

   The global block in ui.css shortens every animation to a fraction of a millisecond, which leaves
   an element wherever a single frame put it. These rules remove the animation outright and restore
   the end state: the arrows sit at full opacity and nothing is frozen mid travel.
   ================================================================ */

@media (prefers-reduced-motion: reduce) {
  .arch-sibling { transition: none; }
  .arch-sibling:hover { transform: none; }
}

/* ---- src/parts/av.css ---- */
/* THE ARTEFACT VIEWER, packages/ui/partials/av-artefact.ejs and av-layers.ejs.
 *
 * WHAT IT DRESSES. One published artefact read at four depths: what it proves, what it resolves to,
 * how it was signed, and the bytes. Layer 1 is the page and it is laid out as copy beside an
 * instrument, the way every other hero on this site is. Layers 2 to 4 are a stack of controls under
 * it, closed, each carrying its own identity hue on its left edge and its number.
 *
 * WHAT IT REFUSES TO DRAW.
 *
 *   A STATE COLOUR ON A LAYER. --ok, --att and --no never appear in this file. Green means Observed
 *   on this site and the evidence marks in layer 1 carry that vocabulary through .ev, which is
 *   dressed elsewhere. A hue here answers which layer, never what is true of it.
 *
 *   A SIZE UNDER THE FLOOR. The reference sets 13px and 12.5px on a card's smaller text. Nothing
 *   here goes below 14px, because a size below the floor is a readability rule rather than a style
 *   choice, and the stylesheet test enforces it.
 *
 *   A FLAT GROUND MADE WITH colour-mix UNDER TEXT. The hue reaches a panel through a gradient and a
 *   border, both of which carry no text, so the contrast gate can still name every pair that does.
 */

.av-page > .band:first-child { border-top: 0; }

/* THE HEADLINE SITS BESIDE THE INSTRUMENT, and the ledger runs under both. The copy column is held
   near the reference's 500, which is what lets the two calls to action sit side by side rather than
   stack, and the figure takes the rest. */
.av-grid {
  display: grid; gap: var(--s7);
  grid-template-columns: minmax(0, 520px) minmax(0, 1fr);
  align-items: center;
}
.av-head { display: grid; gap: var(--s6); }
.av-fig .av-layers { max-width: 780px; margin-inline: auto 0; }
.av-tail {
  display: flex; flex-wrap: wrap; gap: var(--s5) var(--s7);
  align-items: center; justify-content: space-between;
}
.av-copy { display: grid; gap: var(--s4); align-content: start; }
.av-eyebrow { color: var(--teal-dark); text-transform: uppercase; letter-spacing: 0.22em; margin: 0; }
.av-name { margin: 0; overflow-wrap: anywhere; }
.av-lede { margin: 0; font-size: 17px; line-height: 1.55; color: var(--ink-lead); }
.av-from { margin: 0; font-size: var(--t-label); color: var(--faint); }

/* The claims that rest on this file. One row each: the evidence mark in the site's own vocabulary,
   then the claim id, which is the join a reader can follow back to the evidence page. */
.av-claims {
  list-style: none; margin: 0; padding: 0; display: grid; gap: 1px;
  /* auto-fill rather than auto-fit, so an artefact cited by ONE claim gets a half width row rather
     than a row stretched to 1376 with its evidence mark a screen away from its name. */
  grid-template-columns: repeat(auto-fill, minmax(min(520px, 100%), 1fr));
  background: var(--hairline); border: 1px solid var(--hairline); border-radius: var(--r-2); overflow: hidden;
}
.av-claim {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--s3); align-items: center;
  padding: 10px var(--s4); background: var(--paper-alt);
}
.av-claim-text { display: grid; gap: 1px; min-width: 0; }
.av-claim-name { font-size: var(--t-label); font-weight: 600; color: var(--ink); text-decoration: none; }
.av-claim-name:hover { color: var(--brand-strong); text-decoration: underline; }
.av-claim-id { font-size: var(--t-label); color: var(--faint); overflow-wrap: anywhere; }

.av-facts { margin: 0; display: grid; gap: var(--s2); }
.av-fact { display: grid; grid-template-columns: 150px minmax(0, 1fr); gap: var(--s3); align-items: baseline; }
.av-fact dt { font-size: var(--t-label); color: var(--ink-2); }
.av-fact dd { margin: 0; font-size: var(--t-label); color: var(--ink-row); overflow-wrap: anywhere; }
.av-actions { display: flex; flex-wrap: wrap; gap: var(--s3); margin: var(--s2) 0 0; }

/* THE INSTRUMENT. The wrapper holds the aspect ratio of the drawing, so the words laid over it at
   percentage coordinates meet their own plate at every width. */
.av-fig { position: relative; }
.av-layers { position: relative; width: 100%; aspect-ratio: 560 / 376; color: var(--rule); }
.av-layers-svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.av-layers-label {
  position: absolute; margin: 0; display: grid; gap: 2px;
  grid-template-columns: 34px minmax(0, 1fr); align-content: center;
  transform: translateY(-50%);
}
.av-layers-n { grid-row: span 2; font-size: var(--t-label); font-weight: 600; font-family: var(--mono); }
.av-layers-title { font-size: 16px; font-weight: 600; color: var(--ink); }
.av-layers-line { font-size: var(--t-label); color: var(--ink-2); }
.av-layers-label-off .av-layers-title { color: var(--ink-2); }
.av-layers-label-off .av-layers-line { color: var(--faint); }

/* THE STACK. Three controls, each one press deeper than the last. */
.av-stack { display: grid; gap: var(--s3); }
.av-layer {
  border: 1px solid var(--hairline); border-left: 3px solid var(--av-hue); border-radius: var(--r-2);
  background: linear-gradient(180deg, var(--white), var(--paper-alt));
  overflow: hidden;
}
.av-open {
  display: grid; grid-template-columns: 40px minmax(0, 200px) minmax(0, 1fr) 24px;
  gap: var(--s3); align-items: center; width: 100%;
  padding: var(--s4) var(--s5); background: transparent; border: 0; cursor: pointer; text-align: left;
  font: inherit; color: var(--ink);
}
.av-open-n { font-family: var(--mono); font-size: var(--t-label); font-weight: 600; }
.av-open-title { font-size: 17px; font-weight: 600; }
.av-open-state { font-size: var(--t-label); color: var(--ink-2); }
.av-open-tri { justify-self: end; width: 10px; height: 10px; border-right: 2px solid var(--ink-2); border-bottom: 2px solid var(--ink-2); transform: rotate(45deg); }
.av-open[aria-expanded="true"] .av-open-tri { transform: rotate(225deg); }
.av-open:hover .av-open-title { color: var(--brand-strong); }

.av-body { padding: 0 var(--s5) var(--s5); display: grid; gap: var(--s4); border-top: 1px solid var(--hairline); padding-top: var(--s4); }
.av-body-from, .av-absent { margin: 0; font-size: var(--t-small); color: var(--ink-lead); max-width: 70ch; }
.av-group { display: grid; gap: var(--s2); }
.av-group-title { margin: 0; color: var(--ink-2); text-transform: uppercase; letter-spacing: 0.14em; }
.av-rows { margin: 0; display: grid; gap: 1px; background: var(--hairline); border: 1px solid var(--hairline); border-radius: var(--r-1); overflow: hidden; }
.av-row { display: grid; grid-template-columns: minmax(140px, 220px) minmax(0, 1fr); gap: var(--s3); padding: 10px var(--s3); background: var(--paper-alt); }
.av-row dt { font-size: var(--t-label); color: var(--ink-2); overflow-wrap: anywhere; }
.av-row dd { margin: 0; font-size: var(--t-label); color: var(--ink-row); overflow-wrap: anywhere; }
.av-prose { line-height: 1.5; }

/* The bytes. A div with the mono face, never a `pre`, which is what /evidence settled on for this
   material. It scrolls on both axes, so the partial gives it a role, a label and a tabindex. */
.av-bytes {
  background: var(--paper); border: 1px solid var(--hairline); border-radius: var(--r-1);
  padding: var(--s4); font-size: 14px; line-height: 1.6; color: var(--ink-row);
  white-space: pre; overflow: auto; max-height: 520px;
}
/* PROSE KEEPS THE READING MEASURE AND A TABLE TAKES THE WHOLE WIDTH. The verification register is
   one seven column table whose cells hold paragraphs, and at the 720px reading measure it scrolled
   sideways inside a box inside a panel. The markdown renderer already wraps a table in a focusable
   scrolling container, so this file adds none of its own: a second scroll box around the first is
   how a scrolling region loses the tabindex the renderer gave it. */
.av-doc > * { max-width: var(--read-max); }
.av-doc > .md-table { max-width: none; }
.av-fetch { margin: 0; font-size: var(--t-label); color: var(--ink-2); }

/* THE NARROW STATE IS DESIGNED RATHER THAN STACKED. Under 1080 the copy goes on top and the
   instrument takes the full width, which is what keeps four plates wide enough to carry their own
   titles. The same rule the same software page records: match the proportion, not the pixels. */
/* THE CONTROL ROW WRAPS RATHER THAN SQUEEZING. Measured at 390: the four column grid put the title
   in the third track and clipped it, and the chevron landed on the left of the number. The row is a
   wrap at this width, with the number, the title and the chevron on the first line and the state
   line under them. */
@media (max-width: 1080px) {
  .av-grid { grid-template-columns: minmax(0, 1fr); gap: var(--s6); }
  .av-open { display: flex; flex-wrap: wrap; align-items: center; gap: 6px var(--s3); }
  .av-open-title { flex: 1 1 auto; }
  .av-open-tri { order: 1; margin-left: auto; justify-self: auto; }
  .av-open-state { order: 2; flex-basis: 100%; }
}
/* THE FIGURE GETS TALLER RATHER THAN SMALLER. The plates are drawn with preserveAspectRatio none,
   so a taller frame gives each plate the height its two lines of words need. Nothing is hidden: the
   line that says a layer is not carried is the honest half of this figure and it stays on a phone. */
@media (max-width: 720px) {
  .av-layers { aspect-ratio: 560 / 700; }
  .av-layers-label { grid-template-columns: 26px minmax(0, 1fr); }
  .av-layers-title { font-size: var(--t-label); }
  .av-fact { grid-template-columns: minmax(0, 1fr); gap: 2px; }
  .av-row { grid-template-columns: minmax(0, 1fr); gap: 2px; }
  /* A claim row stacks its mark under its name here. Measured at 390 with the mark beside it: the
     evidence label took 190 of 330px and the claim id broke four ways down the middle of a word. */
  .av-claim { grid-template-columns: minmax(0, 1fr); gap: var(--s2); }
}

/* ---- src/parts/ax.css ---- */
/* /architecture: the page and its one instrument, packages/ui/partials/ax-decision.ejs.
 *
 * THE TREATMENTS ARE components/diagram-section.tsx's. The hub, the lit card, the pedestal, the
 * side panel and the ambient pool come from rw.css by class. This file places them, draws the stem,
 * the fan of wires and the two frames, and carries the page's own bands.
 *
 * rw.css SORTS AFTER THIS FILE, so a rule here that meets an rw rule at equal specificity loses.
 * Every override of an rw class is written under `.ax` for that reason.
 *
 * FOUR IDENTITY HUES AND NO STATE COLOUR. Each card carries its hue in `--hue`. Nothing on this page
 * is Observed, so --ok, --att and --no appear nowhere in this file.
 */

/* ---- THE PAGE ---- */
.ax-page { --page-max: 1472px; }
.ax-top { position: relative; padding-block: 3.5rem var(--s6); }
.ax-top-copy > * { margin: 0; }
.ax-eyebrow { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s3); font-size: 14px; font-weight: 600; letter-spacing: 0.22em; text-transform: uppercase; color: var(--brand-strong); }
.ax-eyebrow-rule { width: 1px; height: 14px; background: var(--rule); }
.ax-eyebrow-accent { color: var(--ink-2); }
.ax-headline { margin-top: var(--s4); line-height: 1.02; letter-spacing: -0.035em; max-width: 24ch; }
.ax-headline .accent { display: block; }
.ax-lead { margin-top: 1.25rem; max-width: 34rem; font-size: 17px; line-height: 1.55; color: var(--ink-lead); }
.ax-lead p { margin: 0; }
.ax-actions { margin-top: var(--s6); display: flex; flex-wrap: wrap; gap: var(--s4); }
/* ABOVE 1100 THE COPY TAKES TWO COLUMNS: the headline on the left, the lead and the actions on the
   right, which is the rhythm /use-cases/your-own-assistant draws over its instrument. */
@media (min-width: 1100px) {
  .ax-top-copy { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); column-gap: var(--s7, 4rem); grid-template-areas: "eyebrow eyebrow" "head lead" "head actions"; align-items: start; }
  .ax-eyebrow { grid-area: eyebrow; }
  .ax-headline { grid-area: head; }
  .ax-lead { grid-area: lead; margin-top: var(--s4); }
  .ax-actions { grid-area: actions; }
}

/* ---- THE OUTCOME ROW, the reference's benefits row: ringed 52px glyphs, hairlines between ---- */
.ax-payoff { padding-block: var(--s6); }
.ax-outcomes { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); }
.ax-outcomes li { display: flex; flex-direction: column; align-items: center; text-align: center; padding: 0 var(--s4); }
.ax-outcomes li + li { border-left: 1px solid var(--hairline); }
.ax-outcome-i { width: 52px; height: 52px; }
.ax-outcome-i svg { width: 26px; height: 26px; }
.ax-outcome-t { margin: var(--s4) 0 0; font-size: 18px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.ax-outcome-l { margin: var(--s2) 0 0; max-width: 19rem; text-wrap: balance; font-size: 15px; line-height: 1.5; color: var(--ink-2); }
@media (max-width: 900px) {
  .ax-outcomes { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: var(--s6); }
  .ax-outcomes li + li { border-left: 0; }
  .ax-outcomes li:nth-child(even) { border-left: 1px solid var(--hairline); }
}
@media (max-width: 480px) {
  .ax-outcomes { grid-template-columns: minmax(0, 1fr); }
  .ax-outcomes li:nth-child(even) { border-left: 0; }
}

/* ---- THE DRAWER: the strings a platform implements ---- */
.ax-strings { margin-top: var(--s6); border-top: 1px solid var(--hairline); border-bottom: 1px solid var(--hairline); }
.ax-strings > summary {
  display: flex; align-items: center; gap: var(--s3); padding: var(--s4) 0; cursor: pointer; list-style: none;
  font-size: 16px; font-weight: 600; color: var(--ink);
}
.ax-strings > summary::-webkit-details-marker { display: none; }
.ax-strings > summary::before {
  content: ""; width: 8px; height: 8px; flex: 0 0 auto;
  border-right: 2px solid var(--brand-strong); border-bottom: 2px solid var(--brand-strong);
  transform: rotate(-45deg); transition: transform 160ms ease;
}
.ax-strings[open] > summary::before { transform: rotate(45deg); }
/* THE HEADINGS ON THIS PAGE TAKE THE BODY FACE. h2 and h3 carry the display face site wide, and
   CLAUDE.md rule 1 is one family, Inter, on everything. */
.ax-page h2, .ax-page h3 { font-family: inherit; }
.ax-strings-t { margin: 0; font-size: 16px; line-height: 1.4; font-weight: 600; letter-spacing: normal; color: var(--ink); }
.ax-strings-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s4); padding-bottom: var(--s5); }
.ax-strings-set { --hue: var(--d-blue); }
.ax-strings-h { margin: 0 0 var(--s2); font-size: 14px; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; color: var(--hue); }
.ax-strings-set ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s1, 4px); }
.ax-strings-set li { font-family: var(--mono); font-size: 14px; line-height: 1.5; color: var(--ink); overflow-wrap: anywhere; }
@media (max-width: 1100px) { .ax-strings-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .ax-strings-grid { grid-template-columns: minmax(0, 1fr); } }
@media (prefers-reduced-motion: reduce) { .ax-strings > summary::before { transition: none; } }

/* ---- THE WAY ONWARD: the section's four routes ---- */
.ax-more-h { margin: 0 0 var(--s4); font-size: 14px; font-weight: 600; letter-spacing: 0.22em; text-transform: uppercase; color: var(--ink-2); }
.ax-more { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s4); }
.ax-more a {
  display: grid; grid-template-columns: auto 1fr; column-gap: var(--s3); row-gap: var(--s1, 4px); height: 100%;
  padding: var(--s4); border-radius: 12px; text-decoration: none;
  border: 1px solid var(--hairline); background: var(--paper-alt);
}
.ax-more a:hover { border-color: var(--rule); }
.ax-more-i { grid-row: span 2; color: var(--brand-strong); }
.ax-more-t { font-size: 16px; font-weight: 700; color: var(--ink); }
.ax-more-l { font-size: 14px; line-height: 1.45; color: var(--ink-2); }
@media (max-width: 1100px) { .ax-more { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .ax-more { grid-template-columns: minmax(0, 1fr); } }

/* ---- THE INSTRUMENT ---- */
.ax { position: relative; margin: 0; min-width: 0; }
.ax-glow { top: 60px; }
/* THE READING KEY SITS UNDER THE FIGURE AT EVERY WIDTH, and that is a deliberate departure from the
   reference, which draws its panels beside the figure. Its cards carry short words. These carry
   mark names such as aldercross.accredited.agent, and with panels beside the figure a card was
   230px wide at 1440 and every mark name broke over two lines. Under the figure the four cards take
   the full measure, and from 1440 up each mark name holds one line. At 1100 a card is about 227px
   wide and a mark name breaks, after a dot, which the partial allows and nowhere else. */
.ax-sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; border: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; }
.ax-main { position: relative; min-width: 0; display: grid; justify-items: center; }

/* THE HUB. The reference's hub card: a radial gradient from the top, a brand edge, a glow. */
.ax .ax-hub { width: min(100%, 680px); padding: var(--s5) var(--s5) var(--s4); }
.ax-hub-i { display: inline-flex; color: var(--brand-strong); filter: drop-shadow(0 0 10px var(--teal-dark)); }
.ax-hub-i svg { width: 44px; height: 44px; }
.ax-hub-t { margin: var(--s2) 0 0; font-family: inherit; font-size: 22px; line-height: 1.25; font-weight: 700; letter-spacing: normal; color: var(--ink); }
.ax-hub-l { margin: var(--s1, 4px) 0 0; font-size: 15px; line-height: 1.45; color: var(--ink-2); }
.ax-hub-items { list-style: none; margin: var(--s4) 0 0; padding: 0; display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s2); }
.ax-hub-items li {
  padding: 4px var(--s3); border-radius: 6px; font-size: 14px; font-weight: 500; color: var(--ink-row);
  border: 1px solid var(--hairline); background: var(--paper-alt);
}
.ax-hub-host { margin: var(--s4) 0 0; font-size: 14px; color: var(--ink-2); }
.ax-mono { font-family: var(--mono); font-size: 14px; }
.ax-hub-host .ax-mono { color: var(--ink); }

/* THE STEM AND THE CHIP. One wire joins the hub to a chip that states both directions: the read
   goes up, and the signed answer comes down. */
.ax-stem { width: 2px; height: 22px; background: var(--teal-dark); box-shadow: 0 0 8px var(--teal-dark); }
.ax-wire-chip {
  position: relative; z-index: 1; margin: 0; display: grid; gap: 2px; justify-items: start;
  padding: var(--s2) var(--s4); border-radius: 12px;
  border: 1px solid color-mix(in srgb, var(--teal-dark) 55%, transparent);
  background: var(--paper);
  box-shadow: 0 0 24px color-mix(in srgb, var(--teal-dark) 20%, transparent);
}
.ax-wire-row { display: flex; align-items: center; gap: var(--s2); font-size: 14px; font-weight: 600; color: var(--ink); }
.ax-wire-i { display: inline-flex; color: var(--brand-strong); }
.ax-wire-i svg { width: 16px; height: 16px; }

/* THE FAN. Four beziers from the chip to the four columns, drawn at a fixed height and stretched
   across the width. The columns have no gap between them, so each card's centre falls exactly at
   12.5, 37.5, 62.5 and 87.5 per cent, and the wires and arrowheads can be drawn in percentages. */
.ax-fan { position: relative; width: 100%; height: 124px; }
.ax-fan svg { position: absolute; inset: 0; width: 100%; height: 116px; overflow: visible; filter: drop-shadow(0 0 5px color-mix(in srgb, var(--teal-dark) 70%, transparent)); }
.ax-wire { fill: none; stroke: var(--teal-dark); stroke-width: 2; stroke-linecap: round; opacity: 0.85; vector-effect: non-scaling-stroke; }
.ax-pulse { fill: none; stroke: var(--brand-strong); stroke-width: 4; stroke-linecap: round; vector-effect: non-scaling-stroke; stroke-dasharray: 6 94; stroke-dashoffset: 6; opacity: 0; }
/* THE UPWARD HEAD sits under the chip, where the four reads meet, and points into it. */
.ax-head-up {
  position: absolute; top: -1px; left: 50%; transform: translateX(-50%);
  width: 0; height: 0; border-left: 6px solid transparent; border-right: 6px solid transparent;
  border-bottom: 12px solid var(--brand-strong);
}
.ax-head {
  position: absolute; top: 108px; transform: translateX(-50%);
  width: 0; height: 0; border-left: 6px solid transparent; border-right: 6px solid transparent;
  border-top: 12px solid var(--brand-strong);
}

/* THE ESTATES. Two dashed frames, and each frame is a boundary. Four equal columns with no gap:
   the frames are inset from their columns rather than spaced by a gap, so the card centres stay
   where the fan points. */
.ax-estates { position: relative; width: 100%; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); }
/* THE FRAME LABEL SITS ON THE BOTTOM EDGE ABOVE 1100. On the top edge it lay under the partner
   card's arrowhead at every width, because the label starts at the frame's left inset and the
   partner column is too narrow for it to clear the centre. */
.ax-frame {
  position: relative; min-width: 0;
  border: 1px dashed var(--rule); border-radius: 16px;
  padding: var(--s4) 0 var(--s6);
}
.ax-frame-yours { grid-column: 1 / span 3; margin-right: 10px; }
.ax-frame-partner { grid-column: 4; margin-left: 10px; }
.ax-frame-l {
  position: absolute; bottom: -12px; left: var(--s4); margin: 0;
  padding: 0 var(--s2); background: var(--paper);
  font-family: inherit; font-size: 14px; line-height: 22px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-2);
}
.ax-cells { list-style: none; margin: 0; padding: 0; display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); }
/* A CELL IS NOT A COLUMN, because the frames are inset and bordered. The yours frame gives up 10px
   on its right and 2px of border across three cells, so cell i sits 4i+1 px left of its column's
   centre; the partner frame's one cell sits 5px right of its column's. Padding one side more than
   the other by twice that puts each card back on the centre the fan points at. */
.ax-cell { position: relative; min-width: 0; padding: 0 var(--s3); display: grid; grid-template-rows: auto 1fr; }
.ax-frame-yours .ax-cell:nth-child(1) { padding-left: calc(var(--s3) + 1px); padding-right: calc(var(--s3) - 1px); }
.ax-frame-yours .ax-cell:nth-child(2) { padding-left: calc(var(--s3) + 5px); padding-right: calc(var(--s3) - 5px); }
.ax-frame-yours .ax-cell:nth-child(3) { padding-left: calc(var(--s3) + 9px); padding-right: calc(var(--s3) - 9px); }
.ax-frame-partner .ax-cell { padding-left: calc(var(--s3) - 5px); padding-right: calc(var(--s3) + 5px); }
.ax-branch { display: none; }
.ax .ax-ped { margin-bottom: -6px; }
.ax .ax-card { display: flex; flex-direction: column; padding: var(--s4); min-width: 0; }
.ax-role { margin: 0; font-size: 14px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--hue); }
.ax-title { margin: var(--s1, 4px) 0 0; font-family: inherit; font-size: 17px; line-height: 1.25; font-weight: 700; letter-spacing: normal; color: var(--ink); }
.ax-owner { margin: 2px 0 0; font-size: 14px; color: var(--ink-2); }
.ax-rows { margin: var(--s4) 0 0; display: grid; gap: var(--s3); }
.ax-rows > div { display: grid; gap: 2px; padding-left: var(--s3); border-left: 2px solid color-mix(in srgb, var(--hue) 55%, transparent); }
.ax-rows dt { font-size: 14px; font-weight: 600; color: var(--ink-row); }
.ax-rows dd { margin: 0; font-size: 14px; line-height: 1.4; color: var(--ink-2); }
.ax-rows dd.ax-mono { color: var(--ink); }
.ax-decides {
  margin: auto 0 0; padding-top: var(--s4);
  display: flex; align-items: center; gap: var(--s2);
  font-size: 14px; font-weight: 700; color: var(--brand-strong);
}
.ax-decides-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--brand-strong); box-shadow: 0 0 8px var(--teal-dark); }

/* THE READING KEY. The reference's side panels, set in a row under the figure. */
.ax-key { margin-top: var(--s6); display: grid; gap: var(--s4); grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); align-items: start; }
.ax .ax-panel { padding: var(--s4); }
.ax .ax-panel-h { font-family: inherit; line-height: 1.4; }
.ax-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s3); }
.ax-list li { display: flex; align-items: flex-start; gap: var(--s3); font-size: 15px; line-height: 1.4; color: var(--ink-row); }
.ax-list-i { display: inline-flex; color: var(--brand-strong); }
.ax-list-i svg { width: 19px; height: 19px; }
.ax-hold { grid-column: 1 / -1; margin: 0; padding: var(--s3) var(--s4); border-left: 2px solid var(--brand-strong); font-size: 15px; line-height: 1.5; color: var(--ink-row); }
.ax-caption { margin: var(--s5) 0 0; font-size: 14px; color: var(--ink-2); text-align: center; }

/* THE PULSE. A read travels up each wire in turn and the signed answer comes back down. Every word is on screen in every frame, so
   a still taken at any moment carries the whole figure, and reduced motion gets it standing still. */
@media (prefers-reduced-motion: no-preference) {
  .ax-pulse-1 { animation: ax-pulse 8s linear infinite; }
  .ax-pulse-2 { animation: ax-pulse 8s linear infinite 2s; }
  .ax-pulse-3 { animation: ax-pulse 8s linear infinite 4s; }
  .ax-pulse-4 { animation: ax-pulse 8s linear infinite 6s; }
}
@keyframes ax-pulse {
  0% { opacity: 1; stroke-dashoffset: -94; }
  11% { opacity: 1; stroke-dashoffset: 0; }
  22% { opacity: 1; stroke-dashoffset: -94; }
  24%, 100% { opacity: 0; stroke-dashoffset: -94; }
}

/* ---- THE NARROW STATE: the fan becomes a spine ----
   Below 1100 four cards side by side cannot carry four rows each. The frames stack, the cards stack
   inside them, and one vertical wire runs down the left of both frames with a short branch and an
   arrowhead to each card's pedestal, or to the card itself below 700 where the pedestal goes. */
@media (max-width: 1099px) {
  /* THE HUB TAKES THE FULL MEASURE AND THE STEM DROPS FROM ITS LEFT, on the line the spine runs down,
     so one wire leaves Connect, passes through the chip that names what it carries, and becomes the
     spine. Centred, the stem and the chip left the spine starting in the air. */
  .ax-main { justify-items: stretch; }
  .ax .ax-hub { width: 100%; }
  .ax-stem { justify-self: start; margin-left: 10px; }
  .ax-wire-chip { justify-self: start; justify-items: start; text-align: left; }
  .ax-fan { display: none; }
  .ax-estates { grid-template-columns: minmax(0, 1fr); row-gap: var(--s6); padding-left: 28px; margin-top: var(--s5); }
  .ax-frame { padding: var(--s6) 0 var(--s3); }
  .ax-frame-l { bottom: auto; top: -12px; }
  .ax-frame-yours, .ax-frame-partner { grid-column: 1; margin: 0; }
  /* THE SPINE IS DRAWN BY THE CELLS, one length each, so it ends where the last branch leaves it.
     A cell's length runs from the foot of whatever is above it to its own foot: the chip for the
     first cell of your estate, the cell above inside a frame, and the last cell of your estate for
     the partner's first cell. The last cell stops at its branch. x = 10px on the estates box, which
     is 19px left of a cell. */
  .ax-cell::before {
    content: ""; position: absolute; left: -19px; width: 2px; top: calc(-1 * var(--s4)); bottom: 0;
    background: var(--teal-dark); box-shadow: 0 0 6px var(--teal-dark);
  }
  .ax-frame-yours .ax-cell:first-child::before { top: calc(-1 * (var(--s5) + 1px + var(--s6))); }
  .ax-frame-partner .ax-cell:first-child::before { top: calc(-1 * (var(--s3) + 1px + var(--s6) + 1px + var(--s6))); }
  .ax-frame-partner .ax-cell:last-child::before { bottom: auto; height: calc(var(--s3) + 1px + var(--s6) + 1px + var(--s6) + 45px); }
  /* THE UPWARD HEAD sits at the top of the spine, under the chip, and points into it: the read. */
  .ax-frame-yours .ax-cell:first-child::after {
    content: ""; position: absolute; left: -24px; top: calc(-1 * (var(--s5) + 1px + var(--s6)));
    width: 0; height: 0; border-left: 6px solid transparent; border-right: 6px solid transparent;
    border-bottom: 12px solid var(--brand-strong);
  }
  .ax-cells { grid-auto-flow: row; grid-auto-columns: auto; row-gap: var(--s4); }
  .ax-frame .ax-cell, .ax-frame-yours .ax-cell:nth-child(n), .ax-frame-partner .ax-cell { padding: 0 var(--s3); grid-template-columns: 96px minmax(0, 1fr); grid-template-rows: auto; align-items: start; }
  .ax .ax-ped { margin: var(--s2) 0 0; }
  /* THE BRANCH runs from the spine, across the frame's edge, to the start of the cell's content: the
     pedestal column from 700 to 1099, and the card itself below 700. */
  .ax-branch {
    display: block; position: absolute; top: 44px; left: calc(-28px - 1px + 11px); width: calc(28px - 11px + var(--s3) + 1px);
    height: 2px; background: var(--teal-dark);
  }
  .ax-branch::after {
    content: ""; position: absolute; right: -2px; top: -5px;
    border-top: 6px solid transparent; border-bottom: 6px solid transparent; border-left: 10px solid var(--brand-strong);
  }
  .ax-rows { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--s4); }
}
@media (max-width: 700px) {
  .ax-frame .ax-cell, .ax-frame-yours .ax-cell:nth-child(n), .ax-frame-partner .ax-cell { grid-template-columns: minmax(0, 1fr); }
  .ax .ax-ped { display: none; }
  .ax-rows { grid-template-columns: minmax(0, 1fr); }
  .ax .ax-card { border-top-width: 2px; }
}

/* ---- src/parts/blast.css ---- */
/* The scoped blast radius. Partial: packages/ui/partials/blast.ejs, scoped mode.

   WHAT THIS INSTRUMENT HAS TO SAY. A withdrawal is a choice of scope, the scope is bounded, and the
   bound is printed on an artefact. So the three parts are a rail of scopes, a figure that draws
   exactly what one scope reaches, and the consequence of that scope in business words before
   protocol words. Everything else on this page exists to support that reading.

   NO SCRIPT, AND THAT IS THE DESIGN RATHER THAN A SAVING. The scope in view is a radio group. Five
   figures and five panels are in the page and the checked radio shows one of each. A reader can
   therefore go from the widest scope back to the narrowest and see the narrow one, which is the
   whole comparison; the scripted instrument in tree mode only ever adds gone nodes, so going
   backwards there needs a reset. Arrow keys move through the group and change the figure, which is
   what a radio group is for.

   THE PAIRS ARE POSITIONAL. Nothing below names a scope id, because the ids are the site's and this
   file is the component's. The nth radio shows the nth figure, the nth panel, the nth list, and
   marks the nth tab. Six pairs are written out, which is the most scopes this instrument takes.

   COLOUR CARRIES A STATE AND SO DOES THE MARK. A node keeps its authority (tick), loses it (cross)
   or sits outside the control's reach (circle). A reader who cannot separate green from red still
   reads three different silhouettes, and every chip also carries its state in a <title>.

   NO BRAND COLOUR ANYWHERE IN HERE. Nothing in this instrument is a Raidiam product, so nothing in
   it may be filled teal. The selected tab uses the teal WASH, which is the ground the stage rail
   already uses for the current stage, and its border uses the action colour. Filling it would have
   said the scope is Raidiam's. */

.blast-scoped {
  margin: var(--s5) 0 0; min-width: 0;
  padding: var(--s5);
  background: var(--paper-alt);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
}
.blast-scoped .bs-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 348px);
  grid-template-areas: "scopes scopes" "figure panel";
  gap: var(--s5);
  align-items: start;
}

/* ---- the scope rail ---- */

.blast-scoped .bs-scopes { grid-area: scopes; display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--s2); align-content: start; }
.blast-scoped .bs-scopes > .bs-rail-head { grid-column: 1 / -1; }
.blast-scoped .bs-rail-head {
  margin: 0 0 var(--s1);
  font-size: var(--t-label); font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--ink-2);
}
.blast-scoped .bs-tab {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 2px var(--s2); align-items: baseline;
  padding: var(--s3) var(--s4);
  background: var(--white);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--rule);
  border-radius: var(--r-2);
  cursor: pointer;
  transition: border-color var(--m-drawer) ease, background-color var(--m-drawer) ease;
}
.blast-scoped .bs-tab:hover { border-color: var(--teal-deep); }
.blast-scoped .bs-tab-name { font-size: var(--t-body); font-weight: 600; color: var(--ink); }
.blast-scoped .bs-tab-verb.mono { font-size: 14px; color: var(--ink-2); justify-self: end; }
.blast-scoped .bs-tab-reach { grid-column: 1 / -1; font-size: var(--t-label); font-weight: 400; color: var(--ink-2); }

/* ---- the figure ---- */

.blast-scoped .bs-figure {
  grid-area: figure;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
  padding: var(--s4);
}
.blast-scoped .bs-scroll { overflow-x: auto; }
.blast-scoped .bs-svg { width: 100%; height: auto; display: block; }

.blast-scoped .bs-frame { visibility: hidden; opacity: 0; transition: opacity var(--m-drawer) ease; }

.blast-scoped .bs-divider { stroke: var(--rule); stroke-width: 1; stroke-dasharray: 3 7; opacity: 0.7; }
/* The radius itself, drawn. Every chip on it sits the same distance from the identity, which is
   what the word in the heading means. */
.blast-scoped .bs-orbit { fill: none; stroke: var(--rule); stroke-width: 1; stroke-dasharray: 2 8; opacity: 0.5; }
.blast-scoped .bs-svg text.bs-aside {
  font-size: 13px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase;
  fill: var(--ink-2); text-anchor: middle;
}
.blast-scoped .bs-svg text.bs-aside-2 { font-size: 13px; fill: var(--ink-2); text-anchor: middle; }

.blast-scoped .bs-spoke { stroke: var(--rule); stroke-width: 2; }
.blast-scoped .bs-spoke[data-state="no"] { stroke: var(--no); stroke-dasharray: 4 5; }
.blast-scoped .bs-spoke[data-state="out"] { opacity: 0.35; }

.blast-scoped .bs-chip { fill: var(--white); stroke: var(--rule); stroke-width: 1.5; }
.blast-scoped .bs-node[data-treat="instance"] .bs-chip,
.blast-scoped .bs-node[data-treat="artefact"] .bs-chip { stroke-dasharray: 5 4; }
.blast-scoped .bs-node[data-treat="customer"] .bs-chip { stroke: var(--ink-2); }
.blast-scoped .bs-svg text.bs-name { font-size: 14px; font-weight: 600; fill: var(--ink); }
.blast-scoped .bs-svg text.bs-sub { font-size: 13px; fill: var(--ink-2); }

/* The state wins over the treatment stroke, because a reader asking what a withdrawal reaches is
   reading the state. The mark is the second channel and the <title> is the third. */
.blast-scoped .bs-node[data-state="ok"] .bs-chip { stroke: var(--ok); stroke-width: 2; }
.blast-scoped .bs-node[data-state="ok"] .bs-mark { color: var(--ok); }
.blast-scoped .bs-node[data-state="no"] .bs-chip { stroke: var(--no); stroke-width: 2; }
.blast-scoped .bs-node[data-state="no"] .bs-mark { color: var(--no); }
.blast-scoped .bs-node[data-state="no"] text.bs-name { text-decoration: line-through; }
.blast-scoped .bs-node[data-state="out"] .bs-chip { stroke: var(--rule); stroke-width: 1.5; }
.blast-scoped .bs-node[data-state="out"] .bs-mark { color: var(--ink-2); }
.blast-scoped .bs-node[data-state="out"] text.bs-name,
.blast-scoped .bs-node[data-state="out"] text.bs-sub { opacity: 0.68; }
.blast-scoped .bs-mark { color: var(--ink-2); }

/* The hub is the identity every other chip hangs off, so it reads heavier than any of them. This
   rule sits after the three state rules because it raises a width all three of them set. */
.blast-scoped .bs-node[data-hub] .bs-chip { stroke-width: 3; }
/* The node that loses its authority is the one the eye should land on first. The glow is a shadow,
   where no text lands, so a mix is safe here. */
.blast-scoped .bs-node[data-state="no"] .bs-chip { filter: drop-shadow(0 0 7px color-mix(in srgb, var(--no) 62%, transparent)); }


.blast-scoped .bs-legend {
  list-style: none; margin: var(--s4) 0 0; padding: var(--s4) 0 0;
  border-top: 1px solid var(--rule);
  display: flex; flex-wrap: wrap; gap: var(--s3) var(--s4);
}
.blast-scoped .bs-legend li { display: flex; align-items: baseline; gap: var(--s2); font-size: var(--t-small); }
.blast-scoped .bs-legend .word { font-weight: 600; color: var(--ink); }
.blast-scoped .bs-legend .line { color: var(--ink-2); }
.blast-scoped .bs-legend li[data-state="ok"] .mark { color: var(--ok); }
.blast-scoped .bs-legend li[data-state="no"] .mark { color: var(--no); }
.blast-scoped .bs-legend li[data-state="out"] .mark { color: var(--ink-2); }
.blast-scoped .bs-caption { margin: var(--s3) 0 0; font-size: var(--t-label); font-weight: 400; color: var(--ink-2); }

/* ---- the consequence ---- */

/* EVERY SCOPE LEAVES THE INSTRUMENT THE SAME HEIGHT. Shown and hidden with display, the five
   panels are five different lengths and the page moved under the reader on every press, up to 157px
   of jump between two scopes. Stacked in one grid cell they all stay in layout, so the container is
   as tall as the longest and nothing below it moves. visibility rather than opacity, because a
   hidden panel has to leave the accessibility tree as well as the screen. */
.blast-scoped .bs-panels { grid-area: panel; display: grid; }
.blast-scoped .bs-panel {
  grid-area: 1 / 1; visibility: hidden; opacity: 0;
  transition: opacity var(--m-drawer) ease;
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
  padding: var(--s5);
}
.blast-scoped .bs-panel > * + * { margin-top: var(--s4); }
.blast-scoped .bs-panel-scope { display: grid; gap: 2px; margin: 0; }
.blast-scoped .bs-panel-verb.mono { font-size: 14px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-2); }
.blast-scoped .bs-panel-reach { font-size: var(--t-label); font-weight: 400; color: var(--ink-2); }
/* The question is the one red thing in the panel, as the reference sheet has it. At 21px and 600 it
   is large text, so the state colour clears its floor with room to spare. */
.blast-scoped .bs-panel .t-h3 { color: var(--no); }
.blast-scoped .bs-business { margin: 0; font-size: var(--t-body); line-height: var(--t-body-line); color: var(--ink); }
.blast-scoped .bs-protocol { margin: 0; color: var(--ink-2); }
.blast-scoped .bs-note {
  margin: 0; padding-top: var(--s3); border-top: 1px solid var(--rule); color: var(--ink-2);
}
.blast-scoped .bs-facts { display: grid; gap: var(--s2); margin: 0; }
.blast-scoped .bs-facts > div { display: grid; grid-template-columns: minmax(0, 74px) minmax(0, 1fr); gap: var(--s3); }
.blast-scoped .bs-facts dt { font-size: var(--t-label); font-weight: 600; color: var(--ink-2); }
.blast-scoped .bs-facts dd { margin: 0; font-size: var(--t-label); font-weight: 400; color: var(--ink); }
.blast-scoped .bs-ev { margin: 0; }

/* The write control. It renders disabled on every surface of this site, because there is no
   operator credential in this environment and a control that looks pressable would say there is. */
.blast-scoped .bs-act { width: 100%; justify-content: center; }
.blast-scoped .bs-act:disabled { border-color: var(--no); }
.blast-scoped .bs-operator { margin: 0; font-size: var(--t-label); font-weight: 400; color: var(--ink-2); }

/* ---- the stays and gone readout ---- */

.blast-scoped .bs-lists { display: grid; margin-top: var(--s4); padding-top: var(--s4); border-top: 1px solid var(--rule); }
.blast-scoped .bs-list { grid-area: 1 / 1; visibility: hidden; opacity: 0; transition: opacity var(--m-drawer) ease; }
.blast-scoped .bs-list .blast-list { gap: var(--s5) var(--s7); }
.blast-scoped .bs-list .head {
  color: var(--ink-2); letter-spacing: 0.12em; text-transform: uppercase;
  padding-bottom: var(--s2); border-bottom: 1px solid var(--rule);
}
.blast-scoped .bs-list li { align-items: baseline; font-size: var(--t-label); font-weight: 400; }
.blast-scoped .bs-list li .word { min-width: 11ch; font-weight: 600; white-space: nowrap; }
.blast-scoped .bs-list li[data-outcome="out"] .word { color: var(--ink-2); }
.blast-scoped .bs-list li[data-outcome="out"] .name { color: var(--ink-2); }

/* ---- which scope is in view ----

   Six positional pairs. Written out because CSS has no way to say "the nth of these shows the nth
   of those", and named by position rather than by scope id so this file stays the component's. */

.blast-scoped > .bs-input:nth-of-type(1):checked ~ .bs-grid .bs-frame:nth-of-type(1),
.blast-scoped > .bs-input:nth-of-type(2):checked ~ .bs-grid .bs-frame:nth-of-type(2),
.blast-scoped > .bs-input:nth-of-type(3):checked ~ .bs-grid .bs-frame:nth-of-type(3),
.blast-scoped > .bs-input:nth-of-type(4):checked ~ .bs-grid .bs-frame:nth-of-type(4),
.blast-scoped > .bs-input:nth-of-type(5):checked ~ .bs-grid .bs-frame:nth-of-type(5),
.blast-scoped > .bs-input:nth-of-type(6):checked ~ .bs-grid .bs-frame:nth-of-type(6) { visibility: visible; opacity: 1; }

.blast-scoped > .bs-input:nth-of-type(1):checked ~ .bs-grid .bs-panel:nth-of-type(1),
.blast-scoped > .bs-input:nth-of-type(2):checked ~ .bs-grid .bs-panel:nth-of-type(2),
.blast-scoped > .bs-input:nth-of-type(3):checked ~ .bs-grid .bs-panel:nth-of-type(3),
.blast-scoped > .bs-input:nth-of-type(4):checked ~ .bs-grid .bs-panel:nth-of-type(4),
.blast-scoped > .bs-input:nth-of-type(5):checked ~ .bs-grid .bs-panel:nth-of-type(5),
.blast-scoped > .bs-input:nth-of-type(6):checked ~ .bs-grid .bs-panel:nth-of-type(6) { visibility: visible; opacity: 1; }

.blast-scoped > .bs-input:nth-of-type(1):checked ~ .bs-grid .bs-list:nth-of-type(1),
.blast-scoped > .bs-input:nth-of-type(2):checked ~ .bs-grid .bs-list:nth-of-type(2),
.blast-scoped > .bs-input:nth-of-type(3):checked ~ .bs-grid .bs-list:nth-of-type(3),
.blast-scoped > .bs-input:nth-of-type(4):checked ~ .bs-grid .bs-list:nth-of-type(4),
.blast-scoped > .bs-input:nth-of-type(5):checked ~ .bs-grid .bs-list:nth-of-type(5),
.blast-scoped > .bs-input:nth-of-type(6):checked ~ .bs-grid .bs-list:nth-of-type(6) { visibility: visible; opacity: 1; }

.blast-scoped > .bs-input:nth-of-type(1):checked ~ .bs-grid .bs-tab:nth-of-type(1),
.blast-scoped > .bs-input:nth-of-type(2):checked ~ .bs-grid .bs-tab:nth-of-type(2),
.blast-scoped > .bs-input:nth-of-type(3):checked ~ .bs-grid .bs-tab:nth-of-type(3),
.blast-scoped > .bs-input:nth-of-type(4):checked ~ .bs-grid .bs-tab:nth-of-type(4),
.blast-scoped > .bs-input:nth-of-type(5):checked ~ .bs-grid .bs-tab:nth-of-type(5),
.blast-scoped > .bs-input:nth-of-type(6):checked ~ .bs-grid .bs-tab:nth-of-type(6) {
  background: var(--wash-teal);
  border-color: var(--teal-deep);
  border-left-color: var(--teal-deep);
}
.blast-scoped > .bs-input:nth-of-type(1):checked ~ .bs-grid .bs-tab:nth-of-type(1) .bs-tab-verb,
.blast-scoped > .bs-input:nth-of-type(2):checked ~ .bs-grid .bs-tab:nth-of-type(2) .bs-tab-verb,
.blast-scoped > .bs-input:nth-of-type(3):checked ~ .bs-grid .bs-tab:nth-of-type(3) .bs-tab-verb,
.blast-scoped > .bs-input:nth-of-type(4):checked ~ .bs-grid .bs-tab:nth-of-type(4) .bs-tab-verb,
.blast-scoped > .bs-input:nth-of-type(5):checked ~ .bs-grid .bs-tab:nth-of-type(5) .bs-tab-verb,
.blast-scoped > .bs-input:nth-of-type(6):checked ~ .bs-grid .bs-tab:nth-of-type(6) .bs-tab-verb,
.blast-scoped > .bs-input:nth-of-type(1):checked ~ .bs-grid .bs-tab:nth-of-type(1) .bs-tab-reach,
.blast-scoped > .bs-input:nth-of-type(2):checked ~ .bs-grid .bs-tab:nth-of-type(2) .bs-tab-reach,
.blast-scoped > .bs-input:nth-of-type(3):checked ~ .bs-grid .bs-tab:nth-of-type(3) .bs-tab-reach,
.blast-scoped > .bs-input:nth-of-type(4):checked ~ .bs-grid .bs-tab:nth-of-type(4) .bs-tab-reach,
.blast-scoped > .bs-input:nth-of-type(5):checked ~ .bs-grid .bs-tab:nth-of-type(5) .bs-tab-reach,
.blast-scoped > .bs-input:nth-of-type(6):checked ~ .bs-grid .bs-tab:nth-of-type(6) .bs-tab-reach { color: var(--ink); }

/* The radio is clipped out of sight, so its focus ring has to land on the label that stands for it.
   Without these six the group is operable from the keyboard with nothing on screen to say where the
   keyboard is. */
.blast-scoped > .bs-input:nth-of-type(1):focus-visible ~ .bs-grid .bs-tab:nth-of-type(1),
.blast-scoped > .bs-input:nth-of-type(2):focus-visible ~ .bs-grid .bs-tab:nth-of-type(2),
.blast-scoped > .bs-input:nth-of-type(3):focus-visible ~ .bs-grid .bs-tab:nth-of-type(3),
.blast-scoped > .bs-input:nth-of-type(4):focus-visible ~ .bs-grid .bs-tab:nth-of-type(4),
.blast-scoped > .bs-input:nth-of-type(5):focus-visible ~ .bs-grid .bs-tab:nth-of-type(5),
.blast-scoped > .bs-input:nth-of-type(6):focus-visible ~ .bs-grid .bs-tab:nth-of-type(6) {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
  box-shadow: 0 0 0 2px var(--focus-halo), 0 0 0 4px var(--focus-ring);
}

/* ---- motion ----

   The figure, the panel and the list cross fade when the scope changes, so a press is answered by
   something moving rather than by the picture being different the next time the eye lands on it.

   IT IS A TRANSITION AND NOT AN ANIMATION, and that is a correction rather than a preference. The
   first version faded each node in with a keyframe animation, which never once played on a press:
   an animation restarts when its own element stops being display: none, and the nodes are not what
   is switched, their ancestor group is. Twelve copies ran at load, eleven of them inside hidden
   groups, and getAnimations() on the newly shown node after a scope change returned nothing at all.
   Moving the same animation up onto the group did not fix it either. A transition on a property
   that actually changes does fire, so the frames stack and swap opacity instead of display. */

/* ---- narrow ---- */

/* THE SVG HOLDS 860 USER UNITS WIDE AT THE LEAST, and the number is the 14px floor. Its viewBox is
   736 wide and its smallest label is set at 13, so it must draw at 860 or more for that label to
   reach a reader at 14 or more. Measured on 29 September 2026 with the scope rail and the panel both
   beside the figure: the svg drew 649 wide at 1440 and every label sat between 10.6 and 11.5px. So
   the five scopes go in one row across the top, which gives the figure the width, and the panel
   stays beside it, so the words a press changes sit next to the picture it changes. Below 1180 the
   three stack, and below 860 the figure scrolls inside its own region rather than shrinking. At the
   top it stops at 940, where a label reads at about 16px. */
.blast-scoped .bs-svg { min-width: 860px; max-width: 940px; margin-inline: auto; }
@media (max-width: 1180px) {
  .blast-scoped .bs-grid {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "scopes" "figure" "panel";
  }
  .blast-scoped .bs-scopes { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .blast-scoped .bs-rail-head { grid-column: 1 / -1; }
}
@media (max-width: 860px) {
  .blast-scoped .bs-grid { grid-template-columns: minmax(0, 1fr); grid-template-areas: "scopes" "figure" "panel"; }
  .blast-scoped .bs-scopes { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* THE FIGURE STOPS SHRINKING AND STARTS SCROLLING. Below this width the ring drew at about 280px
   across, which puts a 13px label on screen at 5px and makes the figure a decoration. A diagram is
   one of the three things allowed its own sideways scroll, so it keeps a readable floor and the
   page itself still does not scroll sideways at 390. The stays and gone list under it carries the
   same reading in words for anybody who would rather read than scroll. */
@media (max-width: 560px) {
  .blast-scoped .bs-scopes { grid-template-columns: minmax(0, 1fr); }
  .blast-scoped .bs-figure { padding: var(--s3); }
  .blast-scoped .bs-panel { padding: var(--s4); }
  .blast-scoped .bs-list .blast-list { grid-template-columns: minmax(0, 1fr); }
}

/* All motion stops, and the end state is restored rather than left wherever one frame landed. The
   global reduce block shortens an animation to a fraction of a millisecond, which for a fade from
   0.35 leaves a node that never finished arriving. */
/* All motion stops.

   WHAT THIS BLOCK ACTUALLY DOES, measured rather than assumed. The global reduce block in ui.css
   already shortens every transition to a fraction of a millisecond, and with these four rules
   deleted the instrument still had nothing running after a scope change. So the global rule is what
   stops the motion here, and this block removes the declaration as well, which is what the rest of
   the stylesheet does and what keeps the intent readable at the component rather than one file
   away. Counted on 12 September 2026 with document.getAnimations() straight after a press: sixteen
   running with motion allowed, none with it reduced. */
@media (prefers-reduced-motion: reduce) {
  .blast-scoped .bs-frame,
  .blast-scoped .bs-panel,
  .blast-scoped .bs-list,
  .blast-scoped .bs-tab { transition: none; }
}

/* ---- src/parts/ch-mkt.css ---- */
/*
 * /use-cases/when-something-changes: the COMPONENTS on that page.
 *
 * The page's own bands are packages/ui/src/parts/ch-page.css. The instrument is
 * packages/ui/src/parts/ch.css and nothing here touches it.
 *
 * THE SOURCE OF EVERY MEASURE BELOW is /tmp/claude-501/rw-live/app/use-cases/06/page.tsx, read in
 * the browser on 16 September 2026 rather than off a screenshot. Its utility classes convert at four
 * pixels to the unit: p-4 is 16px, p-6 is 24px, p-7 is 28px, gap-3 is 12px, gap-5 is 20px,
 * rounded-lg is 8px, rounded-xl is 12px, rounded-2xl is 16px. Every number is named beside the rule
 * that sets it.
 *
 * WHERE THIS DEPARTS FROM THE REFERENCE, AND WHY.
 *
 *   TYPE. The reference sets 11px, 12px and 13px across this page. The floor here is 14px and
 *   packages/ui/tests/stylesheet.test.ts holds it over the whole bundle, so those three collapse
 *   into one. Everything that follows is a spacing decision rather than a size decision: the cards
 *   in the hero are taller than the reference's, the timeline's first column is wider because its
 *   entries are words rather than a clock, and the step columns take more of the row.
 *
 *   COLOUR. The reference writes its greys as alpha over a ground, which packages/ui/tools/
 *   contrast.mjs cannot name, so each one is resolved to the nearest opaque token. A card edge takes
 *   var(--hairline), the soft form, because a reader loses nothing by losing it; anything a person
 *   operates takes var(--rule). No flat background under text is a colour-mix, because the contrast
 *   gate reads token pairs by name and can see nothing through a mix.
 *
 *   THE ACCENT. The reference paints its icons and its numbers in its brand cyan. Here that is
 *   var(--teal-dark) for a stroke a reader reads and var(--teal-mid) for a shape. var(--teal) fills
 *   a Raidiam product marker and nothing else, and a change is not a product.
 *
 * WHAT THIS FILE REFUSES TO DRAW. Green that is not a lifecycle state. Every green here comes
 * through the base sheet's `.state[data-state]`, so green means the same thing on this page that it
 * means on every other one, and it is a state rather than an evidence mark.
 *
 * WHAT STAYS FOR THE GALLERY AND NOT FOR THE PAGE. The `.chr` ring and the `.chn` legend at the foot
 * of this file are drawn by two partials this route no longer names. The gallery still renders them
 * and a partial with no stylesheet renders as unstyled text there. Retiring a partial and its rules
 * together is the lead's call.
 */

/* ==========================================================================
   1. THE HERO FIGURE: five changes standing around one agent
   ==========================================================================
   The reference lays this out as a 760 by 440 relative box with five absolutely placed cards, a
   masked globe behind them and an 80px agent badge at the centre. The box here is 470 tall because
   each card carries the same three facts at 14px rather than at 12px.

   THE POSITIONS ARE THE REFERENCE'S OWN, to the percentage: one card centred at the top, two at 22
   per cent and two at 62 per cent of the box height. */
.chp-ring { position: relative; min-width: 0; height: 470px; }

/* The standing note above the top right corner. The reference sets 12px, weight 600, tracking
   0.22em, upper case, right aligned, at top-2 right-0. Held at the 14px floor.

   THE WIDTH CAP IS A MEASUREMENT. The note stands between the card above the centre, whose right
   edge is 1089 at 1440, and the card on the upper right, whose top edge is 261. Uncapped at 14px the
   note ran 307 wide and overlapped the first; capped at 170 its longest line wrapped, the block grew
   to 134 tall and it overlapped the second. 205 is the widest line measured in Chrome, "EVERY
   CONSUMER" at 200, so no line wraps, the block is four lines and 90 tall, and it clears both. */
.chp-ring-note {
  position: absolute; right: 0; top: 8px; margin: 0;
  max-width: 205px;
  text-align: right;
  font-size: var(--t-label); line-height: 1.6; font-weight: 600;
  letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--faint);
}

/* The globe. The reference draws a 360px disc behind the centre, masked to nothing between 55 and
   74 per cent of the radius so it has no edge, at 80 per cent opacity. The raster is the one
   packages/ui/partials/lv-hero.ejs already places on the live demo hero. */
.chp-ring-globe {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: 336px; height: 336px; border-radius: 50%;
  background-size: cover; background-position: center;
  opacity: 0.8; pointer-events: none;
  -webkit-mask-image: radial-gradient(circle at 50% 50%, var(--ink) 55%, transparent 74%);
  mask-image: radial-gradient(circle at 50% 50%, var(--ink) 55%, transparent 74%);
}

/* The centre. The reference puts an 80px badge here holding a line drawn agent, and this now draws
   the same subject the same way: packages/ui/partials/ped.ejs stands the agent glyph in a pool of
   brand light. It is capped at 176px so the headline in the column beside it stays the largest thing
   in the band: measured at 1440, the headline block is 500 by 159. */
.chp-ring-core {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  display: grid; place-items: center;
  width: 176px; height: 176px;
}
/* THE ART RULE IS GONE WITH THE ASSET. Its blend, its mask and its drop shadow all existed to hide
   the square the JPEG arrived in. packages/ui/partials/ped.ejs draws light rather than hiding it. */

/* The card. The reference sets w-230 p-4 rounded-xl, a brand border at 25 per cent, a panel ground
   at 75 per cent and one soft outer glow. 212 wide here, because the copy column is held at 500 so
   the two actions sit in one row and the figure takes what is left of 1216. */
.chp-card {
  position: absolute; z-index: 1;
  width: 212px;
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--s3);
  align-items: start;
  padding: var(--s4);
  border-radius: 12px;
  background: var(--white);
  border: 1px solid color-mix(in srgb, var(--teal-dark) 25%, transparent);
  box-shadow: 0 0 26px color-mix(in srgb, var(--teal-mid) 30%, transparent);
}
.chp-card[data-at="top"] { left: 50%; top: 0; transform: translateX(-50%); }
.chp-card[data-at="left-up"] { left: 0; top: 22%; }
.chp-card[data-at="right-up"] { right: 0; top: 22%; }
.chp-card[data-at="left-down"] { left: 0; top: 62%; }
.chp-card[data-at="right-down"] { right: 0; top: 62%; }

.chp-card .sc-glyph { width: 20px; height: 20px; color: var(--teal-dark); }
.chp-card-b { min-width: 0; }
.chp-card-t { margin: 0; font-size: var(--t-label); line-height: 1.25; font-weight: 700; color: var(--ink); }
/* Three lines, clamped. A scope whose declared reach runs longer than the reference allowed for is
   cut rather than allowed to grow its card into the card below it. */
.chp-card-s {
  margin: 2px 0 0; font-size: var(--t-label); line-height: 1.4; color: var(--ink-2);
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden;
}
.chp-card-v { margin-top: var(--s2); }

/* ==========================================================================
   2. HOW IT WORKS: four steps, and the card that states the window
   ==========================================================================
   The reference draws one rounded panel holding four equal steps with an arrow between each pair,
   and a 320px card beside it. Each step is a 28px numbered ring, then an icon, a 15px title and a
   13px line.

   THE ICON IS NOT DRAWN. packages/ui/partials/ch-steps.ejs has no icon slot and this work does not
   own that file. Reported rather than added. */
.chst { display: grid; }
.chst-kicker {
  margin: 0 0 var(--s4); font-size: var(--t-label); font-weight: 600;
  letter-spacing: 0.24em; text-transform: uppercase; color: var(--teal-dark);
}
/* 340 rather than the reference's 320: the aside's own sentence is longer than the reference's and
   the row is 1216 wide rather than 1336. */
.chst-row { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: var(--s5); align-items: stretch; }
.chst-steps {
  list-style: none; margin: 0; padding: var(--s5);
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s5);
  border: 1px solid var(--hairline); border-radius: 16px; background: var(--white);
}
.chst-step { position: relative; display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--s3); align-items: start; }
/* The arrow the reference sets between one step and the next, drawn in the gap rather than as a
   fifth column, because the markup has four steps and no separator element. It is decoration: the
   numbers already say the order. */
.chst-step + .chst-step::before {
  content: ""; position: absolute; left: -18px; top: 9px;
  width: 12px; height: 10px;
  background: var(--teal-mid);
  -webkit-mask: var(--arrow-right) center / contain no-repeat;
  mask: var(--arrow-right) center / contain no-repeat;
}
.chst-n {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--teal-dark) 50%, transparent);
  color: var(--teal-dark);
  font-size: var(--t-label); font-weight: 700;
}
.chst-b { display: grid; gap: var(--s1); min-width: 0; }
.chst-t { font-size: var(--t-small); line-height: 1.4; font-weight: 700; color: var(--ink); }
.chst-l { font-size: var(--t-label); line-height: 1.5; color: var(--ink-2); }
.chst-aside {
  display: grid; align-content: center;
  padding: var(--s5);
  border: 1px solid var(--hairline); border-radius: 16px; background: var(--white);
}
.chst-aside-t { margin: 0; font-size: 16px; line-height: 1.5; font-weight: 700; color: var(--ink); }
.chst-aside-l { margin: var(--s1) 0 0; font-size: var(--t-label); line-height: 1.55; color: var(--ink-2); }

/* ==========================================================================
   3. THE TIMELINE: walk one change through, step by step
   ==========================================================================
   The reference draws this as the left of two equal panels, p-7 rounded-2xl, with a heading, a
   selector at the top right, then a row per event: a fixed first column, a dot on a vertical
   connector, the words, and the result at the right.

   THE PANEL CHROME IS ON `.chs` RATHER THAN ON THE COLUMN AROUND IT, so the gallery renders the
   same object the page does rather than an unpadded list. */
.chs {
  display: grid; gap: var(--s5); align-content: start;
  padding: 28px;
  border: 1px solid var(--hairline); border-radius: 16px; background: var(--white);
}
.chs-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--s4); align-items: start; }
.chs-title { margin: 0; font-size: 20px; line-height: 1.5; font-weight: 700; color: var(--ink); letter-spacing: -0.01em; }
.chs-lede { margin: var(--s1) 0 0; max-width: 21.25rem; font-size: var(--t-label); line-height: 1.5; color: var(--ink-2); }
/* The reference draws this as a bordered block with a caret. It is a real select here, because a
   reader chooses one of three and a select says so to a keyboard and to a screen reader. */
.chs-select {
  font: inherit; font-size: var(--t-label); font-weight: 600;
  padding: var(--s2) var(--s3); border-radius: 8px;
  border: 1px solid var(--rule); background: var(--paper-alt); color: var(--brand-strong);
}
.chs-steps { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }
/* 96px for the first column rather than the reference's 64. Its entries are a clock; these are
   words, and the longest of them is "The next read". */
.chs-step {
  position: relative;
  display: grid; grid-template-columns: 96px 12px minmax(0, 1fr) auto;
  gap: var(--s4); align-items: start;
  padding-bottom: var(--s5);
  opacity: 0; transform: translateY(6px);
  transition: opacity 320ms ease, transform 320ms ease;
}
.chs-step.is-in { opacity: 1; transform: none; }
/* The connector under the dot, from this row's dot to the next one. Its left edge is the first
   column, the gap, and half the dot: 96 plus 16 plus 6. */
.chs-step:not(:last-child)::after {
  content: ""; position: absolute; left: 117px; top: 22px; bottom: 2px;
  width: 1px; background: var(--hairline);
}
.chs-at { font-size: var(--t-label); line-height: 1.4; font-weight: 500; color: var(--slate); font-variant-numeric: tabular-nums; padding-top: 2px; }
/* The dot takes the step's outcome, which is the one signal that makes a timeline readable at a
   glance: green ran, amber changed, red stopped. */
.chs-dot { width: 12px; height: 12px; border-radius: 50%; margin-top: 6px; background: var(--ink-2); }
.chs-step[data-state="ok"] .chs-dot { background: var(--ok); }
.chs-step[data-state="att"] .chs-dot { background: var(--att); }
.chs-step[data-state="no"] .chs-dot { background: var(--no); }
.chs-body { display: grid; gap: 2px; min-width: 0; }
.chs-step-t { font-size: var(--t-label); line-height: 1.4; font-weight: 700; color: var(--ink); }
.chs-step-l { font-size: var(--t-label); line-height: 1.45; color: var(--ink-2); }
.chs-result { display: grid; gap: var(--s2); justify-items: end; text-align: right; font-size: var(--t-label); font-weight: 500; color: var(--slate); white-space: nowrap; }
.chs-ev { white-space: normal; }
.chs-play { margin: 0; }
.chs-play-btn { display: inline-flex; align-items: center; gap: var(--s2); }
.chs-play-i svg { width: 14px; height: 14px; display: block; }

/* ==========================================================================
   4. THE CONNECTED COMPONENTS
   ==========================================================================
   The reference sets a 16px heading at mt-8, then a two column grid at gap-3 mt-4, each card p-4
   rounded-xl on the alternate ground with the name, an external link mark and the host under it. */
.chp-comps { margin-top: var(--s6); }
.chp-comps-h { margin: 0; font-size: 16px; line-height: 1.5; font-weight: 700; color: var(--ink); }
.chp-comps-grid { margin-top: var(--s4); display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s3); }
.chp-comp {
  display: grid; gap: var(--s1); align-content: start;
  padding: var(--s4); border-radius: 12px;
  border: 1px solid var(--hairline); background: var(--paper-alt);
  color: inherit; text-decoration: none;
}
.chp-comp:hover { border-color: color-mix(in srgb, var(--teal-dark) 40%, transparent); }
.chp-comp-n { display: inline-flex; align-items: center; gap: 6px; font-size: var(--t-label); line-height: 1.4; font-weight: 700; color: var(--ink); }
.chp-comp-out { display: inline-flex; color: var(--slate); }
.chp-comp-out svg { width: 14px; height: 14px; display: block; }
/* The reference writes an italic sentence here. This says who owns the surface in the five fixed
   words the footer legend explains, so the slot carries a declared label rather than a written one. */
.chp-comp-treat { display: block; }
.chp-comp-treat .treat.chip { font-size: var(--t-label); }
/* THE HOST WRAPS RATHER THAN TRUNCATING, which is where this departs from the reference. It sets
   `truncate` and at 12px in a 294 card that loses nothing. At 14px in a 263 card it cut every one of
   the four to about two thirds, and a host a reader cannot read is a card that has stopped saying
   which surface it opens. */
.chp-comp-h {
  font-family: var(--mono); font-size: var(--t-label); line-height: 1.4; color: var(--ink-2);
  overflow-wrap: anywhere;
}

/* ==========================================================================
   5. NARROW
   ==========================================================================
   The reference is not designed narrow. Each of these is the width at which one of its arrangements
   stops working, measured rather than guessed. */
@media (prefers-reduced-motion: reduce) {
  .chs-step { transition: none; }
}
@media (max-width: 1180px) {
  /* Four steps across a full width row leave 150px a column, which breaks a title mid word. */
  .chst-row { grid-template-columns: minmax(0, 1fr); }
  .chst-steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 1080px) {
  /* The five cards stop standing around a centre: two columns of 212 plus a 336 globe needs 760.
     The figure becomes the picture with the five cards listed under it, in the same order. */
  .chp-ring { height: auto; display: grid; gap: var(--s4); justify-items: center; }
  .chp-ring-note { position: static; text-align: left; justify-self: start; }
  .chp-ring-globe { display: none; }
  .chp-ring-core { position: static; transform: none; }
  .chp-card[data-at] { position: static; transform: none; width: 100%; max-width: 32rem; }
}
@media (max-width: 760px) {
  .chst-steps { grid-template-columns: minmax(0, 1fr); }
  .chst-step + .chst-step::before { display: none; }
  .chs { padding: var(--s5); }
  .chs-head { grid-template-columns: minmax(0, 1fr); }
  .chs-step { grid-template-columns: minmax(0, 1fr); gap: var(--s2); padding-bottom: var(--s4); }
  .chs-step:not(:last-child)::after { display: none; }
  .chs-dot { display: none; }
  .chs-result { justify-items: start; text-align: left; }
  .chp-comps-grid { grid-template-columns: minmax(0, 1fr); }
  .chp-ring-core { width: 140px; height: 140px; }
}

/* ==========================================================================
   6. TWO FIGURES THIS ROUTE NO LONGER DRAWS, KEPT FOR THE GALLERY
   ==========================================================================
   packages/ui/partials/ch-ring.ejs and packages/ui/partials/ch-next.ejs are rendered by
   packages/ui/gallery and by nothing else. A partial with no stylesheet renders as unstyled text
   there, so the rules stay. Retiring a partial and its rules together is the lead's call. */
.chr { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--s4); }
.chr-stage { position: relative; aspect-ratio: 1 / 0.86; min-width: 0; }
.chr-ring {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: 34%; aspect-ratio: 1 / 1; border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--teal-mid) 45%, transparent);
  box-shadow: 0 0 60px color-mix(in srgb, var(--teal-mid) 22%, transparent) inset;
}
.chr-ring-2 { width: 52%; border-style: dashed; opacity: 0.45; box-shadow: none; }
.chr-core { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); width: 22%; aspect-ratio: 1 / 1; display: grid; place-items: center; }
.chr-core img {
  width: 100%; height: 100%; object-fit: contain;
  mix-blend-mode: screen;
  -webkit-mask-image: radial-gradient(circle at 50% 50%, var(--ink) 58%, transparent 78%);
  mask-image: radial-gradient(circle at 50% 50%, var(--ink) 58%, transparent 78%);
  filter: drop-shadow(0 0 40px color-mix(in srgb, var(--teal-mid) 55%, transparent));
}
.chr-card {
  position: absolute; width: 13.5rem; max-width: 36%;
  display: grid; gap: 4px;
  padding: var(--s3) var(--s4);
  border: 1px solid var(--rule); border-radius: var(--r-2); background: var(--white);
}
.chr-card[data-at="n"] { left: 50%; top: 0; transform: translateX(-50%); }
.chr-card[data-at="ne"] { right: 0; top: 30%; }
.chr-card[data-at="se"] { right: 0; bottom: 0; }
.chr-card[data-at="sw"] { left: 0; bottom: 0; }
.chr-card[data-at="nw"] { left: 0; top: 30%; }
.chr-card[data-state="ok"] { border-color: color-mix(in srgb, var(--ok) 55%, transparent); }
.chr-card[data-state="att"] { border-color: color-mix(in srgb, var(--att) 55%, transparent); }
.chr-card[data-state="no"] { border-color: color-mix(in srgb, var(--no) 55%, transparent); }
.chr-card-h { margin: 0; font-weight: 600; font-size: var(--t-small); color: var(--ink); }
.chr-card-l {
  margin: 0; font-size: 14px; color: var(--ink-2);
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
}
.chr-card-o { margin: 4px 0 0; }
.chr-rail {
  margin: 0; align-self: center;
  display: grid; gap: 2px;
  font-size: var(--t-label); font-weight: 600;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--ink-2); text-align: right; white-space: nowrap;
}
.chn { padding: var(--s5); border: 1px solid var(--rule); border-radius: var(--r-2); background: var(--white); }
.chn-h {
  margin: 0 0 var(--s4); font-size: var(--t-label); font-weight: 600;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-2);
}
.chn-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s4); }
.chn-item { display: grid; gap: var(--s2); }
.chn-line { font-size: 14px; color: var(--ink-2); }
@media (max-width: 760px) {
  .chr { grid-template-columns: minmax(0, 1fr); }
  .chr-stage { aspect-ratio: auto; display: grid; gap: var(--s3); }
  .chr-ring { display: none; }
  .chr-core { position: static; transform: none; width: 46%; justify-self: center; }
  .chr-card { position: static; width: auto; max-width: none; transform: none; }
  .chr-rail { display: none; }
}

/* ==========================================================================
   7. THE IDENTITY HUES
   ==========================================================================
   WHAT THIS SECTION IS. One place that says which of the four identity hues each set of peers on
   this page carries. Three sets take one: the five change cards standing around the agent, the four
   steps in the how it works strip, and the four surfaces in the connected components grid. The
   payoff row is laid out in packages/ui/src/parts/ch-page.css and takes its hues there.

   WHY THE PAGE NEEDS IT. Ralph's comp for this route, usecases.png, draws the five cards around the
   agent in FIVE COLOURS, and that is the first thing a reader sees: five different things can
   change. Measured at 1440 on 16 September 2026 with getComputedStyle over every element in `main`,
   this route drew ZERO of the four identity hues, so the five cards were one card drawn five times
   and the picture said nothing until it was read. Ralph: "the entire site has gone blue
   monocromatic".

   WHAT AN IDENTITY HUE IS, AND WHAT THE CHIP UNDER IT IS. --d-blue, --d-violet, --d-magenta and
   --d-sand carry no meaning anywhere in this system. They answer WHICH ONE of a set of peers this
   is. The CONTINUE, REDUCE and REFUSE chip at the foot of each card is a STATE: it says what access
   does when that change lands, it carries the word beside the colour, and it is drawn by the base
   sheet's `.state[data-state]` exactly as it was. So a card's hue says which change, and its chip
   says the answer, and neither can be mistaken for the other.

   THE ASSIGNMENT IS POSITIONAL AND IT LIVES HERE. A card takes its hue from its place in the figure
   rather than from its scope id, so data/scopes.yaml cannot pick a colour and a renamed scope
   cannot change one. Four hues over five positions repeat at the fifth, which is the lower right,
   diagonally opposite the top.

   CONTRAST, computed from packages/ui/tokens/tokens.json with the formula in
   packages/ui/tools/contrast.mjs. All four are gated against the three dark grounds at the 4.5 TEXT
   floor rather than the 3 of a graphic. On d-card, the lightest ground and therefore the one that
   decides: d-blue 7.35, d-violet 6.62, d-magenta 10.16 and d-sand 10.41.
   ========================================================================== */

/* The five change cards. */
.chp-ring .chp-card { --hue: var(--d-blue); }
.chp-ring .chp-card[data-at="left-up"] { --hue: var(--d-violet); }
.chp-ring .chp-card[data-at="right-up"] { --hue: var(--d-magenta); }
.chp-ring .chp-card[data-at="left-down"] { --hue: var(--d-sand); }
/* The card lit from above by its own hue. The other three sides keep the brand edge the reference
   draws and the outer glow follows the hue, so a card reads as one object in one colour rather than
   as a cyan card with a coloured line on it. */
.chp-ring .chp-card {
  border-top-color: var(--hue);
  box-shadow: 0 0 26px color-mix(in srgb, var(--hue) 26%, transparent), inset 0 1px 0 color-mix(in srgb, var(--hue) 35%, transparent);
}
.chp-ring .chp-card .sc-glyph { color: var(--hue); }

/* The four steps. They are an order, and the numbers say the order, so the hue here says which step
   a reader is looking at rather than how far through they are. */
.chst .chst-step:nth-child(1) { --hue: var(--d-blue); }
.chst .chst-step:nth-child(2) { --hue: var(--d-violet); }
.chst .chst-step:nth-child(3) { --hue: var(--d-magenta); }
.chst .chst-step:nth-child(4) { --hue: var(--d-sand); }
.chst .chst-n {
  border-color: color-mix(in srgb, var(--hue) 55%, transparent);
  color: var(--hue);
}

/* The four surfaces a reader can open. Each is a different system, which is the one thing the grid
   has to say before a host is read. */
.chp-comps .chp-comp:nth-child(1) { --hue: var(--d-blue); }
.chp-comps .chp-comp:nth-child(2) { --hue: var(--d-violet); }
.chp-comps .chp-comp:nth-child(3) { --hue: var(--d-magenta); }
.chp-comps .chp-comp:nth-child(4) { --hue: var(--d-sand); }
.chp-comps .chp-comp { border-top-color: var(--hue); }
.chp-comps .chp-comp:hover { border-color: color-mix(in srgb, var(--hue) 45%, transparent); border-top-color: var(--hue); }
.chp-comps .chp-comp-out { color: var(--hue); }

/* ---- src/parts/ch-page.css ---- */
/*
 * /use-cases/when-something-changes: the PAGE.
 *
 * The components on it are packages/ui/src/parts/ch-mkt.css. The instrument is
 * packages/ui/src/parts/ch.css and nothing here touches it.
 *
 * THE PAGE LOST TWO BANDS ON 16 SEPTEMBER 2026 AND THIS FILE LOST THEIR RULES. The four step strip
 * and the two panel row went to the technical route, because a procedure and a step by step
 * walkthrough explain a mechanism rather than make a claim, and the page ran to 754 words against a
 * limit of 450. The rules that arranged them are gone from sections 3 and 5 below. The components
 * themselves are untouched in packages/ui/src/parts/ch-mkt.css, which this file does not own.
 *
 * THE SOURCE IS /tmp/claude-501/rw-live/app/use-cases/06/page.tsx, read in the browser on
 * 16 September 2026. Its sections, its measures and its rhythm are taken as written and are named
 * beside each rule. Read there rather than remembered:
 *
 *   container       mx-auto max-w-[1400px] px-8, so 1336 of content
 *   hero            pt-12, grid gap-10, lg:grid-cols-[minmax(0,460px)_1fr], copy pt-6
 *   eyebrow         13px, weight 600, upper case, tracking 0.28em, #7fd8e6
 *   h1              mt-4, 52px, weight 700, line height 1.02, tracking -0.03em
 *   lead            mt-5, max-w-[460px], 17px on 1.6, #aebdd2
 *   actions         mt-8, gap-4
 *   how it works    pt-14, a kicker row at mb-5, then grid gap-5 lg:grid-cols-[1fr_320px]
 *   the two panels  pt-6 pb-6, grid gap-5 lg:grid-cols-2
 *   no rule         the reference draws no horizontal line between any two of its sections
 *
 * THREE VALUES ARE HELD RATHER THAN COPIED, each for a stated reason.
 *
 *   THE MEASURE IS 1216, NOT 1336. The three families on this site are set: 1472 for the home and
 *   the wide routes, 1216 for the use case pages, 1036 for the interior pages. This is a use case
 *   page. Every proportion below is the reference's, scaled into 1216.
 *
 *   THE COPY COLUMN IS 500, NOT THE 419 THE SCALE GIVES. CLAUDE.md records the rule from Ralph's
 *   own comparison at 1440: the two calls to action sit side by side and the pair is one gesture.
 *   Measured in Chrome, the two controls are 244px and 222px with a 16px gap, which is 482. At 419
 *   they stack, which is what the reference itself does at 460 and what he named as wrong.
 *
 *   EVERY SIZE UNDER 14px BECOMES 14px. The reference sets 11, 12 and 13 across this page. The floor
 *   is a readability rule rather than a style choice and packages/ui/tests/stylesheet.test.ts holds
 *   it over the whole bundle.
 *
 * THE LEAD TAKES --ink-lead. The token is the reference's own #aebdd2 on the dark site. Before it
 * existed every lead on this site reached for --ink-2, two steps down, which made a lead read as a
 * caption.
 *
 * WHAT STAYS FOR THE GALLERY AND NOT FOR THE PAGE. The `.chb-` rules at the foot draw
 * packages/ui/partials/ch-orbit.ejs, which no route names. The gallery still renders it and a
 * partial with no stylesheet renders there as unstyled text. Retiring a partial and its rules
 * together is the lead's call.
 */

/* ==========================================================================
   1. THE PAGE MEASURE AND THE BAND RHYTHM
   ==========================================================================
   `.band` in the base sheet gives every band 64px above, 64px below and a full width rule across the
   top. The reference draws no rule between any two of its sections and states one number for the gap
   rather than two, so a band here states its top space and no bottom space. The last band takes its
   bottom space back, because the footer under it has none of its own.

   `.wrap.chp > .band` is three classes against one and cannot reach the seventeen other routes that
   share `.band`. */
.chp { --page-max: 1216px; }
.wrap.chp > .band { border-top: 0; padding-block: var(--s8) 0; }

/* pt-12 on the reference. */
.wrap.chp > .chp-hero { padding-block: var(--s7) 0; }
/* The instrument band, which the reference has no slot for. It takes the pt-14 the reference gives
   its second section, so the page keeps the reference's rhythm with one band fewer in it. */
.wrap.chp > .chp-figure { padding-block: 3.5rem 0; }
/* THE ONE LINE THIS PAGE KEEPS. Reference 06 has no feature row and so draws no line; references 02
   and 03 draw the row this page draws, and both put a border above it with 48px under. The row and
   the line travel together, so the line follows the row rather than the page. */
.wrap.chp > .chp-payoff { margin-top: var(--s8); padding-block: var(--s7) 0; border-top: 1px solid var(--hairline); }
.wrap.chp > .band:last-child { padding-bottom: var(--s8); }

/* ==========================================================================
   2. THE HERO
   ========================================================================== */
.chp-hero {
  display: grid;
  grid-template-columns: 500px minmax(0, 1fr);
  gap: 2.5rem;
  align-items: start;
}
/* pt-6 on the reference's copy column. */
.chp-hero-copy { padding-top: var(--s5); min-width: 0; }
.chp-hero-copy .sc-eyebrow { letter-spacing: 0.28em; color: var(--slate); }
.chp-hero-copy .sc-headline {
  margin-top: var(--s4);
  max-width: none; text-wrap: balance;
  font-size: 52px; line-height: 1.02; letter-spacing: -0.03em;
}
/* max-w-[460px] on the reference, which is its whole copy column. Ours is the same: the column. */
.chp-hero-copy .sc-lead {
  margin-top: 1.25rem; max-width: 31.25rem;
  font-size: 17px; line-height: 1.6;
  color: var(--ink-lead);
}
.chp-hero-copy .sc-actions { margin-top: var(--s6); gap: var(--s4); }

/* ==========================================================================
   3. THE INSTRUMENT BAND
   ==========================================================================
   It carries no heading: the h1 states the proposition and the instrument states it as a picture, so
   a band head between them would state it a third time in words. The one line it does carry is an
   instruction, and it is the only thing on the band that is not a restatement: it tells a reader the
   five tabs are pressable, and nothing else on the page says so. */
.chp-figure { min-width: 0; }
.chp-figure-say { margin-bottom: var(--s5); color: var(--ink-lead); }

/* ==========================================================================
   4. THE PAYOFF ROW
   ==========================================================================
   Reference 06 draws no feature row. References 02 and 03 draw this one: a centred row of four, a
   56px ringed mark, an 18px bold title and a 14px line held to 260px, with a vertical hairline
   between the columns.

   THE MARK IS THE PUBLISHED IMAGE AND NOT A GLYPH. tests/published-assets.test.ts declares the four
   PNGs and the ring is drawn around the image rather than replacing it.

   THE TITLE TAKES THE BODY FACE. One family on everything is the rule this rebuild is held to: a
   second face at 18px beside a 52px display in the first face is what made the old page read soft. */
.chp-payoff { display: grid; }
.chp-payoff-line { margin: 0; max-width: 24ch; }
.chf { margin-top: 0; }
.chf-kicker { margin-bottom: var(--s5); }
.chf-row { list-style: none; margin: var(--s6) 0 0; padding: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); }
.chf-card {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  min-width: 0;
  padding: 0 var(--s5);
}
/* The line between columns, and the first column carries none: a rule at the left edge of a row
   reads as a border around the row rather than as a separator inside it. It takes the hairline
   token because it is decorative: it marks the edge of nothing a person operates. */
.chf-card + .chf-card { border-left: 1px solid var(--hairline); }
.chf-icon {
  display: grid; place-items: center; flex: 0 0 auto;
  width: 56px; height: 56px; border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--teal-dark) 40%, transparent);
}
.chf-icon img { width: 28px; height: 28px; }
.chf-title { margin-top: var(--s4); font-size: 18px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.chf-line { margin-top: var(--s2); color: var(--ink-2); font-size: 14px; line-height: 1.55; max-width: 16.25rem; }

/* ==========================================================================
   5. THE WORKED EXAMPLE'S RIGHT COLUMN, on <route>/evidence
   ==========================================================================
   packages/ui/partials/ch-side.ejs draws the outcome legend over the evidence drawers, and it shares
   the class name `.chs` with the timeline. The timeline's chrome in ch-mkt.css therefore reaches it,
   which it already did before this rebuild. What this rule sets is the arrangement. */
.chs { display: grid; gap: var(--s5); align-content: start; }

/* ==========================================================================
   6. NARROW
   ========================================================================== */
@media (max-width: 1180px) {
  /* 500 of copy against what is left of 1180 gives the figure 600, and five cards of 212 around a
     336 globe need 760. The hero stacks, and the copy loses the top padding that set it against a
     figure now under it. */
  .chp-hero { grid-template-columns: minmax(0, 1fr); }
  .chp-hero-copy { padding-top: 0; }
  .chp-hero-copy .sc-lead { max-width: 40rem; }
  /* Stacked, the figure holds the reference's own 760 and centres, rather than stretching the five
     cards to the two far edges of a full width band with 600px of nothing between them. */
  .chp-hero .chp-ring { width: 100%; max-width: 760px; margin-inline: auto; }
}
@media (max-width: 1000px) {
  /* Two across, then one. At two across the vertical hairline between the two columns of the second
     row would start a rule against nothing, so the separator moves to the second column only. */
  .chf-row { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: var(--s6); }
  .chf-card + .chf-card { border-left: 0; }
  .chf-row > .chf-card:nth-child(2n) { border-left: 1px solid var(--hairline); }
}
@media (max-width: 760px) {
  /* The reference is not designed narrow. 52px in a 360px column breaks a headline mid word, so the
     display scale takes over below the width the reference's own measure stops working at. */
  .chp-hero-copy .sc-headline { font-size: var(--t-display); line-height: var(--t-display-line); }
}
@media (max-width: 560px) {
  .chf-row { grid-template-columns: minmax(0, 1fr); row-gap: var(--s5); }
  .chf-card, .chf-row > .chf-card:nth-child(2n) { border-left: 0; padding: 0; }
}

/* ==========================================================================
   7. ONE FIGURE THIS ROUTE NO LONGER DRAWS, KEPT FOR THE GALLERY
   ==========================================================================
   packages/ui/partials/ch-orbit.ejs is rendered by packages/ui/gallery and by nothing else. The
   `:has()` scoping is not a flourish: `.sc-hero` and `.actions` belong to six scenario pages and to
   the base sheet, so a bare rule on either would land on five pages belonging to five other people.
   `.chb-orbit` is drawn by one partial, so these reach one object and no route. */
.sc-hero:has(.chb-orbit) { grid-template-columns: minmax(0, 1fr) minmax(0, 1.12fr); align-items: center; }
.chb-orbit { margin: 0; display: grid; gap: var(--s4); }
.chb-note {
  display: grid; justify-items: end; gap: 2px;
  color: var(--ink-2);
  font-size: var(--t-label); line-height: var(--t-label-line); font-weight: var(--t-label-weight);
  letter-spacing: 0.22em; text-transform: uppercase;
}
.chb-ring {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 150px minmax(0, 1fr);
  grid-template-rows: auto auto auto;
  column-gap: var(--s3);
  row-gap: var(--s4);
  align-items: center;
  justify-items: stretch;
}
.chb-spokes { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.chb-spokes line { stroke: var(--teal-dark); stroke-width: 1; opacity: 0.42; }
.chb-callout[data-at="top"] { grid-area: 1 / 1 / 2 / 4; justify-self: center; width: min(100%, 17rem); }
.chb-callout[data-at="left-up"] { grid-area: 2 / 1 / 3 / 2; }
.chb-callout[data-at="right-up"] { grid-area: 2 / 3 / 3 / 4; }
.chb-callout[data-at="left-down"] { grid-area: 3 / 1 / 4 / 2; }
.chb-callout[data-at="right-down"] { grid-area: 3 / 3 / 4 / 4; }
.chb-core {
  grid-area: 2 / 2 / 4 / 3;
  justify-self: center; align-self: center;
  position: relative; z-index: 1;
  width: 138px; height: 138px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--paper-alt);
  border: 1px solid var(--teal-dark);
  box-shadow: 0 0 46px color-mix(in srgb, var(--teal-dark) 24%, transparent);
}
.chb-core img { width: 112px; height: 112px; border-radius: 50%; object-fit: cover; }
.chb-callout {
  position: relative; z-index: 1;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--s2) var(--s3);
  padding: var(--s3) var(--s4) var(--s4);
  min-width: 0;
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--r-2);
}
.chb-mark {
  width: 32px; height: 32px; flex: none;
  display: grid; place-items: center;
  border-radius: var(--r-1);
  border: 1px solid color-mix(in srgb, var(--teal-dark) 50%, transparent);
  background: var(--wash-teal);
  color: var(--teal-dark);
}
.chb-mark .sc-glyph { width: 18px; height: 18px; }
.chb-words { min-width: 0; display: grid; gap: 2px; align-self: center; }
.chb-label { font-size: var(--t-small); line-height: var(--t-small-line); font-weight: 600; }
.chb-act { color: var(--ink-2); font-size: var(--t-label); line-height: var(--t-label-line); }
.chb-state { grid-column: 1 / -1; justify-self: start; }
@media (max-width: 1040px) {
  .chb-ring { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); grid-template-rows: auto auto auto auto; }
  .chb-core { grid-area: 1 / 1 / 2 / 3; }
  .chb-callout[data-at="top"] { grid-area: 2 / 1 / 3 / 3; width: 100%; }
  .chb-callout[data-at="left-up"] { grid-area: 3 / 1 / 4 / 2; }
  .chb-callout[data-at="right-up"] { grid-area: 3 / 2 / 4 / 3; }
  .chb-callout[data-at="left-down"] { grid-area: 4 / 1 / 5 / 2; }
  .chb-callout[data-at="right-down"] { grid-area: 4 / 2 / 5 / 3; }
  .chb-spokes { display: none; }
  .chb-note { justify-items: start; }
}
@media (max-width: 560px) {
  .chb-ring { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; }
  .chb-core, .chb-callout[data-at] { grid-area: auto; width: 100%; }
}

/* ==========================================================================
   8. THE IDENTITY HUES ON THE PAYOFF ROW
   ==========================================================================
   The four ringed marks at the foot of the page each name something the instrument above already
   drew. They were four identical rings in one brand cyan, which reads as one object repeated four
   times. Each takes one of the four identity hues, in the order the row is written.

   THE HUES OF THE THREE SETS ABOVE ARE IN packages/ui/src/parts/ch-mkt.css, beside the components
   they belong to. The whole rule is stated there once: an identity hue answers WHICH ONE of a set
   of peers this is and carries no meaning of its own, and the CONTINUE, REDUCE and REFUSE chips
   stay state colours because they say what access does.

   THE RING TAKES THE HUE AND THE MARK INSIDE IT DOES NOT. The mark is a published PNG, declared in
   tests/published-assets.test.ts, so it carries its own colour and no rule here can tint it. The
   ring is what separates the four.
   ========================================================================== */
.chf .chf-card:nth-child(1) { --hue: var(--d-blue); }
.chf .chf-card:nth-child(2) { --hue: var(--d-violet); }
.chf .chf-card:nth-child(3) { --hue: var(--d-magenta); }
.chf .chf-card:nth-child(4) { --hue: var(--d-sand); }
.chf .chf-icon { border-color: var(--hue); }

/* ==========================================================================
   9. THE INSTRUMENT, LIT AND TOLD APART
   ==========================================================================
   WHAT THIS IS. The instrument is the one object on this page that carries the argument, and it was
   drawn in brand cyan and five greys: five tabs, three cards, two arrows and a tree, all one
   colour. CLAUDE.md names that result, a page drawn in cyan alone looks like a wireframe of the
   target, and it measured ten routes that had removed the four hues altogether. This section puts
   them back on the figure and lights the cards. It adds no markup, because
   packages/ui/partials/ch-change.ejs is not this work's file.

   THE DISTINCTION THESE RULES ARE HELD TO. A state colour answers what is TRUE of a thing, sits
   beside a word, and uses --ok, --att and --no. An identity hue answers WHICH ONE of a set of peers
   this is and carries no meaning of its own. Every declaration below is the second kind. Not one of
   them touches a node, an outcome chip or a legend dot, which are the state marks on this figure.

   TWO SETS OF PEERS, AND THEY ARE DIFFERENT QUESTIONS IN DIFFERENT COLUMNS.

     the scope   which of the five changes this is. It is carried by the tab in step one, the
                 published surface in step two and the reading under the strip, so choosing a tab
                 lights one hue along the whole row. The mapping is the hero ring's own, in
                 packages/ui/src/parts/ch-mkt.css, so a scope's card in the hero and the same
                 scope's tab here are one colour.
     the layer   which of the five bands of the tree this is: the recognition, the identity, its
                 artefacts, its running copies, a chain that runs another way. It is carried by the
                 row label in step three, and it is the reading the page exists for, because the
                 claim is that each layer has its own control.

   A reader never compares a tab in the first column with a row label in the third, and the two
   never appear on one element, so the palette serves both axes without either borrowing the other's
   meaning.

   FIVE PEERS AND FOUR HUES, so the fifth repeats the first. That is the hero ring's convention for
   the same five scopes, followed rather than invented here. Both assignments are POSITIONAL and
   both live in this file, so data/scopes.yaml cannot pick a colour and a renamed scope or row
   cannot change one.

   THE ROW LABEL TAKES THE HUE AS TEXT, AND THE PAIR IS GATED RATHER THAN JUDGED.
   packages/ui/tools/contrast.mjs pairs d-blue, d-violet, d-magenta and d-sand with d-ground,
   d-surface and d-card at the 4.5 TEXT floor, not at the 3 of a graphic. The label lands on
   var(--white), and packages/ui/tools/build.mjs remaps white to d-card on dark, which is the
   lightest ground and therefore the one that decides: d-blue 7.35, d-violet 6.62, d-magenta 10.16,
   d-sand 10.41. An earlier pass of this section refused the hue as text on the ground that no
   instrument had measured it. That was wrong, and the remap above is why.

   WHAT THE HUE ON A ROW DOES NOT SAY. Whether the change reached that layer. The node beside the
   label carries data-state and keeps var(--ok), var(--no) or the dashed edge from
   packages/ui/src/parts/ch.css. So one row gives two readings that cannot be confused: the hue says
   which layer, the node says what happened to it.

   THE LIGHT. CLAUDE.md's card recipe is a hairline edge, a top border tinted to the light and
   inset 0 1px 0 in the same colour, so a panel reads as lit from above rather than as a rectangle.
   The three step cards, the published surface, the five tabs and the reading take it in the brand,
   and the band takes one very large soft ellipse behind it, which is what stops the ground reading
   flat. No flat background under text is a colour-mix here: every mix below sits in a shadow or a
   gradient, which is what packages/ui/tests/stylesheet.test.ts permits.

   EVERY SELECTOR CARRIES .wrap.chp ON PURPOSE. packages/ui/src/parts/ch.css sorts after this file,
   so a rule of equal weight would lose to it on load order alone. Two extra classes settle the
   cascade by specificity instead, and they also hold these rules to this page: the gallery renders
   ch-change with no page wrapper and is left exactly as it was.
   ========================================================================== */

/* THE SCOPE AXIS. One hue for the tab, the published surface and the reading of the same scope. */
.wrap.chp .ch { --hue: var(--d-blue); }
.wrap.chp .ch .ch-tab:nth-of-type(1), .wrap.chp .ch .ch-pub:nth-of-type(1), .wrap.chp .ch .ch-read:nth-of-type(1) { --hue: var(--d-blue); }
.wrap.chp .ch .ch-tab:nth-of-type(2), .wrap.chp .ch .ch-pub:nth-of-type(2), .wrap.chp .ch .ch-read:nth-of-type(2) { --hue: var(--d-violet); }
.wrap.chp .ch .ch-tab:nth-of-type(3), .wrap.chp .ch .ch-pub:nth-of-type(3), .wrap.chp .ch .ch-read:nth-of-type(3) { --hue: var(--d-magenta); }
.wrap.chp .ch .ch-tab:nth-of-type(4), .wrap.chp .ch .ch-pub:nth-of-type(4), .wrap.chp .ch .ch-read:nth-of-type(4) { --hue: var(--d-sand); }
.wrap.chp .ch .ch-tab:nth-of-type(5), .wrap.chp .ch .ch-pub:nth-of-type(5), .wrap.chp .ch .ch-read:nth-of-type(5) { --hue: var(--d-blue); }

/* The edge on the three objects a scope owns. 3px rather than 1px, because a one pixel edge in a
   hue beside a one pixel edge in the rule token is a difference nobody sees at reading distance. */
.wrap.chp .ch .ch-tab { border-left: 3px solid var(--hue); }
.wrap.chp .ch .ch-pub .ch-pub-surface { border-left: 3px solid var(--hue); }
.wrap.chp .ch .ch-read { border-left: 3px solid var(--hue); }

/* THE CHOSEN TAB, AND THE SELECTOR IS LONG FOR A REASON. packages/ui/src/parts/ch.css sorts after
   this file and sets border-color on the checked tab in five selectors of six classes each, so the
   rule above would lose its left edge the moment a reader picks that tab. This is the same chain
   with `.wrap.chp` in front of it, which is one class more, and it changes the colour only: the
   brand wash behind the chosen tab stays, because that wash says which control is pressed rather
   than anything about the estate. */
.wrap.chp .ch > .ch-in:nth-of-type(1):checked ~ .ch-grid .ch-tab:nth-of-type(1),
.wrap.chp .ch > .ch-in:nth-of-type(2):checked ~ .ch-grid .ch-tab:nth-of-type(2),
.wrap.chp .ch > .ch-in:nth-of-type(3):checked ~ .ch-grid .ch-tab:nth-of-type(3),
.wrap.chp .ch > .ch-in:nth-of-type(4):checked ~ .ch-grid .ch-tab:nth-of-type(4),
.wrap.chp .ch > .ch-in:nth-of-type(5):checked ~ .ch-grid .ch-tab:nth-of-type(5) { border-color: var(--hue); }

/* THE LAYER AXIS. The label carries the hue and the nodes beside it do not.

   NINE em AND NOT TEN, AND THE em IS THE ROW'S 17px RATHER THAN THE LABEL'S 14px. Measured at 1440
   in Chrome: at 10em the label column takes 170px and leaves the nodes 245, while the artefact row
   needs 251 for its two boxes and a gap, so the trust mark dropped onto a line of its own and that
   row stood 123px tall against the 58 of its neighbours. At 9em the column is 153, the nodes get
   262, and the row holds. The longest label, Running copies, needs about 100px of the 143 the
   column then gives it. */
.wrap.chp .ch-row { grid-template-columns: minmax(0, 9em) minmax(0, 1fr); }
/* AND THE NARROW STATE IS PUT BACK BY HAND, WHICH IS THE COST OF WINNING ON SPECIFICITY.
   packages/ui/src/parts/ch.css stacks the row at @container (max-width: 560px) in one class. The
   rule above carries three, so it beat that query and held the label column at 9em on a phone:
   measured at a 400px viewport, the label took 144 of the 360 the instrument had and the artefact
   and instance rows both grew to three lines. The same query is repeated here at the same width, so
   the stacked state returns. */
@container (max-width: 560px) {
  .wrap.chp .ch-row { grid-template-columns: minmax(0, 1fr); }
}
.wrap.chp .ch .ch-frame .ch-row:nth-of-type(1) .ch-row-label { --hue: var(--d-blue); }
.wrap.chp .ch .ch-frame .ch-row:nth-of-type(2) .ch-row-label { --hue: var(--d-violet); }
.wrap.chp .ch .ch-frame .ch-row:nth-of-type(3) .ch-row-label { --hue: var(--d-magenta); }
.wrap.chp .ch .ch-frame .ch-row:nth-of-type(4) .ch-row-label { --hue: var(--d-sand); }
.wrap.chp .ch .ch-frame .ch-row:nth-of-type(5) .ch-row-label { --hue: var(--d-blue); }
.wrap.chp .ch .ch-frame .ch-row .ch-row-label {
  color: var(--hue);
  font-weight: 600;
  border-left: 3px solid var(--hue);
  padding-left: var(--s3);
}

/* THE AMBIENT GLOW BEHIND THE BAND. One ellipse, very large and very soft, inside the section's own
   stacking context, so it sits under the instrument and over nothing else. */
.wrap.chp > .chp-figure { position: relative; isolation: isolate; }
.wrap.chp > .chp-figure::before {
  content: "";
  position: absolute;
  z-index: -1;
  left: 50%;
  top: 8%;
  width: min(1080px, 94%);
  height: 520px;
  transform: translateX(-50%);
  border-radius: 50%;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--teal-mid) 20%, transparent), transparent);
  filter: blur(46px);
  pointer-events: none;
}

/* The three step cards, the published surface, the tabs and the reading, each lit from above. */
.wrap.chp .ch-step,
.wrap.chp .ch-pub-surface {
  border-top-color: color-mix(in srgb, var(--teal-dark) 34%, transparent);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--teal-mid) 30%, transparent);
}
.wrap.chp .ch-tab { box-shadow: inset 0 1px 0 color-mix(in srgb, var(--teal-mid) 16%, transparent); }
.wrap.chp .ch-read { box-shadow: inset 0 1px 0 color-mix(in srgb, var(--teal-mid) 22%, transparent); }

/* ---- src/parts/ch.css ---- */
/*
 * /use-cases/when-something-changes, rebuilt as one interactive strip. `ch-` is the instrument,
 * `cho-` the outcome legend in the hero, `chd-` the drawers beside the worked example.
 *
 * MEASURED FROM docs/redesign/refs5/three-screens.png, MIDDLE PANEL, medians over thousands of
 * pixels rather than picked: page ground #00101f, panel ground #011121, accent #4c98e0, verified
 * green #3fc293, ink #f8f9fa. The site's own dark tokens are --paper #001721, --white #0b2531,
 * --paper-alt #031e27, --ok, and --teal-dark, which resolves to #15d4d8 on dark. The grounds are
 * close enough that nothing moves.
 *
 * THE ACCENT STAYS THE SITE'S TEAL AND THE DIFFERENCE IS RECORDED RATHER THAN TAKEN. #4c98e0 is a
 * blue and --teal-dark is a cyan. A hue is a token decision across nineteen routes, packages/ui/
 * tokens/tokens.json is the one place it lives, and Ralph has not taken that decision.
 *
 * NOT MEASURED AND NOT USED: spacing, type size, radius and stroke weight. The reference is three
 * panels inside 1536 pixels, so each panel is about 511 wide, and none of those properties survives
 * that downscale. Every one of them comes from the system's own scale.
 *
 * WHAT THE REFERENCE DRAWS THAT THIS DOES NOT, each recorded here so that nobody restores it from
 * the picture later:
 *
 *   A GRADIENT HEADLINE. packages/ui/tools/contrast.mjs enumerates token pairs BY NAME and can see
 *   nothing about a gradient, so the largest text on the page would be gated by no instrument. The
 *   headline takes the flat accent the base sheet already has for the same intent.
 *
 *   THREE TOGGLE SWITCHES IN GREEN, AMBER AND RED. A toggle says a person flips access on this
 *   screen. Nobody does: a change is an act at an authority, and access follows when a consumer
 *   reads again. They are state chips, and the window is printed beside them.
 *
 *   A FOUR DOT TIMELINE READING "Access updated in real time". Nothing on this tenant was measured
 *   at anything like real time, and the last dot is push language over a pull mechanism. The strip
 *   prints the estate's declared window instead.
 *
 *   A PLAY TILE READING "60 second overview". No film is hosted for this journey and /healthz
 *   answers films 0.
 */

/* ---- The instrument ---- */

.ch {
  container-type: inline-size;
  border: 0;
  margin: 0;
  padding: 0;
  min-width: 0;
}

.ch-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, .92fr) auto minmax(0, 1.35fr);
  align-items: stretch;
  gap: 0;
}

.ch-step {
  display: grid;
  align-content: start;
  gap: var(--s2);
  position: relative;
  padding: var(--s6) var(--s4) var(--s4);
  border: 1px solid var(--rule);
  border-radius: var(--r-2);
  background: var(--white);
  min-width: 0;
}

/* The number sits on the top edge of its own card, as the reference has it, rather than in the
   flow. The site already draws this shape on /how-it-works and the two pages are read together. */
.ch-n {
  position: absolute;
  top: calc(var(--s5) * -1);
  left: 50%;
  transform: translateX(-50%);
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--teal-dark);
  background: var(--paper);
  color: var(--teal-dark);
  font: var(--t-h3-weight) var(--t-h3) / 1 var(--sans);
  box-shadow: 0 0 0 6px var(--wash-teal);
}

.ch-verb {
  margin: 0;
  text-align: center;
  font: var(--t-h3-weight) var(--t-h3) / var(--t-h3-line) var(--sans);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink);
}

.ch-does {
  margin: 0 0 var(--s2);
  text-align: center;
  font-size: var(--t-small);
  color: var(--ink-2);
}

/* The arrows, grid items rather than pseudo elements on the cards, so the rail's own gap does not
   have to be faked and an arrow can shrink without the cards moving. */
.ch-arrow {
  align-self: center;
  width: 34px;
  height: 2px;
  margin: 0 var(--s2);
  border-radius: 2px;
  background: var(--teal-dark);
  position: relative;
}

.ch-arrow::after {
  content: "";
  position: absolute;
  right: 0;
  top: 50%;
  width: 8px;
  height: 8px;
  border-top: 2px solid var(--teal-dark);
  border-right: 2px solid var(--teal-dark);
  transform: translateY(-50%) rotate(45deg);
}

/* ---- Step one: what changed ---- */

.ch-tabs { display: grid; gap: 6px; }

.ch-tab {
  display: grid;
  gap: 2px;
  padding: 10px var(--s3);
  border: 1px solid var(--rule);
  border-radius: var(--r-1);
  background: var(--paper);
  cursor: pointer;
}

.ch-tab:hover { border-color: var(--teal-dark); }
.ch-tab-label { font-size: var(--t-small); font-weight: 600; color: var(--ink); }
.ch-tab-act.mono { font-size: var(--t-label); color: var(--ink-2); }

/* ---- Step two: what the authority publishes ---- */

.ch-pub-i { display: grid; place-items: center; justify-self: center; width: 54px; height: 54px; margin: var(--s3) 0; color: var(--teal-dark); }
.ch-pub-i svg { width: 100%; height: 100%; }

.ch-pubs { display: grid; }

.ch-pub {
  grid-area: 1 / 1;
  display: grid;
  align-content: start;
  gap: var(--s3);
  visibility: hidden;
  opacity: 0;
  transition: opacity var(--m-drawer) ease;
}

.ch-pub-who { display: block; font-weight: 600; color: var(--teal-dark); margin-bottom: 2px; }

.ch-pub-surface {
  margin: 0;
  padding: 10px var(--s3);
  border: 1px solid var(--rule);
  border-radius: var(--r-1);
  background: var(--paper);
  font-size: var(--t-small);
  color: var(--ink);
}

.ch-pub-when { display: grid; gap: 2px; margin: 0; justify-items: center; text-align: center; }
.ch-pub-word { font-size: var(--t-label); color: var(--ink-2); }
.ch-pub-bound.mono { font-size: var(--t-body); color: var(--teal-dark); }

/* ---- Step three: what access does ---- */

.ch-frames { display: grid; }

.ch-frame {
  grid-area: 1 / 1;
  display: grid;
  align-content: start;
  gap: var(--s3);
  visibility: hidden;
  opacity: 0;
  transition: opacity var(--m-drawer) ease;
}

.ch-outcome { justify-self: center; padding: 6px var(--s4); }

.ch-tree { display: grid; gap: 6px; }

.ch-row { display: grid; grid-template-columns: minmax(0, 8.5em) minmax(0, 1fr); align-items: center; gap: var(--s3); }
.ch-row-label { font-size: var(--t-label); color: var(--ink-2); }
.ch-row-nodes { display: flex; flex-wrap: wrap; gap: 6px; }

.ch-node {
  display: grid;
  gap: 1px;
  padding: 6px 10px;
  border: 1px solid var(--rule);
  border-radius: var(--r-1);
  background: var(--paper);
}

.ch-node-name { font-size: var(--t-label); font-weight: 600; color: var(--ink); }
.ch-node-sub { font-size: var(--t-label); color: var(--ink-2); }

/* The three states. Green is a lifecycle state here and never an evidence mark: the partial's
   header carries the argument, and data-state is the selector the one colour rule permits. */
.ch-node[data-state="ok"] { border-color: var(--ok); }
.ch-node[data-state="no"] { border-color: var(--no); background: var(--wash-no); }
.ch-node[data-state="no"] .ch-node-name { text-decoration: line-through; }
/*
 * OUT OF SCOPE IS A DASHED BORDER AND THE SECONDARY INK, NEVER AN OPACITY.
 *
 * It was `opacity: .6` and that was a serious axe finding on twenty readings out of twenty: two
 * widths, five scopes and both disclosure states. Opacity composites the text against the panel, so
 * --ink-2 at six tenths stopped being a token pair and became a colour nothing gates.
 * packages/ui/tools/contrast.mjs enumerates pairs BY NAME and can see a composited colour exactly as
 * well as it can see a colour-mix, which is to say not at all. The quiet comes from weight and from
 * the border now, and both colours are pairs the gate reads.
 */
.ch-node[data-state="out"] { border-style: dashed; }
.ch-node[data-state="out"] .ch-node-name { font-weight: 400; color: var(--ink-2); }

.ch-legend { list-style: none; display: flex; flex-wrap: wrap; gap: var(--s2) var(--s4); margin: var(--s3) 0 0; padding: 0; }
.ch-legend li { display: inline-grid; grid-template-columns: 10px auto; align-items: baseline; gap: 2px 6px; font-size: var(--t-label); color: var(--ink-2); }
.ch-legend-word { font-weight: 600; color: var(--ink); }
.ch-legend-line { grid-column: 2; }
.ch-legend-dot { width: 10px; height: 10px; border-radius: 50%; border: 2px solid var(--rule); }
.ch-legend li[data-state="ok"] .ch-legend-dot { border-color: var(--ok); }
.ch-legend li[data-state="no"] .ch-legend-dot { border-color: var(--no); }
.ch-legend li[data-state="out"] .ch-legend-dot { border-style: dashed; }

/* ---- The reading of the scope in view, under the strip ---- */

.ch-reads { display: grid; margin-top: var(--s5); }

.ch-read {
  grid-area: 1 / 1;
  padding: var(--s4) var(--s5);
  border: 1px solid var(--rule);
  border-radius: var(--r-2);
  background: var(--paper-alt);
  visibility: hidden;
  opacity: 0;
  transition: opacity var(--m-drawer) ease;
}

.ch-read-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s3); margin: 0 0 var(--s3); }
.ch-read-ev { margin-left: auto; }
.ch-read-name { font: var(--t-h3-weight) var(--t-h3) / var(--t-h3-line) var(--sans); color: var(--ink); }
.ch-read-verb.mono { font-size: var(--t-label); letter-spacing: .08em; text-transform: uppercase; color: var(--ink-2); }

.ch-facts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s4); margin: 0; }
.ch-facts dt { font-size: var(--t-label); letter-spacing: .06em; text-transform: uppercase; color: var(--ink-2); }
.ch-facts dd { margin: 4px 0 0; font-size: var(--t-small); color: var(--ink); }

/*
 * THE ONE THING THE RADIO GROUP DRIVES, WRITTEN OUT RATHER THAN GENERATED. Five inputs, and each
 * one shows its own tab, its own published surface, its own frame and its own reading. The shape is
 * packages/ui/src/parts/blast.css's, and its comment carries the reason the state lives on the
 * element rather than in a script.
 */
.ch > .ch-in:nth-of-type(1):checked ~ .ch-grid .ch-pub:nth-of-type(1),
.ch > .ch-in:nth-of-type(2):checked ~ .ch-grid .ch-pub:nth-of-type(2),
.ch > .ch-in:nth-of-type(3):checked ~ .ch-grid .ch-pub:nth-of-type(3),
.ch > .ch-in:nth-of-type(4):checked ~ .ch-grid .ch-pub:nth-of-type(4),
.ch > .ch-in:nth-of-type(5):checked ~ .ch-grid .ch-pub:nth-of-type(5),
.ch > .ch-in:nth-of-type(1):checked ~ .ch-grid .ch-frame:nth-of-type(1),
.ch > .ch-in:nth-of-type(2):checked ~ .ch-grid .ch-frame:nth-of-type(2),
.ch > .ch-in:nth-of-type(3):checked ~ .ch-grid .ch-frame:nth-of-type(3),
.ch > .ch-in:nth-of-type(4):checked ~ .ch-grid .ch-frame:nth-of-type(4),
.ch > .ch-in:nth-of-type(5):checked ~ .ch-grid .ch-frame:nth-of-type(5),
.ch > .ch-in:nth-of-type(1):checked ~ .ch-reads .ch-read:nth-of-type(1),
.ch > .ch-in:nth-of-type(2):checked ~ .ch-reads .ch-read:nth-of-type(2),
.ch > .ch-in:nth-of-type(3):checked ~ .ch-reads .ch-read:nth-of-type(3),
.ch > .ch-in:nth-of-type(4):checked ~ .ch-reads .ch-read:nth-of-type(4),
.ch > .ch-in:nth-of-type(5):checked ~ .ch-reads .ch-read:nth-of-type(5) { visibility: visible; opacity: 1; }

.ch > .ch-in:nth-of-type(1):checked ~ .ch-grid .ch-tab:nth-of-type(1),
.ch > .ch-in:nth-of-type(2):checked ~ .ch-grid .ch-tab:nth-of-type(2),
.ch > .ch-in:nth-of-type(3):checked ~ .ch-grid .ch-tab:nth-of-type(3),
.ch > .ch-in:nth-of-type(4):checked ~ .ch-grid .ch-tab:nth-of-type(4),
.ch > .ch-in:nth-of-type(5):checked ~ .ch-grid .ch-tab:nth-of-type(5) {
  border-color: var(--teal-dark);
  background: var(--wash-teal);
}

/*
 * The focus ring belongs on the label a reader sees, because the input itself is visually hidden.
 * The base sheet's ring is reproduced rather than removed: nothing here sets outline: none.
 *
 * A FIFTH SELECTOR STOOD AT THE HEAD OF THIS LIST WITH NO nth-of-type ON EITHER SIDE, so it matched
 * EVERY tab whenever ANY radio had focus, and the four below it were dead. Five rings is the same as
 * no ring: a keyboard visitor could not tell which scope focus was on. Measured with focus on
 * ch-certificate: all five labels reported outline-width 2px, then one.
 *
 * MY OWN CHECK SAID IT WAS FINE. It asked whether the focused label shows a ring, which was true,
 * and was equally true of the other four. A probe with a positive rate of one decides nothing, and
 * this is that defect in a check I wrote in the same hour.
 */
.ch > .ch-in:nth-of-type(1):focus-visible ~ .ch-grid .ch-tab:nth-of-type(1),
.ch > .ch-in:nth-of-type(2):focus-visible ~ .ch-grid .ch-tab:nth-of-type(2),
.ch > .ch-in:nth-of-type(3):focus-visible ~ .ch-grid .ch-tab:nth-of-type(3),
.ch > .ch-in:nth-of-type(4):focus-visible ~ .ch-grid .ch-tab:nth-of-type(4),
.ch > .ch-in:nth-of-type(5):focus-visible ~ .ch-grid .ch-tab:nth-of-type(5) {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
  box-shadow: 0 0 0 2px var(--focus-halo), 0 0 0 4px var(--focus-ring);
}

/*
 * THE ANIMATION IS THE BLAST, AND IT RUNS ONCE PER CHOICE FROM THE SECOND CHOICE ONWARD. The rule
 * below starts matching at the moment a radio is checked, which is what starts the animation.
 *
 * IT DOES NOT DO THAT FOR THE FIRST FRAME, and the comment here used to say it did. One radio
 * carries `checked` in the served markup, so this rule matches at parse and both keyframes are
 * already running 50ms after the document commits, measured with getAnimations. The figure is below
 * the fold on every width, so the first scope's blast finishes unseen on every visit. That is a
 * property of serving a page with a scope already chosen, and the alternative, serving it with none
 * chosen, is an empty figure above a legend, which is worse. Scopes two to five animate on the
 * choice.
 *
 * Under prefers-reduced-motion the whole block is absent, and the state still changes: the node
 * borders, the strike through and the outcome chip are painted by the rules above, which carry no
 * animation of any kind.
 */
@media (prefers-reduced-motion: no-preference) {
.ch > .ch-in:nth-of-type(1):checked ~ .ch-grid .ch-frame:nth-of-type(1) .ch-node[data-state="no"],
.ch > .ch-in:nth-of-type(2):checked ~ .ch-grid .ch-frame:nth-of-type(2) .ch-node[data-state="no"],
.ch > .ch-in:nth-of-type(3):checked ~ .ch-grid .ch-frame:nth-of-type(3) .ch-node[data-state="no"],
.ch > .ch-in:nth-of-type(4):checked ~ .ch-grid .ch-frame:nth-of-type(4) .ch-node[data-state="no"],
.ch > .ch-in:nth-of-type(5):checked ~ .ch-grid .ch-frame:nth-of-type(5) .ch-node[data-state="no"] { animation: ch-hit .42s ease-out both; }
.ch > .ch-in:nth-of-type(1):checked ~ .ch-grid .ch-frame:nth-of-type(1) .ch-outcome,
.ch > .ch-in:nth-of-type(2):checked ~ .ch-grid .ch-frame:nth-of-type(2) .ch-outcome,
.ch > .ch-in:nth-of-type(3):checked ~ .ch-grid .ch-frame:nth-of-type(3) .ch-outcome,
.ch > .ch-in:nth-of-type(4):checked ~ .ch-grid .ch-frame:nth-of-type(4) .ch-outcome,
.ch > .ch-in:nth-of-type(5):checked ~ .ch-grid .ch-frame:nth-of-type(5) .ch-outcome { animation: ch-in .42s ease-out both; }
}

@keyframes ch-hit { from { opacity: .3; transform: scale(.94); } to { opacity: 1; transform: none; } }
@keyframes ch-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

/*
 * THE STRIP BECOMES A COLUMN AT A NARROW CONTAINER, and the arrows turn with it. A container query
 * rather than a media query because this figure is drawn in the page and in the component gallery
 * at two different widths, and the viewport says nothing about which.
 */
@container (max-width: 1000px) {
  .ch-grid { grid-template-columns: minmax(0, 1fr); gap: var(--s5); }
  .ch-arrow { width: 2px; height: 30px; justify-self: center; margin: 0; }
  .ch-arrow::after { right: 50%; top: auto; bottom: 0; transform: translateX(50%) rotate(135deg); }
  .ch-step { padding-top: var(--s6); }
  /*
   * THE NUMBER MOVES TO THE LEFT EDGE IN A COLUMN, and that is a defect fix rather than a
   * preference. Stacked, the arrow runs down the centre of the gap and the badge protrudes above
   * the card on the same centre line, so the badge covered the lower half of the arrow and what
   * shipped was a stub. Measured rather than judged from the screenshot, which read it as worse
   * than it was: the arrow box is 24px and the badge covered 11 of them, so 13px was visible at
   * 1024 and at 390. With the badge at the left edge and the arrow at 30px, 30px is visible at both.
   */
  .ch-n { left: var(--s5); transform: none; }
}

@container (max-width: 560px) {
  .ch-row { grid-template-columns: minmax(0, 1fr); gap: 4px; }
  .ch-facts { grid-template-columns: minmax(0, 1fr); gap: var(--s3); }
}

/* ---- The outcome legend, in the hero ---- */

.cho {
  display: grid;
  gap: var(--s3);
  padding: var(--s5);
  border: 1px solid var(--rule);
  border-radius: var(--r-2);
  background: var(--white);
}

.cho-head { font-size: var(--t-label); letter-spacing: .08em; text-transform: uppercase; color: var(--ink-2); }
.cho-rows { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s3); }
.cho-row { display: grid; grid-template-columns: minmax(0, auto) minmax(0, 1fr); align-items: center; gap: var(--s3); }
.cho-chip { justify-self: start; padding: 6px var(--s3); white-space: nowrap; }
/* CONTINUE IS NOT GREEN. Green means Observed on this site and an Observed mark links its artefact.
   Continue is a lifecycle outcome, so it takes the neutral chip: ink on the paper ground, with a
   hairline. Reduce and refuse keep their state colours, each beside its word. */
.cho-chip[data-state="ok"] { color: var(--ink); background: var(--paper); box-shadow: inset 0 0 0 1px var(--rule); }
.cho-line { font-size: var(--t-small); color: var(--ink-2); }

@media (max-width: 560px) {
  .cho-row { grid-template-columns: minmax(0, 1fr); gap: 4px; }
}

/* ---- The drawers beside the worked example ---- */

.chd { display: grid; gap: var(--s3); }
.chd .drawer { margin: 0; }
.chd-line { margin: 0 0 var(--s3); font-size: var(--t-small); color: var(--ink-2); }
.chd-link { margin: var(--s3) 0 0; }

/* ---- src/parts/control-plane.css ---- */
/* The three band architecture figure. Partial: packages/ui/partials/control-plane.ejs.

   ONE BRAND ELEMENT. The Connect band is the only thing here that carries the accent, and every
   rule that names var(--teal) sits under [data-treat="product"] so the one colour rule can see it.
   The agent tiles above and the infrastructure tiles below are the customer's: a card ground, a
   rule stroke and ink icons. Making either of them teal would say they are Raidiam, which is the
   one thing the treatment vocabulary exists to prevent.

   THE FIGURE HAS NO CARD OF ITS OWN. .figure paints a card ground, and with it the page carried
   four greys stacked: page, figure card, band, tile. The bands are the objects, so the figure is
   transparent and the bands sit on the page ground, which is also where the Connect band's glow
   has somewhere to fall.

   WHAT HAPPENS AT 390. Three rows of tiles, six of them in the middle, is the shape that breaks a
   phone. Nothing here scrolls sideways because every row is a grid of minmax(0, 1fr) tracks and
   every track count steps down: four to two, five to three to two, six to three to two. The tiles
   keep their labels rather than dropping to icons, because a labelless icon row is a decoration.
   The connector arrows step down with them, so an arrow always stands over a column. */

.control-plane { background: transparent; padding: 0; display: block;   /* No card. The base sheet gives every .figure a radius, a stroke and a shadow, and this figure
     is a plane rather than a card: it sets padding to zero for the same reason, so a leaked
     stroke lands hard against the caption with no inset. Until 12 September this reset could
     not be written at all from a part, because the rule lived in site.css, which loads AFTER
     every part. It lives in the base sheet now and an ordinary override works. */
  border: 0; border-radius: 0; box-shadow: none;
}
.control-plane .figure-caption { max-width: var(--measure-notes); }

/* ---- the two customer bands ---- */

.control-plane .cp-band {
  background: var(--paper-alt);
  border: 1px solid color-mix(in srgb, var(--rule) 30%, transparent);
  border-radius: var(--r-3);
  padding: var(--s5);
}
.control-plane .cp-band-label {
  margin: 0 0 var(--s4);
  font-size: var(--t-label); font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--ink-2);
}

.control-plane .cp-tiles {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s3);
}
.control-plane .cp-tiles-wide { grid-template-columns: repeat(5, minmax(0, 1fr)); }

.control-plane .cp-tile {
  display: grid; justify-items: center; align-content: start; gap: var(--s2);
  padding: var(--s4) var(--s3);
  background: var(--white);
  border: 1px solid color-mix(in srgb, var(--rule) 38%, transparent);
  border-radius: var(--r-2);
  text-align: center;
  transition: border-color var(--m-drawer) ease, transform var(--m-drawer) ease;
}
.control-plane .cp-tile:hover { border-color: color-mix(in srgb, var(--rule) 75%, transparent); transform: translateY(-1px); }
.control-plane .cp-icon { display: grid; place-items: center; width: 26px; height: 26px; color: var(--ink-2); }
.control-plane .cp-icon svg { width: 100%; height: 100%; display: block; }
.control-plane .cp-label { font-size: var(--t-label); font-weight: 600; line-height: 1.3; color: var(--ink); }

.control-plane .cp-note {
  margin: var(--s4) 0 0; padding-top: var(--s4);
  border-top: 1px solid color-mix(in srgb, var(--rule) 30%, transparent);
  font-size: var(--t-small); color: var(--ink-2); max-width: var(--measure-notes);
}

/* ---- the connectors ----

   Every arrow points AWAY from Connect: it governs upward and publishes downward. Nothing points
   inward, because nothing asks Connect a question at the moment a platform decides. The word
   beside the arrows carries the rest, which an arrowhead cannot. */

.control-plane .cp-link {
  position: relative;
  display: grid; place-items: center;
  min-height: 76px; padding: var(--s3) 0;
}
/* The arrows stand in the outer thirds and leave the middle to the word. Spread evenly across four
   columns instead, two of the four land behind the sentence and the connector reads as having two
   arrows: that is what the first version drew. */
.control-plane .cp-arrows {
  position: absolute; inset: 0;
  display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); place-items: center;
  color: var(--teal-mid);
}
.control-plane .cp-arrow { width: 10px; height: 40px; display: block; }
.control-plane .cp-arrow:nth-child(3) { grid-column: 5; }
.control-plane .cp-arrow:nth-child(4) { grid-column: 6; }
.control-plane .cp-link[data-dir="down"] .cp-arrow { transform: scaleY(-1); }
.control-plane .cp-link-word {
  position: relative; margin: 0; padding: 0 var(--s4);
  font-size: var(--t-label); line-height: 1.4; color: var(--ink-2);
  text-align: center; max-width: 60ch;
}

/* The four arrows brighten in sequence, so the connector reads as a direction rather than as four
   static glyphs. It is the only motion in the figure and it stops under the reduced motion block
   at the foot of this file. */
@keyframes cp-flow {
  0%, 100% { opacity: 0.62; }
  35% { opacity: 1; }
}
.control-plane .cp-arrow { animation: cp-flow 3.2s ease-in-out infinite; }
.control-plane .cp-link[data-dir="up"] .cp-arrow:nth-child(1) { animation-delay: 0.6s; }
.control-plane .cp-link[data-dir="up"] .cp-arrow:nth-child(2) { animation-delay: 0.4s; }
.control-plane .cp-link[data-dir="up"] .cp-arrow:nth-child(3) { animation-delay: 0.2s; }
.control-plane .cp-link[data-dir="up"] .cp-arrow:nth-child(4) { animation-delay: 0s; }
.control-plane .cp-link[data-dir="down"] .cp-arrow:nth-child(1) { animation-delay: 0s; }
.control-plane .cp-link[data-dir="down"] .cp-arrow:nth-child(2) { animation-delay: 0.2s; }
.control-plane .cp-link[data-dir="down"] .cp-arrow:nth-child(3) { animation-delay: 0.4s; }
.control-plane .cp-link[data-dir="down"] .cp-arrow:nth-child(4) { animation-delay: 0.6s; }

/* ---- the Connect band, the one product element ---- */

/* THE GROUND IS A PLAIN TOKEN AND THE LIGHT IS ALL IN THE SHADOW. Every ground here started as a
   colour-mix, and a mix is outside the contrast gate: packages/ui/tools/contrast.mjs enumerates
   token PAIRS BY NAME and never reads CSS, so it gates `d-ink on d-wash-teal` and can see nothing
   at all about a mix. Text over one was gated by no instrument.

   The reason first written here was that axe cannot resolve a colour-mix. That was wrong, and it
   was my wrong claim rather than this file's: settled afterwards by planting the same failing pair
   twice, once as a mix and once as a hex, and axe reported both as violations. It resolves a mix
   perfectly well.

   A mix is still fine in a shadow or a border, where no text lands, so the top highlight and the
   glow are inset and outset shadows and the ground stays a token the gate can name. */
.control-plane .cp-connect[data-treat="product"] {
  position: relative;
  padding: var(--s6) var(--s5) var(--s5);
  border: 1.5px solid var(--teal);
  border-radius: var(--r-3);
  background: var(--wash-teal);
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--teal) 22%, transparent),
    0 0 22px -2px color-mix(in srgb, var(--teal) 42%, transparent),
    0 0 70px -10px color-mix(in srgb, var(--teal) 55%, transparent),
    inset 0 1px 0 0 color-mix(in srgb, var(--teal) 45%, transparent),
    inset 0 60px 90px -80px color-mix(in srgb, var(--teal) 90%, transparent);
}
/* The lockup is one line, as the reference has it: the wordmark supplies RAIDIAM and the type
   supplies CONNECT. The wordmark is sized by HEIGHT, not width, so its cap height matches the word
   beside it; its letters fill about 21 of the 24 viewBox units, so 22px of image is close to the
   19px cap of 27px type.

   THE HEAD IS A GRID AND THE LOCKUP IS ITS OWN ELEMENT. The first version made the head one wrapping
   flex row and gave the line flex: 0 0 100% to push it onto row two. It stayed on row one, because
   the same rule caps the line at var(--measure-notes) and a flex basis is clamped by max-width
   before the row is broken, so the basis resolved to 74ch rather than to the full width. Two rows
   that must not share a line are two grid rows. */
.control-plane .cp-connect[data-treat="product"] .cp-connect-head {
  display: grid; justify-items: center; gap: var(--s2);
  text-align: center; margin-bottom: var(--s5);
}
.control-plane .cp-connect[data-treat="product"] .cp-lockup {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  column-gap: var(--s3); row-gap: var(--s2);
}
.control-plane .cp-connect[data-treat="product"] .cp-wordmark { display: block; width: auto; height: 22px; }
.control-plane .cp-connect[data-treat="product"] .cp-connect-name {
  font-size: var(--t-h2); font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase;
  line-height: 1; color: var(--ink);
}
.control-plane .cp-connect[data-treat="product"] .cp-connect-line {
  margin: 0; font-size: var(--t-small); color: var(--ink-2); max-width: var(--measure-notes);
}
.control-plane .cp-connect[data-treat="product"] .cp-caps {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: var(--s3);
}
.control-plane .cp-connect[data-treat="product"] .cp-cap {
  display: grid; justify-items: center; align-content: start; gap: var(--s2);
  padding: var(--s4) var(--s2);
  border: 1px solid color-mix(in srgb, var(--teal) 32%, transparent);
  border-radius: var(--r-2);
  text-align: center;
  box-shadow: inset 0 0 26px -12px color-mix(in srgb, var(--teal) 55%, transparent);
  transition: border-color var(--m-drawer) ease, box-shadow var(--m-drawer) ease;
}
.control-plane .cp-connect[data-treat="product"] .cp-cap:hover {
  border-color: color-mix(in srgb, var(--teal) 62%, transparent);
  box-shadow: inset 0 0 26px -8px color-mix(in srgb, var(--teal) 70%, transparent);
}
.control-plane .cp-connect[data-treat="product"] .cp-cap .cp-icon { color: var(--teal); }

/* ---- narrow ---- */

@media (max-width: 1100px) {
  .control-plane .cp-connect[data-treat="product"] .cp-caps { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .control-plane .cp-tiles-wide { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
/* THE CONNECTOR STOPS BEING A LAYER AND BECOMES A STACK. Wide, the arrows are an absolute layer
   behind a centred sentence and the two never meet. Narrow there is no room for both on one line,
   so the arrows lose their absolute position, two of the four go, and the sentence sits under them.
   Dropping the two also retires the grid-column: 5 and 6 placements: left in place against a two
   track grid they created implicit tracks off the right hand edge, and the two arrows landed on top
   of the sentence. That was on screen at 390. */
@media (max-width: 760px) {
  .control-plane .cp-band { padding: var(--s4); }
  .control-plane .cp-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .control-plane .cp-link { min-height: 0; gap: var(--s2); padding: var(--s4) 0; }
  .control-plane .cp-arrows { position: static; width: 100%; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .control-plane .cp-arrow:nth-child(3), .control-plane .cp-arrow:nth-child(4) { display: none; }
  .control-plane .cp-arrow { height: 30px; }
  .control-plane .cp-link-word { padding: 0; }
  .control-plane .cp-connect[data-treat="product"] { padding: var(--s5) var(--s4) var(--s4); }
}
@media (max-width: 560px) {
  .control-plane .cp-tiles-wide { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .control-plane .cp-connect[data-treat="product"] .cp-caps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .control-plane .cp-connect[data-treat="product"] .cp-connect-name { font-size: var(--t-h3); }
  .control-plane .cp-connect[data-treat="product"] .cp-wordmark { height: 18px; }
}

/* All motion stops. The global block in ui.css already shortens every animation to a fraction of a
   millisecond; this one removes the animation outright and restores the end state, so the four
   arrows sit at full opacity rather than wherever a one frame run left them. */
@media (prefers-reduced-motion: reduce) {
  .control-plane .cp-arrow { animation: none; opacity: 1; }
  .control-plane .cp-tile, .control-plane .cp-connect[data-treat="product"] .cp-cap { transition: none; }
  .control-plane .cp-tile:hover { transform: none; }
}

/* ---- src/parts/cta.css ---- */
/* The closing call to action.

   The base .cta in src/ui.css is the plain two column row the journey pages use and it stays
   exactly as it was. Everything here is the WIDE form the home page asks for with `figure: true`,
   scoped to .cta-wide so a page that does not ask for it cannot pick it up by accident. */

.cta .cta-body { display: grid; gap: var(--s3); }
.cta .cta-body > * { margin: 0; }
.cta .cta-sub { font-size: var(--t-body); color: var(--ink-2); max-width: 46ch; }
.cta .cta-actions { display: flex; flex-wrap: wrap; gap: var(--s3); margin-top: var(--s2); }

.cta-wide {
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  align-items: stretch;
  padding: 0;
  overflow: hidden;
  border: 1px solid var(--rule);
}
.cta-wide .cta-body { align-content: center; padding: var(--s8) var(--s7); }
.cta-wide .statement { font-size: var(--t-h1); font-weight: var(--t-h1-weight); line-height: var(--t-h1-line); letter-spacing: var(--t-h1-tracking); max-width: 18ch; }

/* The drawn horizon. It bleeds to the panel edge, so the aside sits over it rather than beside it. */
.cta-figure { position: relative; min-height: 260px; }
.cta-figure svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.cta-aside {
  position: relative; margin: 0; padding: var(--s7) var(--s6);
  font-size: var(--t-h3); font-weight: var(--t-h3-weight); line-height: 1.25;
  max-width: 14ch; margin-left: auto; text-align: right;
}

/* A stacked panel below 900, and the figure keeps a height of its own so it does not collapse to a
   line. Under 620 the figure goes entirely: at that width it is 40 pixels of texture carrying no
   information, and the aside it exists to hold reads better as a line under the actions. */
@media (max-width: 900px) {
  .cta-wide { grid-template-columns: minmax(0, 1fr); }
  .cta-wide .cta-body { padding: var(--s7) var(--s5); }
  .cta-figure { min-height: 180px; }
  .cta-aside { max-width: none; text-align: left; padding: var(--s5); }
}
@media (max-width: 620px) {
  .cta-figure svg { display: none; }
  .cta-figure { min-height: 0; }
  .cta-aside { padding-top: 0; }
}

/* THE CLOSING PANEL ON A SCENARIO PAGE, where the statement is now the route's own working question
   rather than the one sentence every page shared.
 *
 * A QUESTION IS LONGER THAN A SLOGAN AND THE PANEL HAS TO ALLOW FOR IT. The base rule holds the
 * statement to 30ch, which suits "Bring one agent, one platform and one boundary from your estate."
 * A working question runs to about twenty words, so at 30ch it broke to four lines down the left
 * edge of a full width panel and left most of the panel empty. Measured at 1594 in Chrome.
 * The panel is one column here, because the second column held a button that now sits under the
 * text where a reader reaches it after reading the question rather than beside the first line. */
.band > .cta { grid-template-columns: minmax(0, 1fr); }
.band > .cta .statement { max-width: 46ch; }

/* ---- src/parts/display-scale.css ---- */
/* THE DISPLAY SCALE. One statement size per KIND of page, keyed by the route on the body element.
 *
 * WHAT THIS IS. The reference does not set one display size. Measured in its source: 76px on the
 * landing page, 56px on an interior page, 52px on a use case, 44px on the use case index. The
 * token --t-display carries the interior step, and this file narrows it for the two kinds that sit
 * below it. A page inherits the size from its route and declares nothing of its own.
 *
 * WHAT IT REFUSES TO DRAW. It sets no colour, no weight, no tracking and no line height, and it
 * names no page class. A rule that reached for a page's own class would put the size back in the
 * page, which is the thing that let eleven pages drift to a size nobody chose. The home page is the
 * one exception and it is deliberate: src/parts/hm.css sets 68px there with its arithmetic in the
 * file header, because the reference's 76px breaks that headline over five lines in our column.
 *
 * WHY THE BODY AND NOT :root. --t-display is inherited, so one declaration on the body reaches every
 * element on the page, including a headline drawn inside a partial this file has never heard of. */
body[data-route="/use-cases"] { --t-display: clamp(34px, 3.6vw, 44px); }
body[data-route^="/use-cases/"] { --t-display: clamp(36px, 4.2vw, 52px); }
body[data-route="/live-demo/boundary"] { --t-display: clamp(36px, 4.2vw, 52px); }

/* ---- src/parts/dpe.css ---- */
/* /architecture/deployment/evidence: its two figures, packages/ui/partials/dpe-operators.ejs and
 * dpe-signer.ejs.
 *
 * THE TREATMENTS ARE components/diagram-section.tsx's: the hub, the lit card and the pedestal come
 * from rw.css by class. rw.css sorts after this file, so every override of an rw class is written
 * under the figure's own class.
 *
 * IDENTITY HUES ONLY WHERE A FIGURE SAYS WHICH ONE. The four roles on the operators figure take one
 * hue each. On the signer figure the statement card takes blue and the key service violet, which says
 * which side of the line each object is on and nothing else. No state colour: the Deployment
 * evidence mark is the ev partial's own.
 *
 * NO SIZE UNDER 14px, the stylesheet test's floor.
 */

/* ---- WHO OPERATES WHAT ---- */
.dpe-ops { position: relative; margin: var(--s5) 0 0; display: grid; grid-template-columns: minmax(0, 1.1fr) 48px minmax(0, 1fr); align-items: stretch; min-width: 0; }
.dpe-ops-frame { position: relative; min-width: 0; border: 1px dashed var(--rule); border-radius: 16px; padding: var(--s5); }
.dpe-ops-t {
  position: absolute; top: -12px; left: var(--s4); margin: 0; padding: 0 var(--s2); background: var(--paper);
  font-size: 14px; line-height: 22px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-2);
}
.dpe-ops-op { margin: 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s2); font-size: 15px; color: var(--ink-2); }
.dpe-ops-op-l { font-weight: 700; color: var(--ink); }
.dpe-ops-n { font-size: 34px; line-height: 1; font-weight: 700; letter-spacing: -0.02em; color: var(--brand-strong); }
.dpe-ops-group { margin-top: var(--s4); }
.dpe-ops-group-t { margin: 0 0 var(--s2); font-size: 14px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-row); }
.dpe-ops-group-n { color: var(--brand-strong); }
.dpe-ops-chips { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.dpe-ops-chips li {
  padding: 2px var(--s2); border-radius: 6px; font-family: var(--mono); font-size: 14px; line-height: 1.5; color: var(--ink);
  border: 1px solid var(--hairline); background: var(--paper-alt);
}
.dpe-ops-turn { display: flex; align-items: center; justify-content: center; color: var(--ink-2); }
.dpe-ops-turn svg { width: 26px; height: 26px; }
.dpe-ops-frame[data-frame="yours"] { display: grid; gap: var(--s5); align-content: start; }
.dpe-ops .dpe-ops-hub { padding: var(--s4); }
.dpe-ops-hub-l, .dpe-ops-you-l { margin: 0; font-size: 14px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: var(--brand-strong); }
.dpe-ops-you-l { color: var(--ink-2); }
.dpe-ops-hub-items { list-style: none; margin: var(--s2) 0 0; padding: 0; font-size: 18px; font-weight: 700; color: var(--ink); }
.dpe-ops-roles { list-style: none; margin: var(--s2) 0 0; padding: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s2); }
.dpe-ops-role { display: grid; justify-items: center; text-align: center; min-width: 0; }
.dpe-ops .dpe-ped { margin-bottom: 0; }
.dpe-ops-role-l { margin-top: var(--s1, 4px); font-size: 15px; font-weight: 600; color: var(--ink); }

@media (max-width: 999px) {
  .dpe-ops { grid-template-columns: minmax(0, 1fr); row-gap: var(--s5); }
  .dpe-ops-turn { transform: rotate(90deg); }
}
@media (max-width: 560px) {
  .dpe-ops-roles { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: var(--s3); }
}

/* ---- WHERE THE SIGNING KEY IS ---- */
.dpe-signer { margin: var(--s5) 0 0; min-width: 0; }
.dpe-sg-grid { display: grid; grid-template-columns: minmax(0, 1fr) 140px minmax(0, 1fr); align-items: stretch; }
.dpe-sg-side { min-width: 0; display: grid; gap: var(--s4); align-content: start; }
.dpe-sg-side-t { margin: 0; display: flex; flex-wrap: wrap; align-items: center; gap: var(--s3); font-size: 14px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-2); }
.dpe-sg-side-t .ev { letter-spacing: normal; text-transform: none; }
.dpe-signer .dpe-jws, .dpe-signer .dpe-kms { padding: var(--s5); }
.dpe-jws-t, .dpe-kms-t { margin: 0; font-size: 17px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.dpe-jws-h { margin: var(--s4) 0 0; padding: var(--s3) var(--s4); border-radius: 8px; border: 1px solid var(--hairline); background: var(--paper); display: grid; gap: 6px; font-family: var(--mono); font-size: 14px; }
.dpe-jws-h > div { display: grid; grid-template-columns: 4ch minmax(0, 1fr); gap: var(--s3); }
.dpe-jws-h dt { color: var(--ink-2); }
.dpe-jws-h dd { margin: 0; color: var(--ink); overflow-wrap: anywhere; }
/* THE KID IS THE ONE VALUE THE FIGURE POINTS FROM, so it carries the side's hue as an underline. */
.dpe-jws-h [data-kid] dd { color: var(--ink); text-decoration: underline; text-decoration-color: var(--hue); text-decoration-thickness: 2px; text-underline-offset: 4px; }
.dpe-jws-read { margin: var(--s3) 0 0; font-size: 14px; color: var(--ink-2); }
.dpe-signer .dpe-ped { margin: 0 0 var(--s2); }
.dpe-kms-o { margin: 2px 0 0; font-size: 15px; color: var(--ink-2); }
.dpe-kms-holds { list-style: none; margin: var(--s4) 0 0; padding: 0; display: grid; gap: var(--s2); }
.dpe-kms-holds li { padding-left: var(--s3); border-left: 2px solid var(--hue); font-size: 15px; font-weight: 600; color: var(--ink-row); }
.dpe-sg-list { margin: 0; padding-left: 1.2em; display: grid; gap: var(--s2); font-size: 15px; line-height: 1.5; color: var(--ink-row); }

/* THE LINE. A dashed rule down the middle is the limit of what can be read from outside, and one
   arrow crosses it, labelled with the header member that does the pointing. */
.dpe-sg-line { position: relative; display: flex; align-items: center; justify-content: center; }
.dpe-sg-line::before { content: ""; position: absolute; top: 0; bottom: 0; left: 50%; border-left: 2px dashed var(--rule); }
.dpe-sg-arrow { position: absolute; left: 8px; right: 8px; top: 50%; height: 2px; background: var(--brand-strong); box-shadow: 0 0 8px var(--teal-dark); }
.dpe-sg-arrow::after {
  content: ""; position: absolute; right: -2px; top: -5px;
  border-top: 6px solid transparent; border-bottom: 6px solid transparent; border-left: 10px solid var(--brand-strong);
}
.dpe-sg-pointer {
  position: relative; transform: translateY(-22px); padding: 0 var(--s2); background: var(--paper);
  font-family: var(--mono); font-size: 14px; font-weight: 600; color: var(--brand-strong);
}

@media (max-width: 999px) {
  .dpe-sg-grid { grid-template-columns: minmax(0, 1fr); row-gap: 0; }
  .dpe-sg-line { height: 84px; }
  .dpe-sg-line::before { top: 50%; bottom: auto; left: 0; right: 0; border-left: 0; border-top: 2px dashed var(--rule); }
  .dpe-sg-arrow { left: 50%; right: auto; top: 8px; bottom: 8px; width: 2px; height: auto; }
  .dpe-sg-arrow::after { right: auto; top: auto; bottom: -2px; left: -5px; border-left: 6px solid transparent; border-right: 6px solid transparent; border-top: 10px solid var(--brand-strong); border-bottom: 0; }
  .dpe-sg-pointer { transform: translateX(34px); }
}

/* ---- src/parts/dpx.css ---- */
/* /architecture/deployment: its instrument, packages/ui/partials/dpx-exit.ejs. The exit drawn as the
 * entry in reverse: two panels of the same estate, while you use Connect and if you stop.
 *
 * THE TREATMENTS ARE components/diagram-section.tsx's. The hub, the lit card, the pedestal and the
 * ambient pool come from rw.css by class. This file places them, draws the wire, the dashed estate
 * frame and the quiet stopped state.
 *
 * rw.css SORTS AFTER THIS FILE, so a rule here that meets an rw rule at equal specificity loses.
 * Every override of an rw class is written under `.dpx` for that reason.
 *
 * FOUR IDENTITY HUES AND NO STATE COLOUR. A tile carries its hue in --hue, the same in both panels.
 * The stopped tenant goes quiet (lower ink, a dashed wire), not red: nothing was refused. What a
 * tile keeps is set in the brand, not green: nothing was observed.
 *
 * NO SIZE UNDER 14px, the stylesheet test's floor.
 */

.dpx { position: relative; margin: var(--s7, 4rem) 0 0; min-width: 0; }
.dpx-glow { top: 80px; }
/* THE TWO PANELS SHARE THEIR ROWS through subgrid: tag, hub, wire, estate and scope. Without it the
   running panel's two line wire label pushed its estate 20px below its twin, and a reader comparing
   two pictures of the same estate saw them misaligned. */
.dpx-panels { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) 48px minmax(0, 1fr); grid-template-rows: repeat(5, auto); }
.dpx-panel { position: relative; min-width: 0; display: grid; grid-row: 1 / span 5; grid-template-rows: subgrid; justify-items: center; }
.dpx-panel[data-phase="running"] { grid-column: 1; }
.dpx-panel[data-phase="stopped"] { grid-column: 3; }
.dpx-wire { align-self: stretch; grid-template-rows: auto auto 1fr; }
.dpx-tag {
  margin: 0 0 var(--s4); padding: 4px var(--s4); border-radius: 999px;
  font-size: 14px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--brand-strong); border: 1px solid var(--teal-dark); background: var(--paper);
}
.dpx-panel[data-phase="stopped"] .dpx-tag { color: var(--ink-row); border-color: var(--rule); }

/* THE HUB. The reference's hub card while Connect runs. When it stops the card keeps its shape and
   loses its light: the glow and the brand edge go, and the line says what stopped. */
.dpx .dpx-hub { width: min(100%, 440px); padding: var(--s4) var(--s5); }
.dpx-hub-name { margin: 0; font-size: 19px; line-height: 1.25; font-weight: 700; color: var(--ink); }
.dpx-hub-line { margin: var(--s1, 4px) 0 0; font-size: 15px; line-height: 1.45; color: var(--ink-2); }
/* THE ENTITY CONNECT HOSTS, drawn inside the hub because it is on Connect's side of the exit. */
.dpx-hosted {
  margin: var(--s3) 0 0; padding-top: var(--s3); border-top: 1px solid var(--hairline);
  font-size: 14px; line-height: 1.45; color: var(--ink-row);
}
.dpx-hosted .ev, .dpx-scope .ev { white-space: nowrap; }
.dpx-panel[data-phase="stopped"] .dpx-hub {
  background: var(--paper); border-style: dashed; border-color: var(--rule); box-shadow: none;
}
.dpx-panel[data-phase="stopped"] .dpx-hub-name { color: var(--ink-2); }
.dpx-panel[data-phase="stopped"] .dpx-hub-line { color: var(--ink); font-weight: 600; }

/* THE WIRE. A lit stem with the words in it and an arrowhead into the estate. When Connect stops
   the stem is dashed and unlit, and it carries no arrowhead: nothing new arrives. */
.dpx-wire { display: grid; justify-items: center; }
.dpx-wire-line { width: 2px; height: 22px; background: var(--teal-dark); box-shadow: 0 0 8px var(--teal-dark); }
.dpx-wire-end { position: relative; height: auto; min-height: 26px; }
.dpx-wire-end::after {
  content: ""; position: absolute; bottom: -2px; left: 50%; transform: translateX(-50%);
  border-left: 6px solid transparent; border-right: 6px solid transparent; border-top: 11px solid var(--brand-strong);
}
.dpx-wire-l {
  margin: 0; max-width: 34ch; padding: var(--s2) var(--s4); border-radius: 10px; text-align: center;
  font-size: 14px; line-height: 1.45; font-weight: 600; color: var(--ink);
  border: 1px solid var(--teal-dark); background: var(--paper);
}
.dpx-panel[data-phase="stopped"] .dpx-wire-line { background: none; box-shadow: none; border-left: 2px dashed var(--rule); width: 0; }
.dpx-panel[data-phase="stopped"] .dpx-wire-end::after { display: none; }
.dpx-panel[data-phase="stopped"] .dpx-wire-l { border-style: dashed; border-color: var(--rule); color: var(--ink-row); font-weight: 500; }

/* THE ESTATE. A dashed frame is the boundary, as it is on /architecture. The label sits on its top
   edge. Four tiles in a row, each on a pedestal in its hue. */
.dpx-frame {
  position: relative; width: 100%; margin-top: var(--s3);
  border: 1px dashed var(--rule); border-radius: 16px; padding: var(--s5) var(--s3) var(--s4);
}
.dpx-frame-l {
  position: absolute; top: -12px; left: var(--s4); margin: 0; padding: 0 var(--s2); background: var(--paper);
  font-size: 14px; line-height: 22px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-2);
}
.dpx-tiles { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s2); }
.dpx-tile { min-width: 0; display: grid; grid-template-rows: auto 1fr; }
.dpx .dpx-ped { margin-bottom: -6px; }
.dpx .dpx-card { padding: var(--s3); min-width: 0; display: flex; flex-direction: column; gap: var(--s2); }
.dpx-tile-l { margin: 0; font-size: 15px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.dpx-tile-sub { margin: 0; font-size: 14px; line-height: 1.45; color: var(--ink-2); }
.dpx-keeps { margin: 0; font-size: 14px; line-height: 1.45; color: var(--ink-row); }
.dpx-keeps-l { display: block; margin-bottom: 2px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--brand-strong); }
.dpx-scope { margin: var(--s3) 0 0; max-width: 60ch; font-size: 14px; line-height: 1.45; color: var(--ink-2); text-align: center; }

/* THE TURN between the panels: one arrow, which is the only thing that happens between them. */
.dpx-turn { grid-row: 2; grid-column: 2; display: flex; align-items: center; justify-content: center; color: var(--ink-2); }
.dpx-turn svg { width: 26px; height: 26px; }
.dpx-caption { margin: var(--s5) 0 0; font-size: 14px; color: var(--ink-2); text-align: center; }

/* BETWEEN 1000 AND 1300 each panel is about 440px, so its four tiles go two by two. */
@media (max-width: 1299px) {
  .dpx-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: var(--s3); }
}
/* BELOW 1000 THE PANELS STACK and the arrow between them turns down. */
@media (max-width: 999px) {
  .dpx-panels { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; row-gap: var(--s3); }
  .dpx-panel, .dpx-panel[data-phase] { grid-row: auto; grid-column: 1; grid-template-rows: none; }
  .dpx-turn { grid-row: auto; grid-column: 1; transform: rotate(90deg); }
}
@media (max-width: 560px) {
  .dpx-tiles { grid-template-columns: minmax(0, 1fr); }
  .dpx .dpx-ped { display: none; }
  .dpx .dpx-card { border-top-width: 2px; }
}

/* ---- src/parts/enm.css ---- */
/* /architecture/environment: its three instruments. Partials enm-places.ejs, enm-path.ejs and
 * enm-steps.ejs, in packages/ui/partials.
 *
 * THE TREATMENTS ARE components/diagram-section.tsx's. The hub, the lit card, the pedestal and the
 * ambient pool come from rw.css by class. This file places them, draws the fan of wires, the rail
 * and the step tiles.
 *
 * rw.css SORTS AFTER THIS FILE, so a rule here that meets an rw rule at equal specificity loses.
 * Every override of an rw class is written under `.enm` for that reason.
 *
 * FOUR IDENTITY HUES AND NO STATE COLOUR. A place carries its hue in --hue, and a step that acts on a
 * place takes the same hue. Nothing on these figures was observed, so --ok, --att and --no appear
 * nowhere in this file.
 *
 * NO SIZE UNDER 14px, the stylesheet test's floor.
 */

/* ---- THE MAP ---- */
.enm { position: relative; margin: var(--s6) 0 0; min-width: 0; display: grid; justify-items: center; }
.enm-glow { top: 40px; }
.enm .enm-hub { position: relative; z-index: 1; width: min(100%, 760px); padding: var(--s5) var(--s5) var(--s4); }
.enm-hub-t { margin: 0; font-size: 22px; line-height: 1.25; font-weight: 700; color: var(--ink); }
.enm-hub-l { margin: var(--s1, 4px) 0 0; font-size: 15px; line-height: 1.45; color: var(--ink-2); }
.enm-files { list-style: none; margin: var(--s4) 0 0; padding: 0; display: flex; flex-wrap: wrap; justify-content: center; align-items: stretch; gap: var(--s2); }
.enm-file { display: flex; align-items: center; gap: var(--s2); }
.enm-file-body {
  display: grid; gap: 2px; justify-items: start; text-align: left;
  padding: var(--s2) var(--s3); border-radius: 8px;
  border: 1px solid var(--hairline); background: var(--paper-alt);
}
.enm-file-path { font-family: var(--mono); font-size: 14px; color: var(--ink); overflow-wrap: anywhere; }
a.enm-file-path { color: var(--brand-strong); text-decoration: underline; text-underline-offset: 3px; }
.enm-file-role { font-size: 14px; color: var(--ink-2); }
/* THE ARROW BETWEEN THE TWO FILES says the second is generated from the first. */
.enm-file-arrow { width: 22px; height: 2px; background: var(--brand-strong); position: relative; flex: 0 0 auto; }
.enm-file-arrow::after {
  content: ""; position: absolute; right: -2px; top: -5px;
  border-top: 6px solid transparent; border-bottom: 6px solid transparent; border-left: 9px solid var(--brand-strong);
}

/* THE FAN. Four beziers, one per place, each in that place's hue, stretched across the width. The
   columns have no gap, so each card's centre falls at 12.5, 37.5, 62.5 and 87.5 per cent. */
.enm-fan { position: relative; width: 100%; height: 104px; }
.enm-fan svg { position: absolute; inset: 0; width: 100%; height: 98px; overflow: visible; filter: drop-shadow(0 0 5px var(--teal-dark)); }
.enm-wire { fill: none; stroke: var(--hue); stroke-width: 2; stroke-linecap: round; opacity: 0.9; vector-effect: non-scaling-stroke; }
.enm-head {
  position: absolute; top: 90px; transform: translateX(-50%);
  width: 0; height: 0; border-left: 6px solid transparent; border-right: 6px solid transparent;
  border-top: 12px solid var(--hue);
}

.enm-places { list-style: none; margin: 0; padding: 0; width: 100%; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); }
.enm-place { position: relative; min-width: 0; padding: 0 var(--s3); display: grid; grid-template-rows: auto 1fr; }
.enm-branch { display: none; }
.enm .enm-ped { margin-bottom: -6px; }
.enm .enm-card { display: flex; flex-direction: column; padding: var(--s4); min-width: 0; }
.enm-label { margin: 0; font-family: inherit; font-size: 17px; line-height: 1.25; font-weight: 700; letter-spacing: normal; color: var(--ink); }
.enm-count { margin: var(--s2) 0 0; display: flex; align-items: baseline; gap: var(--s2); }
.enm-count-n { font-size: 34px; line-height: 1; font-weight: 700; letter-spacing: -0.02em; color: var(--hue); }
.enm-count-l { font-size: 15px; color: var(--ink-2); }
.enm-detail { margin: var(--s2) 0 0; font-size: 14px; line-height: 1.45; color: var(--ink-2); }
/* WHERE A CARD'S FACTS COME FROM, because they do not all come from one file. */
.enm-source { margin: var(--s2) 0 0; font-size: 14px; line-height: 1.45; font-style: italic; color: var(--ink-2); }
.enm-tok { display: inline-block; max-width: 100%; overflow-wrap: anywhere; }
.enm-group { margin-top: var(--s4); }
.enm-group-t { margin: 0 0 var(--s2); font-size: 14px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-row); }
.enm-group-n { color: var(--hue); }
.enm-chips { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.enm-chips li {
  padding: 2px var(--s2); border-radius: 6px;
  font-family: var(--mono); font-size: 14px; line-height: 1.5; color: var(--ink);
  border: 1px solid var(--hairline); border-left: 2px solid var(--hue); background: var(--paper);
}
.enm-rows { margin: var(--s4) 0 0; display: grid; gap: var(--s3); }
.enm-rows > div { display: grid; gap: 2px; padding-left: var(--s3); border-left: 2px solid var(--hue); }
.enm-rows dt { font-size: 14px; font-weight: 600; color: var(--ink-row); }
.enm-rows dd { margin: 0; font-family: var(--mono); font-size: 14px; line-height: 1.4; color: var(--ink); overflow-wrap: normal; }
.enm-drive { margin: auto 0 0; padding-top: var(--s4); display: grid; gap: 4px; font-size: 14px; color: var(--ink-2); }
.enm-drive code { font-family: var(--mono); font-size: 14px; color: var(--ink); }
.enm-drive-l { font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--hue); }
.enm-caption { margin: var(--s5) 0 0; font-size: 14px; color: var(--ink-2); text-align: center; }

/* THE NARROW MAP: the fan becomes a spine. Below 1340 four columns leave a card under 290px, where
   a tenant host broke over three lines; so the places stack and one wire runs down their left with a
   branch to each pedestal. Measured by a reviewer on 29 September 2026: three lines at 1100 to 1280. */
@media (max-width: 1339px) {
  .enm { justify-items: stretch; }
  .enm .enm-hub { width: 100%; }
  .enm-fan { display: none; }
  .enm-places { grid-template-columns: minmax(0, 1fr); row-gap: var(--s5); padding-left: 28px; margin-top: var(--s5); }
  .enm-place { grid-template-columns: 96px minmax(0, 1fr); grid-template-rows: auto; align-items: start; }
  .enm-place::before {
    content: ""; position: absolute; left: -19px; width: 2px; top: calc(-1 * var(--s5)); bottom: 0;
    background: var(--teal-dark); box-shadow: 0 0 6px var(--teal-dark);
  }
  .enm-place:last-child::before { bottom: auto; height: calc(var(--s5) + 45px); }
  .enm-branch {
    display: block; position: absolute; top: 44px; left: -18px; width: calc(18px + var(--s3));
    height: 2px; background: var(--hue);
  }
  .enm-branch::after {
    content: ""; position: absolute; right: -2px; top: -5px;
    border-top: 6px solid transparent; border-bottom: 6px solid transparent; border-left: 10px solid var(--hue);
  }
  .enm .enm-ped { margin: var(--s2) 0 0; }
}
@media (max-width: 700px) {
  .enm-place { grid-template-columns: minmax(0, 1fr); }
  .enm .enm-ped { display: none; }
  .enm-branch { top: 26px; }
  .enm .enm-card { border-top-width: 2px; }
}

/* ---- THE PATH ---- */
.enm-path { position: relative; margin: var(--s5) 0 0; min-width: 0; }
.enm-track { position: relative; }
.enm-tag { margin: 0; font-size: 14px; line-height: 1.4; font-style: italic; color: var(--ink-2); }
/* THE RAIL runs through the centres of the seven nodes: from the first centre to the last, which is
   half a column in from each edge. */
.enm-rail {
  position: absolute; top: 19px; left: calc(50% / var(--stops)); right: calc(50% / var(--stops)); height: 2px;
  background: var(--teal-dark); box-shadow: 0 0 8px var(--teal-dark); overflow: hidden;
}
.enm-rail-pulse { position: absolute; top: -2px; left: 0; width: 60px; height: 6px; border-radius: 3px; background: var(--brand-strong); opacity: 0; }
.enm-stops { position: relative; list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(var(--stops), minmax(0, 1fr)); }
.enm-stop { min-width: 0; padding: 0 var(--s2); display: grid; justify-items: center; align-content: start; text-align: center; }
.enm-node {
  width: 40px; height: 40px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center;
  font-size: 16px; font-weight: 700; color: var(--brand-strong);
  border: 2px solid var(--brand-strong); background: var(--paper);
  box-shadow: 0 0 16px var(--teal-dark);
}
.enm-stop-body { margin-top: var(--s3); display: grid; gap: var(--s2); }
.enm-where { margin: 0; font-family: inherit; font-size: 16px; line-height: 1.3; font-weight: 700; letter-spacing: normal; color: var(--ink); }
.enm-caught {
  margin: 0; padding: var(--s2) var(--s3); border-radius: 8px; text-align: left;
  font-size: 14px; line-height: 1.45; color: var(--ink-row);
  border: 1px solid var(--hairline); background: var(--paper-alt);
}
.enm-caught-l { display: block; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--brand-strong); }
.enm-sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; border: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
@media (prefers-reduced-motion: no-preference) {
  .enm-rail-pulse { animation: enm-travel 7s ease-in-out infinite 1s; }
}
@keyframes enm-travel {
  0% { opacity: 0; transform: translateX(-60px); }
  4% { opacity: 1; }
  46% { opacity: 1; }
  50%, 100% { opacity: 0; transform: translateX(1400px); }
}

/* THE NARROW PATH: the rail turns vertical down the left, and each stop's words sit beside its node. */
@media (max-width: 1099px) {
  .enm-rail { top: 20px; bottom: 20px; left: 19px; right: auto; width: 2px; height: auto; }
  .enm-rail-pulse { display: none; }
  .enm-stops { grid-template-columns: minmax(0, 1fr); row-gap: var(--s5); }
  .enm-stop { grid-template-columns: 40px minmax(0, 1fr); column-gap: var(--s4); justify-items: start; text-align: left; padding: 0; }
  .enm-stop-body { margin-top: 6px; }
}

/* ---- THE STEPS ---- */
.enm-steps { margin-top: var(--s5); }
.enm-path .enm-drawer { margin-top: var(--s5); }
.enm-step-list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s4); counter-reset: none; }
.enm-step {
  position: relative; min-width: 0; display: grid; align-content: start; gap: var(--s2);
  padding: var(--s4); border-radius: 12px;
  border: 1px solid var(--hairline); border-top: 2px solid var(--hue, var(--rule));
  background: linear-gradient(180deg, var(--paper-alt) 0%, var(--paper) 100%);
}
.enm-step-head { margin: 0; display: flex; align-items: center; gap: var(--s3); }
.enm-step-n {
  width: 30px; height: 30px; border-radius: 50%; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  font-size: 15px; font-weight: 700; color: var(--brand-strong); border: 1px solid var(--brand-strong);
}
.enm-step-label { font-size: 16px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.enm-step-place { margin: 0; display: flex; align-items: center; gap: var(--s2); font-size: 14px; font-weight: 600; color: var(--ink-row); }
.enm-step-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--hue); box-shadow: 0 0 8px var(--hue); }
.enm-cmd {
  margin: var(--s1, 4px) 0 0; padding: var(--s2) var(--s3); border-radius: 8px; overflow-x: auto;
  font-family: var(--mono); font-size: 14px; line-height: 1.45; color: var(--ink);
  border: 1px solid var(--hairline); background: var(--paper);
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.enm-drawer { margin-top: var(--s4); border-top: 1px solid var(--hairline); border-bottom: 1px solid var(--hairline); }
.enm-drawer > summary {
  display: flex; align-items: center; gap: var(--s3); padding: var(--s4) 0; cursor: pointer; list-style: none;
  font-size: 16px; font-weight: 600; color: var(--ink);
}
.enm-drawer > summary::-webkit-details-marker { display: none; }
.enm-drawer > summary::before {
  content: ""; width: 8px; height: 8px; flex: 0 0 auto;
  border-right: 2px solid var(--brand-strong); border-bottom: 2px solid var(--brand-strong);
  transform: rotate(-45deg); transition: transform 160ms ease;
}
.enm-drawer[open] > summary::before { transform: rotate(45deg); }
.enm-notes { margin: 0 0 var(--s4); padding-left: 1.4em; display: grid; gap: var(--s3); font-size: 15px; line-height: 1.55; color: var(--ink-row); max-width: 80ch; }
.enm-notes-l { font-weight: 600; color: var(--ink); }
@media (max-width: 1099px) { .enm-step-list { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px) { .enm-step-list { grid-template-columns: minmax(0, 1fr); } }
@media (prefers-reduced-motion: reduce) { .enm-drawer > summary::before { transition: none; } }

/* ---- src/parts/estate-page.css ---- */
/* The Estate index, rebuilt against the Raidiam Agents reference route /evidence.
   View: apps/site/src/views/estate/index.ejs.

   WHY THIS FILE EXISTS BESIDE estate.css. estate.css carries the whole explorer: the status strip,
   the figure, the record pages and the change record. This file carries the INDEX only, and every
   rule in it is scoped under .estp, which the index wraps itself in and no other view writes. So a
   change here cannot reach /estate/reachability, /estate/audit or an entity page.

   IT ALSO HAS TO OUTRANK estate.css RATHER THAN FOLLOW IT. packages/ui/tools/build.mjs concatenates
   src/parts in sorted order, and "estate-page.css" sorts BEFORE "estate.css" because a hyphen is
   lower than a full stop. So a rule here at the same specificity would lose. The .estp prefix is
   what makes every rule below win: one extra class beats the bare .ex-* rule in every case,
   including inside a media query, which is why the widths at the foot restate the index's
   responsive behaviour rather than letting estate.css supply it.

   WHAT THE REFERENCE GIVES THIS PAGE. Its /evidence route is one full bleed opening band carrying a
   faint rule grid, a kicker over a display statement, and the instrument itself inside a bordered
   panel with a wide radius and an accent ring. Under it, panels on the page ground with a hairline
   between bands. That is the language. None of its copy is here.

   WHAT THE REFERENCE DOES NOT GIVE IT. The reference names no runtime and makes no evidence claim,
   so it carries no treatment legend and no evidence legend. Both survive: the figure key names four
   treatments beside the bars it draws, and the footer carries all five labels with the third party
   note and all four evidence labels. Green appears under Observed and nowhere else. */

.estp { display: block; }

/* ---- the opening band -------------------------------------------------------

   FULL BLEED, so the grid and the closing hairline reach the window edge. The section sits outside
   the page wrap and carries its own wrap inside, which is the shape the reference uses and the
   shape the home page hero already has here.

   THE GRID IS A GRADIENT, so it may hold a colour-mix. packages/ui/tests/stylesheet.test.ts refuses
   a mix in a FLAT background, because packages/ui/tools/contrast.mjs names token pairs and can see
   nothing inside a mix. No text lands on this layer. */

.estp .estp-hero {
  position: relative;
  overflow: hidden;
  padding-block: calc(var(--s8) + var(--s4)) var(--s8);
  border-bottom: 1px solid var(--rule);
}
.estp .estp-hero-grid {
  position: absolute; inset: 0;
  pointer-events: none;
  background-image:
    linear-gradient(to right, color-mix(in srgb, var(--ink) 7%, transparent) 1px, transparent 1px),
    linear-gradient(to bottom, color-mix(in srgb, var(--ink) 7%, transparent) 1px, transparent 1px);
  background-size: 44px 44px;
  -webkit-mask-image: radial-gradient(ellipse 120% 100% at 50% 0%, var(--ink), transparent 75%);
  mask-image: radial-gradient(ellipse 120% 100% at 50% 0%, var(--ink), transparent 75%);
}
.estp .estp-hero-in { position: relative; }
.estp .estp-hero-copy { max-width: 56rem; }
.estp .estp-hero-copy .eyebrow { letter-spacing: 0.3em; margin-bottom: var(--s4); }
.estp .estp-hero-copy .t-display { margin: 0 0 var(--s5); }
.estp .estp-lead { max-width: var(--measure-body); color: var(--ink-2); margin: 0 0 var(--s6); }
.estp .estp-hero-copy .actions { margin: 0; }

/* ---- the counts ---------------------------------------------------------------

   ONE PANEL, FIVE CELLS, HAIRLINES BETWEEN THEM, rather than five separate cards. The reference
   draws its decoded claims as rows inside a single rounded border, and the counts are the same kind
   of thing: one reading, read across, not five unrelated facts. Five cards beside a title is what
   this page had, and at 1440 it squeezed a 24 character caption into a 230 pixel column.

   NO CELL CARRIES A STATE COLOUR ANY MORE, AND THAT IS THE FIX FOR THIS PAGE. The row used to paint
   the withdrawn count red and the failed read count amber. Four business reviewers read the result
   as an outage, and /architecture links here as "The live estate", so a prospect who clicked through
   concluded the product was down.

   Both numbers were true. Neither is a fault. "Withdrawn" here means an entity the declaration names
   that no authority lists, which is a real gap in the tenant and stays on the page in those words. A
   failed read is a diagnostic about one endpoint, not about the estate. Red is the page telling a
   buyer that a true, expected number is an emergency, so the red goes and the label carries the
   meaning instead.

   The cell grounds alternate by column so the panel reads as a grid rather than as a flat block. */

.estp .estp-tiles {
  list-style: none; margin: var(--s7) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
  overflow: hidden;
}
.estp .estp-tiles .ex-tile {
  display: grid; grid-template-columns: minmax(0, 1fr); align-content: start; gap: var(--s2);
  min-width: 0;
  padding: var(--s5);
  background: var(--white);
  border: 0;
  border-radius: 0;
}
.estp .estp-tiles .ex-tile:nth-child(2n) { background: var(--paper-alt); }
.estp .estp-tiles .ex-tile .n {
  font-family: var(--display);
  font-size: var(--t-h1); line-height: 1.02; font-weight: var(--t-h1-weight);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.estp .estp-tiles .ex-tile .k {
  font-size: var(--t-label); line-height: 1.4;
  letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--ink-2);
}
/* ---- the reading this page does not have -----------------------------------------

   WHEN NO AUTHORITY ANSWERED, NO NUMBER IS DRAWN AT ALL. The count row used to render six zeros in
   that state, and a zero is a number: "0 entities drawn" reads as an estate with nothing in it
   rather than as a page that has read nothing. Two of the four reviewers met exactly that and
   reported the product as down. The view swaps the whole row for this block, so an unread value
   never reaches the page wearing the shape of a count.

   THE DISCIPLINE THE COPY USED TO EXPLAIN, KEPT HERE WHERE IT BELONGS. An estate held on screen
   after it stopped being read is the one thing this page must never show, so nothing is cached
   forward and no last good reading is drawn. That is a rule for us. A buyer needs the consequence,
   which is one sentence saying the page holds no reading, and not the reasoning behind it.

   It takes the panel shape of the count row rather than a warning shape. The page is working; it
   has nothing to report yet.

   IT IS NOW THE ONLY PLACE THE ROUTE SAYS SO, so it is built like a cell of the count row rather
   than like a note. The label takes the position and the type of a count's caption and the sentence
   takes the position of the number, which is what makes the panel read as the count row answering
   instead of as a paragraph left behind where an instrument failed to load. */

.estp .estp-unread {
  margin: var(--s7) 0 0;
  display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s3);
  padding: var(--s6) var(--s5);
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
}
.estp .estp-unread p { margin: 0; max-width: var(--measure-notes); color: var(--ink-2); }
.estp .estp-unread .estp-unread-e {
  font-size: var(--t-label); line-height: 1.4;
  letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--ink-2);
}

/* ---- the bands under it -------------------------------------------------------

   A hairline between bands and nothing else. The reference separates its sections with
   `border-b border-border/60` and no change of ground, so a page reads as one surface with rules
   across it rather than as a stack of stripes. */

.estp .estp-band { padding-block: var(--s8); }
.estp .estp-band + .estp-band { border-top: 1px solid var(--rule); }
.estp .estp-head { max-width: var(--measure-notes); margin-bottom: var(--s6); }
.estp .estp-head .t-h2 { margin: 0 0 var(--s3); }
.estp .estp-head p { margin: 0; }

/* ---- the figure panel ---------------------------------------------------------

   THE ACCENT RING IS THE REFERENCE'S ONE LIT PANEL. It draws exactly one instrument per page inside
   a ring of its action colour, and this figure is this page's instrument. The ring is two shadows,
   a hairline and a wide soft bloom, so no text sits on either and the panel's own ground stays a
   plain token the contrast gate can name.

   The panel is wider than estate.css leaves it. That file caps it at 960 to stop a 900 unit drawing
   floating in a 1344 pixel column; the cap stays, and the panel around it now fills the column, so
   the drawing is centred inside a panel the width of the page rather than pinned left. */

.estp .ex-figure-wrap { padding-block: 0; }
.estp .ex-graph {
  margin: 0; max-width: none;
  padding: var(--s7) var(--s6);
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--teal-deep) 35%, transparent),
    0 0 40px -8px color-mix(in srgb, var(--teal-deep) 45%, transparent);
}
/* 1060 rather than estate.css's 900. The drawing's coordinates are user units and a unit was a
   pixel at 900, so this scales it by 1.18: a box is 52 pixels tall and its name is 15. That file's
   warning is about 1.46, where a box becomes a banner, and about stretching to the full 1344 of the
   page. Held below both, and the panel around it stays the width of the column. */
.estp .ex-graph svg { width: min(100%, 1060px); }
.estp .ex-graph .ex-key {
  margin-top: var(--s6); padding-top: var(--s5);
  border-top: 1px solid var(--rule);
}
.estp .ex-graph .ex-key-item { font-size: var(--t-label); }
.estp .ex-graph-note { margin-top: var(--s5); }

/* The boxes. The reference's panels sit one step above the ground they are on, so a node inside a
   card takes the page ground rather than the alternate band, which is what put a near flat box on a
   near flat card. */
.estp .ex-graph svg .ex-node-box { fill: var(--paper); stroke: var(--rule); }
.estp .ex-graph svg .ex-node:hover .ex-node-box,
.estp .ex-graph svg .ex-node:focus-visible .ex-node-box { stroke: var(--teal-deep); stroke-width: 2; }

/* ---- the reconciliation line --------------------------------------------------

   It is the sentence that says the figure and the declaration agree, so it reads as a standing note
   rather than as body copy: a rule down its left edge, the counts inside it lifted to the action
   colour, the rest at reading size. */

.estp .estp-reconcile {
  padding-block: 0;
  margin-bottom: var(--s7);
}
.estp .estp-reconcile p {
  max-width: var(--measure-notes);
  padding-left: var(--s5);
  border-left: 2px solid var(--rule);
}
.estp .estp-reconcile p + p { margin-top: var(--s4); }
.estp .estp-reconcile [data-count-of] { color: var(--teal-dark); font-variant-numeric: tabular-nums; }

/* ---- the record ----------------------------------------------------------------

   THE ROWS ARE THE REFERENCE'S DECODED CLAIMS. It draws them as a single rounded bordered block of
   rows with alternating grounds, a monospaced key in the action colour and a monospaced value in the
   reading colour. This record has one more column than that, the lifecycle word, and otherwise it is
   the same object: a dense list of identifiers somebody reads down.

   The group heading sits OUTSIDE the block rather than as its first row, because a heading inside a
   striped list reads as one of the rows. */

/* THE RECORD SITS BEHIND ONE PRESS, and the press has to look like the page's own disclosure rather
   than like a control that hides the estate. It takes the drawer border and radius the diagnostics
   drawer at the foot already has, so a reader meets one kind of disclosure on this page and not two.

   THE GROUPS INSIDE IT KEEP THEIR GRID. .ex-groups is the wrapper the details now lives in, so the
   stacking of the eight groups moves onto the details body. Without this the groups collapse to the
   flow default and the spacing between Anchors and Authorities disappears. */

.estp .ex-record {
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
  padding: var(--s4) var(--s5);
}
.estp .ex-record > .body { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s7); margin-top: var(--s5); }
.estp .ex-groups { display: block; padding-bottom: 0; }
.estp .ex-group > .t-h3 {
  display: flex; align-items: baseline; gap: var(--s3);
  padding-bottom: 0; margin: 0 0 var(--s4);
  border-bottom: 0;
}
.estp .ex-group-n {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 26px; height: 22px; padding: 0 8px;
  border: 1px solid var(--rule); border-radius: var(--pill);
  font-family: var(--sans); font-size: var(--t-label); font-weight: var(--t-label-weight);
  color: var(--ink-2); font-variant-numeric: tabular-nums;
}
.estp .ex-rows {
  list-style: none; margin: 0; padding: 0;
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
  overflow: hidden;
}
.estp .ex-row {
  display: grid;
  grid-template-columns: minmax(0, 22rem) minmax(0, 1fr) max-content;
  align-items: center; gap: var(--s2) var(--s5);
  padding: var(--s4) var(--s5);
  border: 0; border-radius: 0;
  background: var(--white);
}
.estp .ex-row:nth-child(2n) { background: var(--paper-alt); }
.estp .ex-row + .ex-row { border-top: 1px solid var(--rule); }
.estp .ex-row:hover { background: var(--wash-teal); }
.estp .ex-row-id { font-size: var(--t-label); }
.estp .ex-row-id .ex-path { color: var(--teal-dark); }
.estp .ex-row-open .treat .label { font-family: var(--display); }

/* ---- the disclosure -------------------------------------------------------------

   The reads that did not answer are a diagnostic, so they keep the quietest treatment on the page:
   a bordered panel with no fill, under everything the page states as fact. */

.estp .ex-drawer {
  padding-bottom: 0;
  margin-top: var(--s7);
}
.estp .ex-drawer .drawer {
  padding: var(--s4) var(--s5);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
}

/* ---- widths ---------------------------------------------------------------------

   estate.css moves .ex-tiles and .ex-row at three widths, and every one of those rules is a single
   class, so nothing there can reach past the .estp selectors above. The index restates its own
   behaviour at the same three widths rather than inheriting it. */

@media (max-width: 1080px) {
  /* THE LAST CELL SPANS THE GAP. Five cells in three columns leaves one empty grid area, and the
     gap here is the rule colour showing through, so an empty area draws as a dark block rather than
     as nothing. The fifth cell takes the spare column instead. It is the count of entities held
     under two governance records, which is the one this estate exists to demonstrate, so the extra
     width lands on the right cell. */
  .estp .estp-tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .estp .estp-tiles .ex-tile:last-child { grid-column: span 2; }
  .estp .estp-hero { padding-block: var(--s8) var(--s7); }
}

@media (max-width: 900px) {
  .estp .ex-graph { display: none; }
  .estp .ex-graph-note { display: block; }
  .estp .ex-row { grid-template-columns: minmax(0, 1fr) max-content; }
  .estp .ex-row-id { grid-column: 1 / -1; }
}

@media (max-width: 620px) {
  .estp .estp-hero { padding-block: var(--s7) var(--s6); }
  .estp .estp-band { padding-block: var(--s7); }
  .estp .estp-tiles { grid-template-columns: minmax(0, 1fr); }
  .estp .estp-tiles .ex-tile:last-child { grid-column: auto; }
  .estp .estp-tiles .ex-tile { padding: var(--s4); }
  .estp .ex-row { grid-template-columns: minmax(0, 1fr); padding-inline: var(--s4); }
  .estp .ex-row-state { justify-self: start; }
  .estp .estp-reconcile p { padding-left: var(--s4); }
}

/* ---- reduced motion --------------------------------------------------------------

   The index adds one transition of its own, the row ground on hover. estate.css already stops the
   figure, the live dot and the picker; this stops the row here so the index does not reintroduce
   motion the shared sheet removed. */

@media (prefers-reduced-motion: reduce) {
  .estp .ex-row { transition: none !important; }
}

/* ---- src/parts/estate.css ---- */
/* The Estate explorer. Views: apps/site/src/views/estate/*.ejs.

   THE EXPLORER IS THE ONLY SURFACE ON THIS SITE THAT READS AT REQUEST TIME. Everything else is
   content. So the job of this sheet is to make a live console look like one: a status strip in the
   chrome, counts that came off the reading, a figure of the estate, and a record under it. The
   words are the views' and the logic is the explorer package's. Nothing here invents a value.

   WHAT IS DELIBERATELY NOT HERE.

   No layout animation. The figure's coordinates are computed on the server and written into the
   SVG, so there is nothing for a script to settle and nothing to stop under reduced motion except
   the hover transitions and the one live dot, which the block at the foot of this file stops.

   No colour as the only channel. A withdrawn box carries the word "withdrawn" as well as the red
   edge, and a treatment carries its label in the key as well as its bar.

   No colour-mix in a flat background. contrast.mjs gates token pairs by name and cannot see a mix,
   so text over one is gated by nothing. Every ground under a word here is a plain token.

   WHAT HAPPENS AT 390. The figure is 900 user units wide and its boxes carry twenty seven character
   names. Scaled to a phone those names are four pixels tall, which is a picture of a graph rather
   than a graph, so below 900 the figure is not drawn and the note beside it says so. Nothing is
   lost: the table under it carries every entity, every identifier and every lifecycle word, and it
   is the same markup at every width. The figure never scrolls sideways because it never exists at a
   width where it would have to. */

/* ---- the status strip -------------------------------------------------------

   The read line used to be the first content on the page, at body size, above the title. It is a
   diagnostic and it belongs in the chrome. Every word of it survives here, and a stale read turns
   the strip, so the demotion costs nothing at the moment the warning matters. */

.ex-bar {
  background: var(--paper-alt);
  border-bottom: 1px solid var(--rule);
}
.ex-bar-row {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--s3) var(--s5);
  padding-block: var(--s3);
}
.ex-read {
  display: inline-flex; align-items: center; flex-wrap: wrap; gap: var(--s2) var(--s3);
  font-size: var(--t-small); color: var(--ink-2);
  margin: 0;
}
.ex-read .mono { color: var(--ink); }
.ex-read .ev { font-size: var(--t-label); }
.ex-dot {
  flex: none; width: 8px; height: 8px; border-radius: var(--pill);
  background: var(--ink-2);
  animation: ex-pulse 2400ms ease-in-out infinite;
}
@keyframes ex-pulse { 0%, 100% { opacity: 0.35; } 50% { opacity: 1; } }
.ex-bar.is-stale { background: var(--wash-att); border-bottom-color: var(--att); }
.ex-bar.is-stale .ex-read { color: var(--att); }
.ex-bar.is-stale .ex-read .mono { color: var(--att); }
.ex-bar.is-stale .ex-dot { background: var(--att); }
.ex-bar[data-answered="no"] { background: var(--wash-no); border-bottom-color: var(--no); }
.ex-bar[data-answered="no"] .ex-read { color: var(--no); }
.ex-bar[data-answered="no"] .ex-dot { background: var(--no); animation: none; }

/* ---- the head: the title beside the counts --------------------------------- */

.ex-top {
  display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  gap: var(--s7) var(--s8); align-items: start;
  padding-block: var(--s8) var(--s7);
}
.ex-title .t-display { margin-bottom: var(--s4); max-width: var(--measure-display); }
.ex-lead { max-width: var(--measure-body); color: var(--ink-2); margin-bottom: var(--s5); }

.ex-tiles {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s3);
}
.ex-tile {
  display: grid; grid-template-columns: minmax(0, 1fr); align-content: start; gap: var(--s1); min-width: 0;
  padding: var(--s4);
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
}
.ex-tile .n {
  font-size: var(--t-h2); line-height: 1.05; font-weight: var(--t-h2-weight);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.ex-tile .k { font-size: var(--t-label); line-height: 1.35; color: var(--ink-2); }
.ex-tile[data-state="no"] .n { color: var(--no); }
.ex-tile[data-state="att"] .n { color: var(--att); }

/* ---- the figure ------------------------------------------------------------- */

.ex-figure-wrap { padding-block: 0 var(--s7); }
.ex-figure-head { max-width: var(--measure-notes); margin-bottom: var(--s5); }
.ex-figure-head .t-h3 { margin-bottom: var(--s2); }

.ex-graph {
  /* The card hugs the figure. Left to run the full 1344 of the page it framed a 900 unit drawing in
     220 pixels of nothing on each side, which reads as a figure that failed to load rather than as
     one that is the size it wants to be. */
  margin: 0; max-width: 960px;
  padding: var(--s5) var(--s4);
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
  box-shadow: var(--shadow-lift);
}
.ex-graph svg { display: block; width: min(100%, 900px); height: auto; margin-inline: auto; }
/* THE FIGURE IS DRAWN AT ITS NATURAL SIZE, not stretched to the page. The view box is 900 units
   wide and a unit is a pixel, so a box is 44 pixels tall and its name is 13 pixels, which is what
   the geometry was laid out for. Left to fill a 1344 pixel column the same figure scales by 1.46
   and every box becomes a banner. */

.ex-graph svg .ex-edge {
  stroke: var(--rule); stroke-width: 1.5; fill: none;
}
/* The one line that leaves the domain of the authority governing most of this estate. It is the
   two domain story in a single stroke, so it is drawn heavier and in the graphic accent rather than
   left to be found among nine identical greys. */
.ex-graph svg .ex-edge.is-cross { stroke: var(--teal-mid); stroke-width: 2.5; }

.ex-graph svg text.ex-head-label {
  fill: var(--ink-2); font-family: var(--sans); font-size: 12px; font-weight: 600;
  letter-spacing: 0.12em; text-transform: uppercase;
}

.ex-graph svg .ex-detach line { stroke: var(--rule); stroke-width: 1; stroke-dasharray: 4 5; }
.ex-graph svg text.ex-detach-label,
.ex-graph svg .ex-detach text {
  fill: var(--ink-2); font-family: var(--sans); font-size: 12px; letter-spacing: 0.06em; text-transform: uppercase;
}

.ex-graph svg .ex-node { cursor: pointer; }
.ex-graph svg .ex-node-box {
  fill: var(--paper-alt); stroke: var(--rule); stroke-width: 1;
  transition: stroke var(--m-drawer) ease, fill var(--m-drawer) ease;
}
.ex-graph svg .ex-node-bar { fill: var(--bound); }
.ex-graph svg text.ex-node-name {
  fill: var(--ink); font-family: var(--sans); font-size: 13px; font-weight: 600;
}
.ex-graph svg text.ex-node-sub {
  fill: var(--ink-2); font-family: var(--sans); font-size: 12px;
}
.ex-graph svg .ex-node:hover .ex-node-box,
.ex-graph svg .ex-node:focus-visible .ex-node-box { stroke: var(--teal-deep); stroke-width: 2; }

/* The treatment bars. Only a Raidiam product is teal, which is the whole reason the bar exists
   rather than the box being filled: a filled box in the brand colour would say Raidiam runs the
   entity, and nine of these fifteen entities belong to somebody else. */
.ex-graph svg .ex-node[data-treat="product"] .ex-node-bar { fill: var(--teal); }
.ex-graph svg .ex-node[data-treat="customer"] .ex-node-bar { fill: var(--ink); }
.ex-graph svg .ex-node[data-treat="reference"] .ex-node-bar { fill: var(--bound); }
.ex-graph svg .ex-node[data-treat="third"] .ex-node-bar { fill: var(--ink-2); }
.ex-graph svg .ex-node[data-treat="third"] .ex-node-box { stroke-dasharray: 5 4; }

/* Withdrawn: declared, and no superior lists it. Drawn with no line into it and a red edge, and the
   word "withdrawn" is written in the box, because the edge alone is colour as the only channel. */
.ex-graph svg .ex-node[data-state="no"] .ex-node-box { stroke: var(--no); stroke-dasharray: 3 4; }
.ex-graph svg .ex-node[data-state="no"] text.ex-node-sub { fill: var(--no); }

/* The key sits inside the card, under the drawing. A hierarchy with one wide fan-out leaves a
   quarter of its box empty on the shallow side, and a key floating outside the card left that
   emptiness reading as a figure that failed rather than as a figure with a legend. */
.ex-key {
  list-style: none; margin: var(--s5) 0 0; padding: var(--s4) 0 0;
  border-top: 1px solid var(--rule);
  display: flex; flex-wrap: wrap; gap: var(--s2) var(--s5);
  font-size: var(--t-label); color: var(--ink-2);
}
.ex-key-item { display: inline-flex; align-items: center; gap: var(--s2); }
.ex-key-item .bar { flex: none; width: 4px; height: 16px; border-radius: 2px; background: var(--bound); }
.ex-key-item[data-treat="product"] .bar { background: var(--teal); }
.ex-key-item[data-treat="customer"] .bar { background: var(--ink); }
.ex-key-item[data-treat="third"] .bar { background: var(--ink-2); }
.ex-key-item .edge { flex: none; width: 26px; height: 0; border-top: 1.5px solid var(--rule); }
.ex-key-item .edge.is-cross { border-top: 2.5px solid var(--teal-mid); }

/* Two sentences that swap with the figure. At a width where no box is drawn, an instruction to
   select a box names something that is not on the screen. */
.ex-graph-note { display: none; max-width: var(--measure-notes); }
.ex-graph-only { display: inline; }

/* ---- the reconciliation line and the record ---------------------------------- */

.ex-reconcile { padding-block: 0 var(--s6); }
.ex-reconcile p { max-width: var(--measure-notes); }
.ex-reconcile p + p { margin-top: var(--s3); }
.ex-reconcile [data-count-of] { font-weight: 600; color: var(--ink); }

.ex-groups { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s6); padding-bottom: var(--s7); }
.ex-group > .t-h3 {
  display: flex; align-items: baseline; gap: var(--s3);
  padding-bottom: var(--s3); margin-bottom: var(--s2);
  border-bottom: 1px solid var(--rule);
}
.ex-group-n {
  font-size: var(--t-label); font-weight: 400; color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.ex-rows { list-style: none; margin: 0; padding: 0; }

.ex-row {
  display: grid;
  grid-template-columns: minmax(0, 20rem) minmax(0, 1fr) max-content;
  align-items: center; gap: var(--s2) var(--s5);
  padding: var(--s3) var(--s4);
  border-radius: var(--r-2);
  border: 1px solid transparent;
  transition: background var(--m-drawer) ease, border-color var(--m-drawer) ease;
}
.ex-row + .ex-row { border-top-color: var(--rule); }
.ex-row:hover { background: var(--white); border-color: var(--rule); }
.ex-row-open { text-decoration: none; min-width: 0; }
.ex-row-open:hover { text-decoration: underline; }
.ex-row-open .treat .label { color: var(--ink); font-weight: 600; }
.ex-row-open:hover .treat .label { color: var(--teal-dark); }
/* The identifier, whole, with the host graded back. Every character of the value a consumer pins is
   printed: the host is what a reader recognises and the path is what tells two entities on the same
   host apart, so the path carries the reading colour and the host does not. Nothing is elided. */
.ex-row-id { min-width: 0; overflow-wrap: anywhere; line-height: 1.45; }
.ex-row-id .ex-host { color: var(--ink-2); }
.ex-row-id .ex-path { color: var(--ink); }

/* The treatment swatch, its label and, where the treatment demands one, its note. The note is a
   sentence rather than a word, so the row lets it wrap under the name instead of squeezing the name
   into a column one word wide, which is what it did. */
.ex-row-open .treat { display: inline-flex; flex-wrap: wrap; align-items: baseline; gap: var(--s1) var(--s2); }
.ex-row-open .treat .note { flex-basis: 100%; padding-left: var(--s4); font-size: var(--t-label); color: var(--ink-2); }
.ex-row-state { justify-self: end; }
.ex-row-note { grid-column: 1 / -1; }

/* The endpoints inside the disclosure wrap too. A closed details element does not grow the page, so
   the reads that did not answer measured clean at 390 while holding a 700 pixel line: the overflow
   arrived only when a reader opened it, which is the one state nothing was measuring. */
.ex-drawer { padding-bottom: var(--s7); }
.ex-drawer .mono, .ex-drawer li { overflow-wrap: anywhere; }
.ex-drawer ul { padding-left: 1.2em; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s2); }

/* ---- the record pages: one entity, the chain, reachability, the change record ---- */

.ex-page-head { padding-block: var(--s7) var(--s5); }
/* THE HEADING CAN BE AN IDENTIFIER, so it breaks where it must. When an entity's host does not
   answer there is no name to show and the page falls back to the entity's own federation
   identifier, which is a URL and has no space in it. At 390 wide that put a 603 px unbroken token
   in a 350 px column and took the document to 623. Nothing had seen it: the page only renders that
   way when a host is down, and no harness had ever taken a reading with one down. */
.ex-page-head .t-display, .ex-page-head .t-h1 { max-width: var(--measure-display); margin-block: var(--s3) var(--s4); overflow-wrap: anywhere; }
.ex-page-head .ex-lead { margin-bottom: var(--s5); }

/* The identity card: the treatment, the name, the identifier a consumer pins, and the lifecycle.
   The identifier is the value the whole page hangs from, so it is set at reading size rather than
   dropped to a caption, and it wraps rather than being cut. */
.ex-ident {
  display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s3); justify-items: start;
  padding: var(--s5);
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
  box-shadow: var(--shadow-lift);
  margin-bottom: var(--s5);
}
.ex-ident .ex-ident-name { margin: 0; }
.ex-ident .ex-ident-id {
  width: 100%; margin: 0; padding: var(--s3) var(--s4);
  background: var(--paper-alt); border-radius: var(--r-2);
  color: var(--ink); overflow-wrap: anywhere;
}
.ex-ident-meta { display: flex; flex-wrap: wrap; gap: var(--s3) var(--s5); align-items: center; }

/* The facts grid: one claim per cell, the value under the word. Replaces four paragraphs that each
   restated a URL. */
.ex-facts {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--s4);
  margin: 0;
}
.ex-fact {
  display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s1); align-content: start; min-width: 0;
  padding: var(--s4);
  background: var(--white); border: 1px solid var(--rule); border-radius: var(--r-2);
}
.ex-fact .h {
  font-size: var(--t-label); font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--ink-2);
}
.ex-fact .v { font-size: var(--t-small); color: var(--ink); overflow-wrap: anywhere; }
.ex-fact .v .mono { overflow-wrap: anywhere; }

/* Marks. Five of these used to print the same hundred character issuer URL five times, so the one
   thing that differed between the rows was the tail of the third line. The role is the heading, the
   full type stays under it, and the issuer is named once above the list. */
.ex-marks { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s2); }
.ex-mark {
  display: grid; grid-template-columns: minmax(0, 1fr) max-content max-content;
  align-items: center; gap: var(--s2) var(--s4);
  padding: var(--s3) var(--s4);
  background: var(--white); border: 1px solid var(--rule); border-radius: var(--r-2);
}
.ex-mark .role { font-weight: 600; color: var(--ink); overflow-wrap: anywhere; }
.ex-mark .type { grid-column: 1 / -1; color: var(--ink-2); overflow-wrap: anywhere; }

/* The consumer picker on the chain view. A row of choices where exactly one is current, rather than
   seven identical buttons where nothing says which one was walked. */
.ex-picker { display: flex; flex-wrap: wrap; gap: var(--s2); align-items: center; }
.ex-picker-label { font-size: var(--t-label); font-weight: 600; color: var(--ink-2); margin-right: var(--s2); }
.ex-picker a {
  display: inline-flex; align-items: center; min-height: 36px; padding: 0 var(--s4);
  border: 1px solid var(--rule); border-radius: var(--pill);
  font-size: var(--t-label); font-weight: 600; text-decoration: none; color: var(--ink-2);
  transition: border-color var(--m-drawer) ease, color var(--m-drawer) ease;
}
.ex-picker a:hover { color: var(--teal-dark); border-color: var(--teal-deep); }
.ex-picker a[aria-current] { color: var(--teal-dark); border-color: var(--teal-deep); background: var(--wash-teal); }

.ex-panel {
  min-width: 0; padding: var(--s5);
  background: var(--white); border: 1px solid var(--rule); border-radius: var(--r-3);
  box-shadow: var(--shadow-lift);
}
.ex-panel + .ex-panel { margin-top: var(--s5); }
.ex-panel > .t-h3 { margin-bottom: var(--s2); }
.ex-panel .ex-anchor-id { margin-bottom: var(--s4); color: var(--ink-2); overflow-wrap: anywhere; }

/* An empty result. A table head with no rows under it reads as a page that failed rather than as an
   answer, and on this surface the answer "the documents permit nothing" is a real one. */
.ex-none {
  padding: var(--s5);
  background: var(--paper-alt); border: 1px dashed var(--rule); border-radius: var(--r-2);
  color: var(--ink-2); max-width: var(--measure-notes);
}

/* EVERY GRID HERE DECLARES minmax(0, 1fr), and the reason is worth the line. A grid with no
   template has one implicit column of `auto`, which is max-content, so a wide table inside it does
   not shrink and does not scroll: it widens the grid, then the page, and the masthead and the
   footer end short of the right edge while the body scrolls sideways. Measured on the chain view,
   which carries a seven column table of hundred character URLs: the document came out 3042 pixels
   wide in a 1440 viewport. The .table-scroll wrapper was already there and could do nothing,
   because its max-width: 100% resolved against a column that had already grown. */
.ex-section { padding-bottom: var(--s7); display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s5); }

/* The caveats under a computed view. They are not decoration: each one names something the view
   does not check, and a reader who skips them reads an edge as more than it is. Listed rather than
   run together as three grey paragraphs, so each is a separate thing to have read. */
.ex-caveats {
  list-style: none; margin: 0; padding: 0; max-width: var(--measure-notes);
  display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s2);
  font-size: var(--t-small); color: var(--ink-2);
}
.ex-caveats li { padding-left: var(--s4); border-left: 2px solid var(--rule); }

.ex-reasons { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s3); }
.ex-reasons li { display: grid; grid-template-columns: minmax(0, 14rem) minmax(0, 1fr); gap: var(--s2) var(--s5); }
.ex-reason-name { font-weight: 600; color: var(--ink); }
.ex-reason-why { color: var(--ink-2); overflow-wrap: anywhere; }

.ex-path .trust-path { margin-block: var(--s5); }
.ex-none p + p { margin-top: var(--s3); }
.ex-none ul { margin: var(--s3) 0 0; padding-left: 1.2em; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s2); }
.ex-none ul li { overflow-wrap: anywhere; }
/* A hundred character identifier in a table cell or a paragraph breaks anywhere rather than pushing
   the page sideways. `code` already does this in the base sheet and `.mono` does not, which is why
   the record page was 583 pixels wide inside a 390 pixel phone. */
.ex-stack-wrap { padding-bottom: var(--s7); min-width: 0; }
.ex-stack-wrap .mono, .ex-stack-wrap td, .ex-stack-wrap h3, .ex-stack-wrap li, .ex-facts .mono, .ex-marks .mono { overflow-wrap: anywhere; }
.ex-stack-wrap .stack-layout, .ex-stack-wrap .stack, .ex-stack-wrap .stack > section { min-width: 0; }
.ex-facts dt, .ex-facts dd { margin: 0; }
.ex-facts .v a { overflow-wrap: anywhere; }
.ex-section .table-scroll, .ex-panel .table-scroll { max-width: 100%; min-width: 0; }

/* ---- widths ------------------------------------------------------------------ */

@media (max-width: 1080px) {
  .ex-top { grid-template-columns: minmax(0, 1fr); gap: var(--s6); }
  .ex-tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (max-width: 900px) {
  /* The figure is not drawn below this width. See the note at the head of this file: a 900 unit
     graph scaled to a phone is a picture of a graph. The table carries the same entities. */
  .ex-graph { display: none; }
  .ex-key { display: none; }
  .ex-graph-only { display: none; }
  .ex-graph-note { display: block; }
  .ex-row { grid-template-columns: minmax(0, 1fr) max-content; }
  .ex-row-id { grid-column: 1 / -1; }
}

@media (max-width: 760px) {
  .ex-reasons li { grid-template-columns: minmax(0, 1fr); gap: var(--s1); }
}

@media (max-width: 620px) {
  .ex-top { padding-block: var(--s6) var(--s5); }
  .ex-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ex-bar-row { justify-content: flex-start; }
  .ex-row { grid-template-columns: minmax(0, 1fr); padding-inline: 0; }
  .ex-row-state { justify-self: start; }
  .ex-mark { grid-template-columns: minmax(0, 1fr); }
  .ex-ident { padding: var(--s4); }
}

/* ---- reduced motion ------------------------------------------------------------

   ALL of it. The live dot is the only thing on these pages that moves on its own, and it is the
   thing this rule exists for: an indicator that pulses forever is exactly the kind of motion a
   reader with vestibular sensitivity asked to be rid of. Proved by consequence rather than by
   reading the rule: with the block removed, the computed animation-name of .ex-dot under an
   emulated reduce preference is ex-pulse; with it in place it is none. */

@media (prefers-reduced-motion: reduce) {
  .ex-dot,
  .ex-bar .ex-dot,
  .ex-graph svg .ex-node-box,
  .ex-row,
  .ex-picker a {
    animation: none !important;
    transition: none !important;
  }
}


/* ==================================================================================
   /estate WITHOUT THE EXPLORER. View: apps/site/src/views/estate.ejs.
   Partials: packages/ui/partials/ex-kinds.ejs and packages/ui/partials/ex-domains.ejs.

   WHY THIS BLOCK IS IN THIS FILE AND WHY IT CANNOT REACH ANYTHING ABOVE IT.
   apps/site/src/app.ts mounts the explorer's router before the site's own /estate handler, so the
   explorer answers that route wherever apps/site/src/routes/estate/index.ts is present and the
   view above answers where it is not. Everything above this fence dresses the explorer and is
   prefixed .ex-; everything below is prefixed .exd- or .exk- and sits under .exd-page, which no
   explorer view writes. Checked by name: no selector above uses .exd or .exk.

   WHAT IT IS. The counted estate on the face. The hero carries the argument on the left and the
   record counted by kind on the right, one lane per kind, each lane in its own identity hue. Then
   the two domain figure with its reading, the six organisation cards, the three live requests, the
   payoff and the close.

   THE FOUR IDENTITY HUES ARE THE DESIGN. --d-blue, --d-violet, --d-magenta and --d-sand mean
   nothing on their own, which is exactly what lets them separate one kind of record from the next.
   A hue arrives on an element as --hue and the cycle below is positional, so a content file cannot
   tie a colour to a kind and a reader cannot read a meaning into one. Green means Observed on every
   surface of this site, amber means in progress and red means refused, so none of the three is
   here. All four hues clear 6.6 to 1 as text on the lightest dark ground, which
   packages/ui/tools/contrast.mjs gates by name.

   THE MEASURE IS THE PAGE'S OWN 1376 AND NOT THE INTERIOR 1036. /estate is one of the five routes
   the site draws at full .wrap width.

   WHERE IT HOLDS AT 14px. The only sizes below the floor are inside the two figures' own svg text,
   which packages/ui/tests/stylesheet.test.ts exempts by selector because a drawing scales with its
   box. The lane figure is 620 user units capped at 680, so its 13px lane name renders at 14.3.

   WHAT HAPPENS AT 1180, AT 1100, AT 860 AND AT 560. The hero drops to one column and the lane
   figure goes under the copy. The instrument drops its panel under the figure. The six organisation
   cards step from three columns to two to one, and the three request cards and the four
   destinations do the same. Below 720 the two domain figure is not drawn: it is 680 user units
   carrying twenty seven character names, and scaled to a phone those names are five pixels tall.
   Nothing is lost, because the panel beside it states the same sentences in words at every width.
   The lane figure stays at every width, because a lane is a hue, a number and two words.
   ================================================================================== */

/* ---- the hue cycle ---------------------------------------------------------------

   ONE RULE SET, READ BY EVERY HUED THING ON THE PAGE, and it is positional. Four hues over six
   lanes repeat at the fifth, which is the arrangement /architecture already uses and the only one
   that keeps neighbours apart without spending a fifth meaning. */

.exd-page .exk-lanes > g:nth-child(4n + 1),
.exd-page .exk-row:nth-child(4n + 1),
.exd-page .exd-card:nth-child(4n + 1),
.exd-page .exd-read-card:nth-child(4n + 1),
.exd-page .exd-destination:nth-child(4n + 1),
.exd-page .exd-domain:nth-child(4n + 1) { --hue: var(--d-blue); }
.exd-page .exk-lanes > g:nth-child(4n + 2),
.exd-page .exk-row:nth-child(4n + 2),
.exd-page .exd-card:nth-child(4n + 2),
.exd-page .exd-read-card:nth-child(4n + 2),
.exd-page .exd-destination:nth-child(4n + 2),
.exd-page .exd-domain:nth-child(4n + 2) { --hue: var(--d-violet); }
.exd-page .exk-lanes > g:nth-child(4n + 3),
.exd-page .exk-row:nth-child(4n + 3),
.exd-page .exd-card:nth-child(4n + 3),
.exd-page .exd-read-card:nth-child(4n + 3),
.exd-page .exd-destination:nth-child(4n + 3),
.exd-page .exd-domain:nth-child(4n + 3) { --hue: var(--d-magenta); }
.exd-page .exk-lanes > g:nth-child(4n + 4),
.exd-page .exk-row:nth-child(4n + 4),
.exd-page .exd-card:nth-child(4n + 4),
.exd-page .exd-read-card:nth-child(4n + 4),
.exd-page .exd-destination:nth-child(4n + 4),
.exd-page .exd-domain:nth-child(4n + 4) { --hue: var(--d-sand); }

/* THE TWO TRUST DOMAINS TAKE THE FIRST TWO HUES IN THE FIGURE, because the figure draws them as
   two columns and a reader has to follow one column down. The subject at the foot keeps the brand,
   which is the lit box the whole figure points at. */
.exd-page .exd-fig svg g.exd-node:nth-of-type(1),
.exd-page .exd-fig svg g.exd-node:nth-of-type(2) { --hue: var(--d-blue); }
.exd-page .exd-fig svg g.exd-node:nth-of-type(3),
.exd-page .exd-fig svg g.exd-node:nth-of-type(4) { --hue: var(--d-violet); }

/* ---- the hero: the argument beside the counted record ---------------------------- */

.exd-page .exd-top { position: relative; padding-block: 56px var(--s7); }
.exd-page .exd-top > * { position: relative; z-index: 1; }
.exd-page .exd-glow { z-index: 0; }

/* TWO COLUMNS, STARTING TOGETHER. The lane figure is shorter than the copy, so centring the pair
   dropped the eyebrow down the band and left the headline in the middle of the page. */
.exd-page .exd-hero {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 0.92fr);
  gap: 48px; align-items: start;
}
.exd-page .exd-copy { min-width: 0; }

/* THE EYEBROW IS TWO WORDS WITH A RULE BETWEEN THEM, which is the shape the reference draws over
   an interior page: the section, then the subject of the page in the brand colour. */
.exd-page .exd-eyebrow { margin: 0; letter-spacing: 0.24em; }
.exd-page .exd-eyebrow-rule { margin: 0 var(--s2); color: var(--faint); }
.exd-page .exd-eyebrow-accent { color: var(--teal-dark); }

/* --t-display IS THE SITE'S 54px STEP and this page used to set its own clamp that reached 56.
   Five h1 sizes across twenty one routes is what the redesign tracker records as fault F3, so the
   step is the shared one and the accent is a block, so the sentence breaks at its own clause. */
.exd-page .exd-statement { margin: var(--s4) 0 0; max-width: 19ch; text-wrap: balance; }
.exd-page .exd-statement .accent { display: block; text-wrap: balance; }
.exd-page .exd-statement .accent { text-shadow: 0 0 28px color-mix(in srgb, var(--teal-mid) 50%, transparent); }

/* --ink-lead IS THE COLOUR OF A LEAD, one step above secondary text. */
.exd-page .exd-lead {
  margin: 20px 0 0; max-width: 46ch;
  color: var(--ink-lead); font-size: var(--t-body); line-height: 1.6;
}
.exd-page .exd-lead > p { margin: 0; }
.exd-page .exd-lead > p + p { margin-top: var(--s3); }

/* THE READ LINE IS THE CREDIBILITY AND IT SITS AT THE TOP. The date is derived in the view from
   the three requests below, so the line and the cards cannot name different days. */
.exd-page .exd-read-line {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2) var(--s3);
  margin: var(--s5) 0 0; padding: 10px var(--s4);
  border: 1px solid var(--hairline); border-radius: var(--pill);
  width: fit-content; max-width: 100%;
}
.exd-page .exd-read-when {
  font-size: var(--t-label); font-weight: 600; line-height: 1.4;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-row);
}
/* THE SEPARATOR BETWEEN THE THREE PARTS OF THE READ LINE IS DRAWN, not typed. A punctuation mark
   in the markup is a word to the word count and a noise to a screen reader; a pseudo element is
   neither. */
.exd-page .exd-read-when + .exd-read-when { position: relative; padding-left: var(--s4); }
.exd-page .exd-read-when + .exd-read-when::before {
  content: ""; position: absolute; left: 6px; top: 50%;
  width: 3px; height: 3px; margin-top: -2px; border-radius: var(--pill);
  background: var(--faint);
}
.exd-page .exd-actions { display: flex; flex-wrap: wrap; gap: var(--s3); margin-top: var(--s6); }

/* ---- the lane figure: the record counted by kind ----------------------------------

   ONE LANE PER KIND. The hue is the lane's identity, the number is computed by the view from the
   rows it draws, and the markers are those rows. The last lane is empty on purpose: the count of
   credentials needed to read any of this is zero, and an empty track says that faster than a
   sentence. */

.exd-page .exk { margin: 0; min-width: 0; }
.exd-page .exk svg { display: block; width: min(100%, 680px); height: auto; }

.exd-page .exk svg .exk-key { fill: var(--hue); }
.exd-page .exk svg .exk-n {
  fill: var(--hue);
  font-family: var(--display); font-size: 26px; font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.exd-page .exk svg text.exk-label {
  fill: var(--ink); font-family: var(--sans); font-size: 13px; font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase;
}
.exd-page .exk svg text.exk-empty {
  fill: var(--ink-2); font-family: var(--sans); font-size: 13px;
  letter-spacing: 0.14em; text-transform: uppercase;
}
.exd-page .exk svg .exk-track { stroke: var(--rule); stroke-width: 1; }
.exd-page .exk svg .exk-track-empty { stroke: var(--hue); stroke-dasharray: 3 6; opacity: 0.55; }
.exd-page .exk svg .exk-dot { fill: var(--hue); }
.exd-page .exk svg .exk-ring { fill: none; stroke: var(--hue); stroke-width: 1; opacity: 0.5; }
.exd-page .exk svg .exk-rule { stroke: var(--hairline); stroke-width: 1; }

/* THE NARROW STATE OF THE SAME FIGURE. One row per lane, the hue on a left rule, the number, the
   name, and the markers as dots. It is drawn below 760 and the SVG above is drawn at or over it,
   so only one of the two is ever displayed and the page carries each word once. */
.exd-page .exk-list { display: none; list-style: none; margin: 0; padding: 0; }
.exd-page .exk-row {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--s2) var(--s3);
  min-width: 0;
  padding: var(--s3) 0 var(--s3) var(--s4);
  border-left: 3px solid var(--hue);
  border-bottom: 1px solid var(--hairline);
}
.exd-page .exk-row:last-child { border-bottom: 0; }
.exd-page .exk-row-n {
  min-width: 34px;
  font-family: var(--display); font-size: 24px; line-height: 1; font-weight: 700;
  font-variant-numeric: tabular-nums; color: var(--hue);
}
.exd-page .exk-row-label {
  flex: 1 1 auto; min-width: 0;
  font-size: var(--t-label); font-weight: 600; line-height: 1.4;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink);
}
.exd-page .exk-row-marks { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.exd-page .exk-row-dot { display: block; width: 8px; height: 8px; border-radius: var(--pill); background: var(--hue); }
.exd-page .exk-row-empty {
  font-size: var(--t-label); line-height: 1.4;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-2);
}

/* ---- the instrument: the figure beside its reading ---------------------------------

   360 IS THE PANEL AND THE FIGURE TAKES THE REST. The reference draws a side panel at 320 and this
   one carries three sentences, so it is one step wider. The figure is capped below the column it
   sits in because its coordinates are user units and a unit was a pixel at 680: letting it fill a
   950 pixel column scales every box by 1.4 and a box becomes a banner. */

.exd-page .exd-instrument,
.exd-page .exd-members,
.exd-page .exd-reads { border-top: 1px solid var(--hairline); padding-block: var(--s7); }
.exd-page .exd-grid {
  max-width: 1120px; margin-inline: auto;
  display: grid; grid-template-columns: minmax(0, 1fr) 360px; gap: 40px;
  align-items: center;
}

.exd-page .exd-fig { margin: 0; min-width: 0; }
.exd-page .exd-fig svg { display: block; width: min(100%, 760px); height: auto; margin-inline: auto; }

/* THE BOX TAKES ITS DOMAIN'S HUE ON ITS EDGE AND THE BAR KEEPS THE TREATMENT. Two channels, two
   questions: the edge says which trust domain the box belongs to, the bar says who builds the
   thing, and the key under the cards below names every bar. */
.exd-page .exd-fig svg .exd-box { fill: var(--white); stroke: var(--hue, var(--rule)); stroke-width: 1.5; }
.exd-page .exd-fig svg .exd-node-subject .exd-box {
  fill: var(--wash-teal);
  stroke: color-mix(in srgb, var(--teal-deep) 55%, transparent); stroke-width: 1.5;
}
.exd-page .exd-fig svg .exd-bar { fill: var(--bound); }
.exd-page .exd-fig svg .exd-node[data-treat="product"] .exd-bar { fill: var(--teal); }
.exd-page .exd-fig svg .exd-node[data-treat="customer"] .exd-bar { fill: var(--ink); }
.exd-page .exd-fig svg .exd-node[data-treat="reference"] .exd-bar { fill: var(--bound); }
.exd-page .exd-fig svg .exd-node[data-treat="third"] .exd-bar { fill: var(--ink-2); }

.exd-page .exd-fig svg .exd-edge { stroke: var(--teal-dark); stroke-width: 1.5; fill: none; opacity: 0.75; }
.exd-page .exd-fig svg .exd-edge-first { stroke: var(--d-blue); }
.exd-page .exd-fig svg .exd-edge-second { stroke: var(--d-violet); }
.exd-page .exd-fig svg .exd-head { fill: var(--teal-dark); }

/* 13px AND 12px ON THE DRAWING, which is the one place the floor does not apply: these scale with
   the box, and the stylesheet test exempts a size inside an svg text selector for that reason. At
   the 760 the figure is capped to they render at 14.5 and 13.4. */
.exd-page .exd-fig svg text.exd-name { fill: var(--ink); font-family: var(--sans); font-size: 13px; font-weight: 600; }
.exd-page .exd-fig svg text.exd-sub { fill: var(--ink-2); font-family: var(--sans); font-size: 12px; }
.exd-page .exd-fig svg text.exd-edge-word {
  fill: var(--ink-2); font-family: var(--sans); font-size: 12px;
  letter-spacing: 0.12em; text-transform: uppercase;
}

.exd-page .exd-panel { min-width: 0; }
.exd-page .exd-panel-h { letter-spacing: 0.18em; }
.exd-page .exd-rows { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s4); }
.exd-page .exd-row { display: flex; align-items: flex-start; gap: var(--s3); }
/* A BRAND DOT AND NOT A GREEN TICK. The reference circles each row of a panel in green; green on
   this site means Observed and an Observed mark links the artefact it was read from, so a plain
   statement row carries the brand instead and the one Observed mark sits under the list. */
.exd-page .exd-row-mark { flex: none; width: 20px; height: 22px; display: grid; place-items: center; }
.exd-page .exd-row-mark::before {
  content: ""; display: block;
  width: 7px; height: 7px; border-radius: var(--pill);
  background: var(--teal-dark);
}
.exd-page .exd-row-t { font-size: var(--t-small); line-height: 1.55; color: var(--ink-row); }
.exd-page .exd-panel-ev { margin: var(--s5) 0 0; }

/* ---- the record: six organisation cards --------------------------------------------

   A HAIRLINE BETWEEN BANDS AND NO CHANGE OF GROUND, which is how the reference separates its
   sections, so the page reads as one surface with rules across it rather than as a stack of
   stripes. */

.exd-page .exd-head { max-width: var(--measure-notes); margin-bottom: var(--s6); }
.exd-page .exd-head .t-h2 { margin: 0 0 var(--s3); }
.exd-page .exd-head-line { margin: 0; color: var(--ink-lead); font-size: var(--t-small); line-height: 1.6; }

/* THE TWO DOMAIN CAPTIONS, one line each over the grid, each wearing its own hue on the edge so a
   reader can pair a caption with the column of the figure above it. */
.exd-page .exd-domains {
  list-style: none; margin: 0 0 var(--s6); padding: 0;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s5);
}
.exd-page .exd-domain { min-width: 0; padding-left: var(--s4); border-left: 2px solid var(--hue); }
.exd-page .exd-domain-n {
  display: block;
  font-size: var(--t-label); font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--hue);
}
.exd-page .exd-domain-l { display: block; margin-top: 4px; font-size: var(--t-small); line-height: 1.55; color: var(--ink-2); }

.exd-page .exd-cards {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s4);
}
/* THE CARD ANSWERS ITS OWN QUESTION ON ITS FACE: who it is, what it does, and which authorities
   sign about it. The top edge is the card's identity hue, which is the reference's card lit from
   above made literal, and the left bar is the treatment the estate declares. */
.exd-page .exd-card {
  position: relative; min-width: 0;
  display: flex; flex-direction: column; align-items: stretch; gap: var(--s2);
  padding: var(--s5) var(--s5) var(--s5) 24px;
  border: 1px solid var(--hairline);
  border-top: 2px solid var(--hue);
  border-radius: 16px 16px 16px 16px;
  background: var(--white);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--hue) 30%, transparent);
}
.exd-page .exd-card-bar {
  position: absolute; left: 0; top: var(--s5); bottom: var(--s5);
  width: 4px; border-radius: 0 2px 2px 0;
  background: var(--bound);
}
.exd-page .exd-card[data-treat="product"] .exd-card-bar { background: var(--teal); }
.exd-page .exd-card[data-treat="customer"] .exd-card-bar { background: var(--ink); }
.exd-page .exd-card[data-treat="reference"] .exd-card-bar { background: var(--bound); }
.exd-page .exd-card[data-treat="third"] .exd-card-bar { background: var(--ink-2); }
.exd-page .exd-card-t { margin: 0; font-size: 17px; font-weight: 700; line-height: 1.3; color: var(--ink); }
.exd-page .exd-card-l { margin: 0; font-size: var(--t-label); line-height: 1.5; color: var(--ink-2); }
/* THE CHIPS SIT ON THE BOTTOM EDGE OF THE CARD. Six cards carry lines of one, two and three lines,
   and left in flow the chip row landed at a different height on every card. */
.exd-page .exd-card-u { margin: auto 0 0; padding-top: var(--s3); display: flex; flex-wrap: wrap; gap: var(--s2); }
.exd-page .exd-under {
  display: inline-flex; align-items: center; min-height: 24px; padding: 0 10px;
  border: 1px solid var(--hairline); border-radius: var(--pill);
  font-size: var(--t-label); line-height: 1.4; color: var(--ink-row);
  background: var(--paper-alt);
}
/* AN ORGANISATION WITH NO CLAIM IS STILL IN THE RECORD, and saying so is the point of a record.
   The chip is dashed and carries the words, so the state is not colour alone and no reader has to
   work out why one card is quieter than the others. */
.exd-page .exd-under-none { border-style: dashed; color: var(--ink-2); background: transparent; }

.exd-page .exd-key { margin-top: var(--s6); }

/* ---- the three requests -------------------------------------------------------------

   A NUMBERED CARD PER KIND OF REQUEST, each opening one artefact at the host that serves it. This
   is the page's demonstration: the reader presses a link and Raidiam Connect answers them the same
   signed bytes it answers a consumer, with no credential in between. */

.exd-page .exd-read-cards {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s5);
}
.exd-page .exd-read-card {
  min-width: 0;
  display: grid; grid-template-columns: minmax(0, 1fr); align-content: start; gap: var(--s2);
  padding: var(--s6);
  border: 1px solid var(--hairline);
  border-top: 2px solid var(--hue);
  border-radius: 16px;
  background: var(--white);
}
.exd-page .exd-read-n {
  font-family: var(--display);
  font-size: 22px; line-height: 1; font-weight: 700; font-variant-numeric: tabular-nums;
  color: var(--hue);
}
.exd-page .exd-read-t { margin: var(--s2) 0 0; font-size: 17px; font-weight: 700; line-height: 1.3; color: var(--ink); }
.exd-page .exd-read-l { margin: 0; font-size: var(--t-label); line-height: 1.55; color: var(--ink-2); }
/* THE HOST IS THE CREDIBILITY, so it is printed whole and it wraps rather than being cut. It is
   derived from the card's own link in the view, so the words and the destination cannot differ. */
.exd-page .exd-read-host {
  margin: var(--s3) 0 0;
  font-size: var(--t-label); line-height: 1.5; color: var(--ink-row);
  overflow-wrap: anywhere;
}
.exd-page .exd-read-open {
  display: inline-flex; align-items: center; gap: var(--s2);
  min-height: 24px; margin-top: var(--s4); justify-self: start;
  font-size: var(--t-label); font-weight: 600; line-height: 1.4;
  color: var(--teal-dark); text-decoration: none;
}
.exd-page .exd-read-open::before {
  content: ""; display: block;
  width: 16px; height: 11px; flex: none;
  background: currentColor;
  -webkit-mask: var(--arrow-right) center / contain no-repeat;
  mask: var(--arrow-right) center / contain no-repeat;
}
.exd-page .exd-read-open:hover { text-decoration: underline; text-underline-offset: 0.14em; }
.exd-page .exd-read-ev { margin: var(--s4) 0 0; }

/* ---- the payoff and the four destinations --------------------------------------------- */

.exd-page .exd-payoff { padding-block: var(--s6) 0; border-top: 0; }
.exd-page .exd-payoff-in { border-top: 1px solid var(--hairline); padding-top: 40px; text-align: center; }
.exd-page .exd-payoff-h { margin: 0; font-size: 30px; line-height: 1.2; font-weight: 700; letter-spacing: -0.02em; color: var(--ink); }
.exd-page .exd-payoff-sub { margin: var(--s2) auto 0; max-width: 60ch; font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-2); }

.exd-page .exd-destinations {
  list-style: none; margin: var(--s6) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s5);
}
.exd-page .exd-destination { min-width: 0; }
.exd-page .exd-destination-link { display: flex; flex-direction: column; align-items: center; text-decoration: none; color: inherit; }
/* THE RING TAKES THE DESTINATION'S HUE, so four destinations read as four places rather than as
   one control repeated. The glyph inside takes the same hue through currentColor. */
.exd-page .exd-destination .rw-ring { border-color: var(--hue); color: var(--hue); }
.exd-page .exd-destination-t { margin-top: var(--s4); font-size: 16px; font-weight: 700; line-height: 1.3; color: var(--ink); }
.exd-page .exd-destination-l { margin-top: 4px; max-width: 24ch; text-align: center; font-size: var(--t-label); line-height: 1.45; color: var(--ink-2); }
.exd-page .exd-destination-link:hover .exd-destination-t { color: var(--hue); }
/* The ring is drawn on the anchor, because the list item is not focusable and an outline on the
   row would leave the ring and the words outside it. */
.exd-page .exd-destination-link:focus-visible { outline: 2px solid var(--teal-dark); outline-offset: 4px; border-radius: var(--r-2); }
.exd-page .exd-destination .rw-ring .sc-glyph { display: inline-flex; }

/* ---- the closing panel ------------------------------------------------------------------ */

.exd-page .exd-close { padding-block: var(--s7) 0; border-top: 0; }
.exd-page .exd-close-panel {
  display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: var(--s6);
  padding: var(--s6);
  border: 1px solid var(--rule);
  border-radius: 16px;
  background: var(--paper-alt);
}
.exd-page .exd-close-h { margin: 0; font-size: 24px; line-height: 1.25; font-weight: 700; letter-spacing: -0.02em; max-width: 24ch; color: var(--ink); }
.exd-page .exd-close-line { margin: var(--s2) 0 0; max-width: 44ch; font-size: var(--t-small); line-height: 1.6; color: var(--ink-lead); }
.exd-page .exd-close-btn { margin-top: var(--s5); }
.exd-page .exd-close-side-h { margin: 0; font-size: var(--t-label); font-weight: 600; line-height: 1.4; color: var(--ink); }
.exd-page .exd-explore { list-style: none; margin: var(--s4) 0 0; padding: 0; display: grid; gap: var(--s3); }
/* 24px MINIMUM, because each row is one link to one page with no other text beside it. Neither
   exemption in WCAG 2.2 clause 2.5.8 applies: the link is not inside a sentence, and the rows sit
   12px apart, so the 24px circles would intersect. */
.exd-page .exd-explore-item a {
  display: inline-flex; align-items: center; gap: var(--s2);
  min-height: 24px;
  font-size: var(--t-label); line-height: 1.4;
  color: var(--teal-dark); text-decoration: none;
}
.exd-page .exd-explore-item a::before {
  content: ""; display: block;
  width: 16px; height: 11px; flex: none;
  background: currentColor;
  -webkit-mask: var(--arrow-right) center / contain no-repeat;
  mask: var(--arrow-right) center / contain no-repeat;
}
.exd-page .exd-explore-item a:hover { text-decoration: underline; text-underline-offset: 0.14em; }

/* ---- the narrow states -------------------------------------------------------------------- */

@media (max-width: 1180px) {
  .exd-page .exd-hero { grid-template-columns: minmax(0, 1fr); gap: var(--s6); }
  .exd-page .exd-statement { max-width: 22ch; }
  .exd-page .exk svg { margin-inline: auto; }
}

@media (max-width: 1100px) {
  .exd-page .exd-grid { grid-template-columns: minmax(0, 1fr); gap: var(--s6); }
  .exd-page .exd-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .exd-page .exd-destinations { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* TWO REQUEST CARDS, NOT THREE. Measured at 900: three columns left each card 250 wide, which
     broke the host string over two lines and the Observed mark over three. */
  .exd-page .exd-read-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 860px) {
  .exd-page .exd-top { padding-block: var(--s7) 0; }
  .exd-page .exd-close-panel { grid-template-columns: minmax(0, 1fr); }
  .exd-page .exd-domains { grid-template-columns: minmax(0, 1fr); gap: var(--s4); }
}

/* THE TWO DOMAIN FIGURE IS NOT DRAWN BELOW 720, and the panel beside it is the whole of what it
   said. The drawing is 680 user units carrying twenty seven character names; at 360 pixels those
   names are under six pixels tall, which is a picture of a figure rather than a figure. It never
   scrolls sideways because it never exists at a width where it would have to. The lane figure
   above it stays, because a lane is a hue, a number and two words. */
@media (max-width: 760px) {
  .exd-page .exk svg { display: none; }
  .exd-page .exk-list { display: block; }
  .exd-page .exd-read-cards { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 720px) {
  .exd-page .exd-fig { display: none; }
}

@media (max-width: 560px) {
  .exd-page .exd-cards { grid-template-columns: minmax(0, 1fr); }
  .exd-page .exd-destinations { grid-template-columns: minmax(0, 1fr); gap: var(--s6); }
  .exd-page .exd-payoff-in { padding-top: var(--s6); }
  .exd-page .exd-close-panel { padding: var(--s5); }
  .exd-page .exd-actions .btn { width: 100%; justify-content: center; }
}

/* ---- src/parts/ev-page.css ---- */
/*
 * /evidence, rebuilt against the Raidiam Agents reference route /evidence.
 *
 * WHAT THE REFERENCE PAGE IS, READ FROM app/evidence/page.tsx ON 16 SEPTEMBER. Every section is
 * `mx-auto max-w-[1100px] px-8` and the page is centred inside it, while the masthead and the
 * footer stay at 1536. A hero: a kicker at 13px on 0.28em, a 56px statement in an 820px measure
 * whose second half takes the brand, a 17px lede in a 560px measure, then a row of tabs inside one
 * rounded tray with the current one filled. Under it a figure, then "Explore the evidence" over a
 * row of six tiles and one rounded panel: a title with a badge beside it, a sentence, a row of
 * view tabs, and the artefact. It ends on a short "Want to go deeper?" row over one soft rule.
 * There is no rule between any two sections: the rhythm is spacing alone.
 *
 * WHAT WAS TAKEN AND WHAT WAS REFUSED IS AT THE BOTTOM OF THIS COMMENT. The reference's own words
 * and figures are comp content. Only its measures, its spacing and its treatments are copied.
 *
 * EVERY RULE HERE IS SCOPED UNDER .evx, which apps/site/src/views/evidence.ejs writes on this
 * page's wrap and no other view writes. That is what lets this file restyle .evx- classes that
 * packages/ui/src/parts/ev.css already owns without reaching another route, and it is also a
 * cascade requirement rather than a preference: the parts are concatenated in sorted file name
 * order, so `ev-page.css` is read BEFORE `ev.css` and loses to it at equal specificity. Every
 * override below is therefore written as `.evx .evx-thing`, which is one class heavier.
 *
 * WHAT THE MARKUP GAVE ME AND WHAT IT DID NOT. Each agent owns a disjoint set of files, so the
 * three partials this page renders, ev-counts, ev-instrument and ev-index, are not mine to edit.
 * Every shape below is therefore reached by styling the markup as it stands. The filter tray is the
 * one that shows: `.evx-filters` is the container the partial already writes, so the tray needs no
 * extra element. The picker is a nav of six tiles and each workspace is its sibling; five of the
 * six carry `hidden` in the served markup, so one of them is on the page at a time.
 *
 * THE PAGE IS RESTYLED AND NOT REBUILT, WHICH IS RALPH'S RULING. /evidence scored "I want to know
 * more" with the panel and he reads it as the one route that already looks right, so the count
 * strip, the six way instrument, the eleven row index and every word on them stay. What changes is
 * the look: the measure, the rhythm, the treatments.
 *   THE MEASURE. The page is 1100 and centred, which is the reference's, asked for by setting
 *     --page-max on this page's own wrap. The headline takes an 820px measure and the lede 560.
 *   THE RHYTHM. No rule between sections, which is the reference's; one soft rule over the closing
 *     row, which is the one rule the reference draws. A band head closes from 12 and 32 to 8 and 24.
 *   THE INSTRUMENT. Six tiles in a row over one panel, which is the reference's shape and which
 *     packages/ui/src/parts/ev.css already drew. The 236px sidebar that stood here came from a
 *     superseded sheet and is deleted. The panel keeps the accent ring.
 *   THE FILTER. Five outlined pills become one tray with the current cell filled, which is how the
 *     reference draws its tab strip.
 * Carried over from the shell pass earlier the same day: a decorative divider takes --hairline and
 * a card edge keeps --rule, a navigation label takes --ink-nav, the copy control is the site's
 * outlined action, and the hero takes .rw-glow. The kicker now tracks at 0.28em, which is the value
 * app/evidence/page.tsx states rather than the target's general eyebrow.
 *
 * FOUR THINGS IN THE REFERENCE ARE NOT REPRODUCED, and each was refused on evidence rather than on
 * taste. They are restated here because the picture is persuasive and somebody will bring them back.
 *   Everything the reference's evidence page SAYS. Its JWT, its issuer, its scopes, its four
 *     "Verified" checks and its "Last checked 12 seconds ago" are comp content invented for the
 *     picture. Nothing on this estate declares any of them, so none of it reaches the page.
 *   The green "Signature valid" pill beside the artefact. Nothing on this page verifies a
 *     signature. The browser fetches the artefact and decodes it. It holds no key a superior
 *     vouches and it walks no chain, so the panel says what it did instead: the host, the status
 *     it answered and the time of the read.
 *   THE REFERENCE'S GROUND AND ITS BRAND, AND THIS IS THE LARGEST GAP LEFT ON THE PAGE. The
 *     reference is a dark application: ground #030910, panels #081524, brand cyan #22d3ee. This
 *     site is light: --paper #F1F4F3, --white on a card, --teal-dark #195E67 for the accent. The
 *     dark values exist in packages/ui/tokens/tokens.json under `dark` and nothing selects them.
 *     Flipping one route to them would make /evidence the only dark page on a light site, and the
 *     token file, the contrast tool and the theme are not this task's to change. Recorded, not
 *     applied. Every measure, spacing and treatment below is the reference's; only the hue is not.
 *   The reference's 13px kicker, 13px card text and 1rem panel radius. This system's type floor is
 *     14px, enforced by packages/ui/tests/stylesheet.test.ts, and its largest radius token is
 *     --r-3. Every metric below comes from the system's own scale.
 *
 * THE CLOSING CALL TO ACTION IS NOT ADDED, and that is a measured refusal rather than an omission.
 * The reference ends every route on one. tests/visitor/lib/facts.ts finds a page's call to action as
 * `.cta a[href]`, and clause V17 then requires it within 25 Tab hops of a fresh load. This page has
 * no `.cta` today, so V17 passes it over. Counted in Chrome at 1440 on the rebuilt page, it carries
 * 123 focusable controls, 97 of them inside `main`: the masthead, the stage rail, six instrument
 * tiles, three artefact chips, four view tabs, a copy control, a search field, five filters and
 * twelve index rows, each with its own artefact links. A closing band under all of that would sit
 * about a hundred hops past the budget, so adding it turns a passing clause red. The ceiling lives
 * in tests/visitor/keyboard-budget.json, which this work does not own.
 *
 * CONTRAST, RESTATED FOR THE GROUNDS THE SECOND PASS MOVED THINGS ONTO. The tiles left the white
 * panel and went back to their own --paper-alt cards, and the filters left the page ground for the
 * --paper-alt tray. Every pair below is one packages/ui/tools/contrast.mjs already enumerates:
 *   ink       on paper       the statement, a count figure
 *   ink-2     on paper       the lede, a count label
 *   teal-dark on paper       the kicker, a link
 *   ink-nav   on paper-alt   a tile label at rest, which is a navigation label
 *   ink-2     on paper-alt   a tile's second line, a filter at rest in the tray
 *   teal-dark on paper-alt   a tile glyph
 *   ink       on white       an index claim, a fact value
 *   ink-2     on white       a workspace note, a fact term
 *   teal-dark on wash-teal   the current tile, the current filter and the current view tab
 *   rule      on white       the panel's own edge
 *   rule      on paper       the tile's edge, the tray's edge, and the edge of anything operated
 * --hairline is gated by nothing and that is its definition: it draws the rule under the panel's
 * header, the rule over the count strip, the one rule over the closing row and the texture behind
 * the hero, and losing any of the four entirely would cost a reader nothing. The panel edge, the
 * tile, the chip, the tray, the search field and the code block keep --rule, because a reader has
 * to see where each of them starts before pressing it.
 */

/* ---- The measure, taken from app/evidence/page.tsx --------------------------------------------
   THE REFERENCE CENTRES THIS ROUTE IN 1100 AND KEEPS ITS MASTHEAD AT 1536. Both numbers are in its
   source: every section on the page is `mx-auto max-w-[1100px] px-8`, while components/site-header
   and components/site-footer stay at `max-w-[1536px] px-8`. So the narrow measure is the page and
   not the shell, and it is asked for here by overriding one custom property on this page's own
   wrap rather than by writing a width. `.wrap` reads --page-max on the element it is set on, which
   is this element, so the site rule keeps its gutter arithmetic and no other route moves.

   WHY THE INDEX SURVIVES THE 276px IT LOSES. Every column of the claim row is minmax(0, fr) and
   every cell carries min-width 0, so the row cannot overflow: the claim wraps instead. Counted on
   the served markup, the longest claim is "Accreditation withdrawal reaching the mark and status
   endpoints" at 63 characters, which took two lines at the old width and takes two at this one. */
.evx { --page-max: 1036px; }

/* ---- The section rhythm, counted off the reference --------------------------------------------
 * THE REFERENCE DRAWS NO RULE BETWEEN SECTIONS. Every section on app/evidence/page.tsx is spacing
 * alone: `pt-12` and `pt-16`, no border. The one rule on the page is the short one over "Want to go
 * deeper?", and it is drawn at `border-line/70`, softer than anything else on the page. The site
 * rule gives every .band a --rule top edge, so this route carried two full width bright lines the
 * reference does not have, and they cut the page into filed sections rather than one argument.
 * The deeper block keeps its line, as --hairline, because the reference keeps that one.
 *
 * THE BAND HEAD CLOSES UP for the same reason: the reference sets 8px between a section heading and
 * its line, then 24px to the thing under them. The site default is 12 and 32. */
/*
 * THE RHYTHM IS STATED PER BAND AND THE SITE'S 64 ABOVE AND BELOW IS DROPPED. Every section on the
 * reference carries its own top padding and no bottom padding at all: `pt-14` on the hero, `pt-12`
 * on the figure, `pt-16` on the inspector. The site rule gives a band 64 on both edges, so two
 * adjacent bands opened 128 apart and the page ran a third longer than the reference at the same
 * content. Each number below is the reference's own, converted on this scale: --s7 is 48 and
 * `pt-12` is 48, --s8 is 64 and `pt-16` is 64. The hero's `pt-14` is 56, which is between two steps
 * and is written as the reference writes it.
 */
.evx .band { border-top: 0; padding-block: 0; }
.evx .band-head { gap: var(--s2); margin-bottom: var(--s5); }
.evx .evx-band-figure { padding-top: var(--s7); }
.evx .evx-band-index { padding-top: var(--s8); }
.evx .evx-deeper { margin-top: var(--s6); border-top: 1px solid var(--hairline); padding-block: var(--s5) var(--s8); }

/* ---- The hero, over the reference's grid ground ---------------------------------------------- */
/* The reference runs a 44px grid behind the hero at very low contrast and fades it with a radial
   mask, so the texture reads in the middle of the band and never under the words.

   IT IS CENTRED, AND THAT IS THE REFERENCE'S OWN GEOMETRY RATHER THAN A TASTE. app/evidence/page.tsx
   sets `text-center` on the hero section and `mx-auto` on both the headline and the lede. This file
   used to force it left, which came from docs/redesign/refs7/three-pages.png: a superseded sheet. */
/*
 * THE HERO NO LONGER CLIPS ITSELF, AND THAT IS THE DEFECT THIS RULE FIXES. It carried
 * `overflow: hidden`, which cuts a 120px blur off square at the padding box: measured at 1440, the
 * pool ran from 190 to 1250 and the hero clipped it at 202 and 1238, so the band drew a lighter
 * rectangle with three straight edges under the headline. An ambient pool with a visible boundary
 * is a panel nobody meant to draw. The clip goes and two things go with it.
 *   THE GROUND STOPS OVERHANGING. It was inset by a negative gutter on each side, which the clip
 *     then removed, so the declaration had been doing nothing. It is square with the hero now.
 *   THE FIGURE BAND UNDER IT TAKES A STACKING POSITION. The pool is absolutely positioned at
 *     z-index 0 and, unclipped, reaches about 80px into the band below. A positioned element paints
 *     over the content of a later static sibling, so without this the pool would tint the figure's
 *     four rows. One declaration, on the band, rather than a z-index on every card inside it.
 */
.evx .evx-hero { position: relative; text-align: center; justify-items: center; gap: var(--s4); padding-block: 3.5rem 0; }
.evx .evx-hero > * { position: relative; z-index: 1; }
.evx .evx-band-figure, .evx .evx-band-explore, .evx .evx-band-index, .evx .evx-deeper { position: relative; z-index: 1; }
.evx .evx-grid {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  /* THE TEXTURE IS MIXED FROM --hairline AND NOT --rule. --rule is the boundary of a card, and a
     grid drawn from it read as a table of empty cells behind the headline. --hairline is the
     decorative line, so the mix rises from 28 percent to 70 to land the texture back where it was.
     A colour-mix is refused in a flat background and allowed in a gradient, which is what these
     are, because no text ever lands on a gradient the gate cannot name. */
  background-image:
    linear-gradient(to right, color-mix(in srgb, var(--hairline) 70%, transparent) 1px, transparent 1px),
    linear-gradient(to bottom, color-mix(in srgb, var(--hairline) 70%, transparent) 1px, transparent 1px);
  background-size: 44px 44px;
  /* THE MASK FOLLOWS THE WORDS. It faded from the top left while the hero was left aligned. The
     hero is centred now, so a top left fade lights the empty corner and leaves the right of the
     band flat. The anchor moves to the middle of the top edge, where the headline is. */
  -webkit-mask-image: radial-gradient(ellipse at 50% 20%, var(--ink) 0%, transparent 72%);
  mask-image: radial-gradient(ellipse at 50% 20%, var(--ink) 0%, transparent 72%);
}
/* THE AMBIENT POOL, UNDER THE GRID AND OVER NOTHING. .rw-glow is the target's fifth treatment and
   carries its own geometry, so only four things change here.
   POSITION IS RESTATED, AND LEAVING IT OUT IS THE BUG THIS RULE EXISTS TO AVOID. `.evx .evx-hero >
     *` above sets `position: relative` at two classes, .rw-glow sets `position: absolute` at one,
     so the pool loses and takes layout: 820 by 420 of empty block between the kicker and the
     headline. .evx-grid restates it for the same reason and this rule follows it.
   z-index 0, because that same rule lifts every direct child to 1 and would put a blurred teal pool
     over the headline.
   THE ANCHOR GOES BACK TO THE CENTRE. It was pulled to 26 percent while the hero was left aligned.
     The hero is centred now, so .rw-glow's own 50 percent is correct and the override is dropped:
     one fewer number on this page that has to agree with another.
   The top rises, so the pool reaches the headline rather than starting under it. */
/* THE POOL IS HELD TO 70 PERCENT OF THE MEASURE NOW THAT NOTHING CLIPS IT. .rw-glow caps itself at
   90 percent, and 90 percent plus a 120px blur on each side is wider than the wrap below about
   1200, which puts the pool past the gutter and scrolls the document sideways. At 70 percent the
   blurred pool is inside the wrap from 800 up, and below 800 the wrap is already the viewport less
   two gutters, so the blur lands in the gutter rather than past it. */
.evx .evx-hero-glow { position: absolute; z-index: 0; top: -60px; max-width: 70%; }

/* THE KICKER TRACKS AT 0.28em, WHICH IS WHAT app/evidence/page.tsx SETS. It was 0.3em off a
   superseded sheet, then 0.22em off the target's general eyebrow. The reference states this page's
   own value in its source, `tracking-[0.28em]`, and the three section routes it draws, /evidence,
   /how-it-works and /architecture, all carry that number. The size and the weight stay the site's,
   because site.css states them for every eyebrow and this page is not the place to fork them.

   THE COLOUR STAYS THE BRAND AND THE REFERENCE'S MUTED GREY IS REFUSED. The reference sets this
   kicker to its muted foreground on three routes and to the brand on /use-cases, so it does not
   hold one position. On this site the kicker is a brand mark on ten routes, and one route dropping
   it to secondary ink reads as a page that lost its accent rather than as a quieter page. */
.evx .evx-hero .eyebrow { letter-spacing: 0.28em; margin-bottom: 0; }
/* THE TWO MEASURES ARE THE REFERENCE'S IN PIXELS, NOT IN CHARACTERS. It writes `max-w-[820px]` on
   the headline and `max-w-[560px]` on the lede, both with `mx-auto`. A ch measure was the site's
   habit and it drew the headline at about 594px, which broke "See the proof. In real time." across
   two lines where the reference sets it on one. The pixel measure is the thing that makes the
   hero look like the reference, so it is taken literally. */
.evx .evx-hero .t-display { max-width: 820px; margin-inline: auto; }
.evx .evx-lede { max-width: 560px; margin-inline: auto; text-wrap: pretty; }

/* The instrument band carries no top rule and opens close to the count strip, so the statement, the
   figures and the panel read as one band. The reference puts its inspector inside the hero band for
   the same reason: a rule between the words and the thing they describe reads as a change of
   subject. */
.evx .evx-band-explore { border-top: 0; padding-top: var(--s8); }

/* ---- The count strip, drawn as the reference's tray --------------------------------------------
 *
 * WHAT THE SLOT IS. app/evidence/page.tsx puts one control under its lede and nothing else:
 * `mt-9 flex flex-wrap items-center justify-center gap-2 rounded-xl border border-line bg-panel/50
 * p-1.5`, holding five cells at `rounded-lg px-5 py-2.5`. It is the only boxed object above the
 * figure and it is what stops the hero being three centred paragraphs on an empty ground.
 *
 * WHAT GOES IN IT. Not the reference's five words. Live status, Trust chain, Signed statements, API
 * calls and Configuration are comp navigation: three of the five name views this estate has no data
 * for, and none of the five is a control this page could honour. The five cells hold the count strip
 * instead, which is five figures counted from data/capabilities.yaml and the estate declaration, and
 * which already sat in exactly this position. So the tray is taken and the labels are refused.
 *
 * THE CELLS ARE NOT SWITCHES AND MUST NOT LOOK LIKE ONE. The reference fills the current cell and
 * leaves the other four bare, which is how a reader knows it is a position. Nothing here is current,
 * so every cell is drawn the same and none carries a ground. A filled cell in a row of five figures
 * would be a selection a reader could not change.
 *
 * THE FIGURE DROPS FROM --t-figure TO --t-h1. At 1440 --t-figure resolves to 40px, and five of them
 * inside a 6px tray took the hero to 104px of tray under a 54px headline, which inverts the two.
 * --t-h1 is 32 at this width and the tray lands at 86.
 */
.evx .evx-counts {
  /* `mt-9` is 36. --s6 is 32 and is the nearest step on this scale. */
  margin-top: var(--s6);
  background: var(--paper-alt);
  border: 1px solid var(--hairline);
  border-radius: var(--r-3);
  padding: var(--s1);
  gap: var(--s2);
  overflow: visible;
}
.evx .evx-count {
  padding: var(--s4) var(--s5);
  justify-items: center;
  text-align: center;
  /* NO DIVIDER ON ANY EDGE AT ANY WIDTH. The cells are five figures, not five positions of one
     control, and a tray already separates them with its own gap. */
  border: 0;
  border-radius: var(--r-2);
  gap: var(--s2);
}
.evx .evx-count-value { font-size: var(--t-h1); line-height: var(--t-h1-line); font-weight: var(--t-h1-weight); }
/* THE FIGURE NO LONGER NAMES A DISPLAY FACE, BECAUSE THERE IS ONLY ONE FACE. This rule set
   `font-family: var(--display)` when --display was Space Grotesk and the body was Inter. The target
   sets one family, Inter, on everything including its 54px display, so tokens.json now resolves
   --display to the same stack --sans resolves to and the declaration changed nothing. A rule that
   changes nothing and reads as a second face is worse than no rule: the next reader believes the
   page has one. */
.evx .evx-count-label { text-transform: uppercase; letter-spacing: 0.1em; text-wrap: pretty; }

/* ---- The instrument, as app/evidence/page.tsx draws it -----------------------------------------
 * A ROW OF SIX TILES, THEN ONE PANEL UNDER THEM. This is the reference's own shape, read from its
 * source: `grid grid-cols-3 gap-3 sm:grid-cols-6` over six component buttons, then a separate
 * `rounded-2xl border bg-panel/60` card holding the title, a tab row and the artefact.
 *
 * IT WAS A 236px SIDEBAR AND THAT CAME FROM A SUPERSEDED SHEET. The rules deleted here were
 * measured from docs/redesign/refs7/three-pages.png, which is not the build this site is matched
 * against. Two things follow from taking the current reference instead. The tiles go back to a row
 * of six, which is what packages/ui/src/parts/ev.css already draws, so the overrides are removed
 * rather than rewritten. And the panel gets the whole measure: at 1100 a sidebar left the workspace
 * about 815px to carry an artefact beside its translation, which is the one part of this page that
 * cannot afford to be narrow.
 */
.evx .evx-instrument { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s5); }
.evx .evx-picker { grid-template-columns: repeat(6, minmax(0, 1fr)); gap: var(--s3); }

/* The tile. The reference sets `px-3 py-5` on a rounded bordered button with a 28px glyph over a
   label, so the tile takes --s5 and --s3 and keeps the 28px glyph packages/ui/src/parts/ev.css
   already gives it. The second line, "Reads the wire" against "Declared", has no slot in the
   reference and stays: it is the distinction this page exists to make, and a reader who cannot see
   it before pressing has to press all six to find it. */
.evx .evx-tile { padding: var(--s4) var(--s3); }

/* THE LINE UNDER A SECTION HEADING IS THE REFERENCE'S 15px MUTED SUB, NOT A 17px LEAD. It writes
   `mt-2 text-[15px] text-[#8ea3bd]` under both of its section headings. This page set both at body
   size in the primary ink, which made each one read as a second headline. */
.evx .evx-band-sub { font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-2); }

/* The panel. `rounded-2xl border border-line bg-panel/60` in the reference, and here the site's
   largest radius over the white card ground. The accent ring stays on it: it was drawn around the
   sidebar version and it is the thing that makes the instrument read as the object of the page. */
.evx .evx-work {
  border-radius: var(--r-3);
  padding: var(--s5);
  /* The header below pulls its margin out past the panel's padding to reach both edges. Without
     this it would also reach past the rounded corners. The reference's card carries the same
     declaration for the same reason: `overflow-hidden rounded-2xl`. */
  overflow: hidden;
  /* One accent hairline and a soft halo outside it. Both are shadows, so no flat background carries
     a mix and the contrast gate still names every ground on the panel.

     THE RING STAYS BRAND AND DOES NOT TAKE THE COMPONENT'S HUE. It was tried on 16 September 2026
     and measured, and it is wrong twice over. The reference's own panel is `rounded-2xl border
     border-line bg-panel/50`, with the hue on the six tiles and none on the panel, so hueing it
     copies nothing. And the Accreditation hue is #35d9a4 against the observed green #35CC86: the
     measured ring was rgb(53, 217, 164) at 30% around a panel whose Trust mark card reads "Not
     observed on this tenant", which is a green halo over an absence on the one page whose subject
     is the difference. The hue belongs on the tile, which carries no evidence mark. */
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--teal-dark) 30%, transparent),
    0 0 40px -8px color-mix(in srgb, var(--teal-dark) 40%, transparent);
}

/* The workspace header: the name on the left, where the artefact comes from beside it, the note
   under both. The reference sets a badge beside its title in the same position.

   THE RULE UNDER IT RUNS EDGE TO EDGE, WHICH IS THE REFERENCE'S PANEL. Its card divides the header
   from the tab row and the tab row from the body with `border-b` on full width blocks. The header
   here is a grid item inside a padded panel, so it pulls its own margin back by the panel's padding
   and restores it as padding: the rule then reaches both edges and the text does not move. */
.evx .evx-work-head {
  grid-template-columns: auto minmax(0, 1fr);
  align-items: baseline;
  column-gap: var(--s3);
  margin: calc(-1 * var(--s5)) calc(-1 * var(--s5)) 0;
  padding: var(--s5);
  border-bottom: 1px solid var(--hairline);
}
.evx .evx-work-title { grid-column: 1; }
.evx .evx-source { grid-column: 2; }
.evx .evx-work-what { grid-column: 1 / -1; }

/* ---- The facts strip, as the reference's decoded table ----------------------------------------
   The reference prints its decoded artefact as striped term and value rows inside one rounded
   boundary. These five facts are the same shape of content, so they take the same treatment: five
   rows rather than five columns, which also stops the fifth fact, the evidence mark, from being
   squeezed into a column a third of its width.

   THE BOX IS A HAIRLINE AND IT WAS A RULE, WHICH LEFT THE TWO FILES DISAGREEING. The base rules in
   packages/ui/src/parts/ev.css draw this strip's top and bottom edges, and they moved to --hairline
   with every other divider. This override replaces them with a box on all four sides, so while it
   named --rule the strip took a bright frame on a panel where nothing else had one. Nobody operates
   the strip: it is five terms and five values, and the stripe below does the separating. */
.evx .evx-facts {
  grid-template-columns: minmax(0, 1fr);
  gap: 0;
  padding: 0;
  border: 1px solid var(--hairline);
  border-radius: var(--r-2);
  overflow: hidden;
}
.evx .evx-fact {
  display: grid;
  grid-template-columns: minmax(0, 190px) minmax(0, 1fr);
  gap: var(--s4);
  align-items: baseline;
  padding: var(--s3) var(--s4);
}
.evx .evx-fact:nth-child(odd) { background: var(--paper); }
.evx .evx-fact-ev { grid-column: auto; }

/* ---- The view tabs, as the reference's toggle group -------------------------------------------
   The reference sets its view tabs in one row with the current one filled and the rest carrying no
   ground: `rounded-md bg-[#123047] px-4 py-1.5 text-brand` against `rounded-md px-4 py-1.5`. The
   markup here carries the copy control in the same row, so it keeps its own boundary and stays a
   pill, which is what the reference does with the one badge in its own tab row.

   THE RADIUS IS A SOFT RECTANGLE AND NOT A PILL, WHICH IS THE ONE THING THAT CHANGED HERE. The
   reference draws no pill switch anywhere on this page: its hero tabs are `rounded-lg`, its view
   tabs `rounded-md`. A pill switch beside the rectangular filter tray two bands down read as two
   kinds of control doing one job. --r-2 is this system's nearest step and the chip below takes it
   too, so every switch on the route is now one shape.

   WHAT IS NOT TAKEN: the reference rules its tab row off from the panel header and from the code
   with a full width `border-b`. The row here is two boxes deep inside a padded panel, so a rule
   that reached both edges would need a second negative margin measured against two paddings, and
   that arithmetic breaks silently at the narrow widths. The header rule is drawn and this one is
   not; the reference's is the divider that carries the shape, and this one is the one it repeats. */
.evx .evx-tabs { border-bottom: 0; gap: var(--s2); }
.evx .evx-tab {
  border-bottom: 0;
  border-radius: var(--r-2);
  padding: var(--s2) var(--s4);
  min-height: 36px;
}
.evx .evx-tab:hover { background: var(--paper-alt); }
.evx .evx-tab.is-current { background: var(--wash-teal); color: var(--teal-dark); }
/* The copy control takes its whole shape from packages/ui/src/parts/ev.css now, where it is the
   site's outlined action. The override that used to sit here set the pill and the padding and was
   the only half of that treatment this page had. */

/* The artefact chooser sits above the facts, one pill per artefact, and it is the same control as
   the view tabs one level up. Drawn the same way, so a reader meets one kind of switch twice rather
   than two kinds once. */
.evx .evx-chip { background: none; border-radius: var(--r-2); }
.evx .evx-chip.is-current { background: var(--wash-teal); color: var(--teal-dark); border-color: var(--teal-dark); }

/* The artefact block. The reference drops its raw JSON onto the page ground inside the panel, which
   separates the bytes from the card that frames them. */
.evx .evx-code { border-radius: var(--r-2); }

/* ---- How to read this page, which the page no longer prints -----------------------------------
   THE THREE CARD BAND IS GONE AND THESE RULES GO WITH IT. The reference closes its inspector with
   three small panels and this page copied the shape. Two of the three explained the page to itself,
   which is what this rebuild is removing everywhere, and the third, the signature caveat, moved up
   into the lede over the instrument. A rule for markup nothing renders is a rule the next reader
   has to test against the page to find out is dead, so it is deleted rather than left. The record
   of what the band said, and of where its one fact went, is in apps/site/src/views/evidence.ejs. */

/* ---- The filter group, as the reference's tab strip -------------------------------------------
 * THE ONE CONTROL THE REFERENCE DRAWS THAT THIS PAGE ALSO HAS. app/evidence/page.tsx sets its five
 * tabs inside one container, `rounded-xl border border-line bg-panel/50 p-1.5`, and fills the
 * current one rather than outlining all five: `rounded-lg bg-[#123047] px-5 py-2.5 text-brand`,
 * with the rest carrying no border and no ground at all. Five separately outlined pills, which is
 * what this row was, read as five things to press. One tray with one filled cell reads as one
 * control with a position, which is what a filter is.
 *
 * THE COUNTS AND THE WORDS ARE UNCHANGED. The reference's five tabs are invented and name views
 * this estate does not have. These five are the evidence vocabulary plus All, and the figure beside
 * each is counted from data/capabilities.yaml. Only the treatment is taken.
 *
 * .evx-filters IS THE CONTAINER ITSELF, so the tray needs no extra element: the partial that draws
 * it, packages/ui/partials/ev-index.ejs, is not this task's to edit. */
.evx .evx-filters {
  display: inline-flex;
  /* THE TRAY HUGS ITS FIVE CELLS. `.evx-controls` is a grid, so a grid item stretches to the column
     unless it is told not to, and a tray drawn the width of the page with five cells packed into
     its left end reads as an empty container. The reference's tray is full width because its five
     tabs are centred in it; this one is ranged left with the search field above it. */
  justify-self: start;
  flex-wrap: wrap;
  gap: var(--s1);
  padding: var(--s1);
  background: var(--paper-alt);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
}
.evx .evx-filter {
  background: none;
  border: 0;
  border-radius: var(--r-2);
  padding: var(--s2) var(--s5);
}
/* Hover lifts the ink and nothing else, which is the reference's `hover:text-white`. A ground on
   hover inside a tray reads as a second selection. */
.evx .evx-filter:hover { background: none; color: var(--ink); }
.evx .evx-filter.is-current { background: var(--wash-teal); color: var(--teal-dark); }
.evx .evx-filter.is-current .evx-filter-count { color: var(--teal-dark); }

/* ---- The index --------------------------------------------------------------------------------
   Eleven claims and a legend, one row each. The reference has no equivalent and takes no view on
   it, so this keeps the shape it had and takes the panel's hover and boundary language. */
.evx .evx-summary:hover { background: var(--paper-alt); }
.evx .evx-summary { padding-inline: var(--s3); border-radius: var(--r-1); }
.evx .evx-body { padding-left: calc(14px + var(--s3) + var(--s3)); }

/* ---- The deeper row ---------------------------------------------------------------------------
   Four ways out of the page, and the command that answers it as JSON. The reference draws the same
   block: one soft rule, the question in primary ink at label size, then the routes under it. Its
   routes are `href="#"` and this page's four all resolve, so the shape is taken and the links are
   ours. The line under each route is ours too and the reference has no slot for it; it stays,
   because a route named without saying what it answers is a link a reader has to spend to read. */
.evx .evx-deeper-head { color: var(--ink); }

/* THE NARROW STATES ARE RESTATED HERE AND NOT LEFT TO ev.css, and that is a cascade requirement
   rather than duplication. The rules above are written `.evx .evx-picker`, which is two classes.
   The same rules inside a media query in packages/ui/src/parts/ev.css are written `.evx-picker`,
   which is one. A media query adds no specificity, so the wide rule above would beat the narrow one
   and the picker would hold six columns down to 375. Each narrow rule therefore carries the same
   two classes as the rule it has to beat. The reference drops to `grid-cols-3` below its `sm`
   breakpoint and this keeps that step, with a second step to two. */
@media (max-width: 1000px) {
  .evx .evx-picker { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (max-width: 700px) {
  .evx .evx-picker { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* The panel's padding drops, so the header's negative margin has to drop with it or the rule
     overshoots the panel by 8px on each side. One number, stated twice, in the same block. */
  .evx .evx-work { padding: var(--s4); }
  .evx .evx-work-head { margin: calc(-1 * var(--s4)) calc(-1 * var(--s4)) 0; padding: var(--s4); }
  .evx .evx-count { padding: var(--s3) var(--s4); }
  .evx .evx-fact { grid-template-columns: minmax(0, 1fr); gap: var(--s1); }
}

/* TOUCH TARGETS ON THE TWO LINK LISTS.
 *
 * WCAG 2.2 clause 2.5.8 sets 24 CSS pixels as the minimum, and tools/redesign/responsive.mjs reads
 * it at every width. Measured at 390 wide: the claim row's link was 275 by 23 and the route links
 * under a claim were 19 tall. The clause exempts a link inside a sentence, and these are not in
 * sentences: they are lists of things to press, one per line, which is exactly the case the clause
 * is about.
 *
 * IT IS A MINIMUM HEIGHT AND NOT PADDING, so the rows do not move apart and the page keeps the
 * density the evidence index is built on. The box grows around the text rather than below it.
 */
.evx-row a,
.evx-pages a {
  display: inline-flex; align-items: center;
  min-height: 24px;
}

/* THE MEASURE, stated once for this page. An evidence companion, which is an interior page takes 1036px: the reference writes its container as a
   BOX and --page-max here is the CONTENT width, so the number is that box less its 64px of
   padding. Without this line the page fell back to the wide default and sat 340px wider than
   its siblings, which the 16 September route audit measured across eleven pages. */
.uce-page { --page-max: 1036px; }

/* ---- src/parts/ev.css ---- */
/*
 * /evidence, rebuilt as an explorer: a count strip, a six way instrument, and a searchable index.
 *
 * WHAT IT REPLACED AND WHY. The page served 1981 visible words inside `main` with every drawer
 * closed, which was the most text on the estate. The content was right and the shape was wrong: an
 * audit database rendered as prose. Eleven claims were eleven drawers whose summary line was the
 * whole claim sentence, so a reader had to read every claim to find one; eight artefacts were eight
 * stacked panels, each with its own plain English essay beside it. Nothing is deleted here. The
 * claim sentence moved inside its row, the artefact introductions became a facts strip above the
 * code, and the four evidence classes moved from four prose blocks into the count strip and the
 * filter row, where they are a control rather than a paragraph.
 *
 * THE CLASS PREFIX IS evx- AND NOT ev-, and that is a cascade decision rather than a naming one.
 * packages/ui/src/parts/evidence.css already owns forty one ev- classes, and the parts are
 * concatenated in sorted file name order, so `ev.css` is read BEFORE `evidence.css` and would lose
 * to it at equal specificity on every name they shared. A separate prefix makes the question moot.
 * What this file DOES reuse from evidence.css, by name and deliberately, is the artefact reader:
 * .ev-code, .ev-pane, .ev-part, .ev-block, .ev-claims, .ev-claim and the .j- syntax colours. That
 * machinery was the half of the old page that worked, so it is carried rather than rewritten.
 *
 * WHAT WAS MEASURED FROM docs/redesign/refs7/three-pages.png, LEFT panel of three, medians over
 * thousands of pixels in the raw crop rather than picked by eye:
 *
 *     page ground            #021222      built as --paper       #001721
 *     strip cell, rest       #041A35
 *     strip cell, current    #032D5C
 *     tile, rest             #01162C      built as --paper-alt   #031E27
 *     tile, current          #012854      built as --wash-teal   #03313B
 *     workspace card         #011527      built as --white       #0B2531
 *
 * THE REFERENCE'S ACCENT IS A ROYAL BLUE AND THIS SITE'S IS A CYAN. The hue is not taken. This is
 * the same product as the other eighteen routes, the reference is one render of one page, and an
 * accent is a token decision across all of them, so the site's own accent stays and the difference
 * is recorded here rather than applied. Spacing, type size, radius and stroke weight are not taken
 * either: the reference panel is 507 px wide against a full width design, so every metric in it is
 * below what that resolution kept. Each comes from the system's own scale.
 *
 * THREE THINGS IN THE REFERENCE ARE NOT BUILT, and each is recorded so nobody restores them from
 * the picture.
 *   The green "Valid signature" pill beside the artefact. Nothing on this page verifies a
 *     signature. The browser fetches the artefact and decodes it; it holds no key the superior
 *     vouches and it walks no chain. A green tick asserting a valid signature over a read that
 *     checked none is the exact fault this page exists to catch elsewhere.
 *   The four green "Verified" nodes in the figure and the "All trust checks valid" banner under it.
 *     Same reason, at figure scale. Three of the four states it paints green are not observed on
 *     this tenant. THE FIGURE ITSELF IS DRAWN NOW and was not when this note was first written: the
 *     refusal was aimed at the ticks and took the shape with them. The hero instrument, .evx-sp
 *     below, draws the eleven claims and the artefacts they cite, counted, with no mark of any kind
 *     on any part of it.
 *   The five tab strip reading Live status, Trust chain, Signed statements, API calls,
 *     Configuration. Three of those five name views this estate has no data for. The slot holds
 *     the count strip instead, which is five figures counted from the matrix and the declaration,
 *     drawn in the reference's own tray.
 *
 * EVERY DECORATIVE DIVIDER HERE IS --hairline AND NOT --rule, which changed on 16 September when
 * the rest of the site changed. --rule is #4d6a89 on the dark site and clears the component floor
 * of 3, which is correct for the edge of a card and for anything a person operates: a tile, a chip,
 * a filter, a search field, the code block. It is wrong for a line a reader is not meant to see.
 * This page drew every divider it has at that weight: the count strip's box and the rules between
 * its cells, the two rules that frame the facts strip, the tab strip's baseline, the badge saying
 * where an artefact came from, the rules between the rows of the declared list, the rules between
 * the rows of the index and the rules between the columns of the deeper row. The result was a
 * reading surface ruled like a spreadsheet. Each of those takes --hairline now, at 1.24 on a card,
 * which is where the target build draws its own. The test for which token a line takes: if losing
 * the line entirely would cost a reader nothing, it is a hairline.
 * WHAT KEEPS --rule IS EVERY EDGE A FINGER LANDS ON. The tile, the workspace card, the instrument
 * panel, the chip, the filter, the search field, the artefact block and the copy control. A reader
 * has to see where each of those starts before pressing it, which is what the component floor of 3
 * is for.
 *
 * A NAVIGATION LABEL TAKES --ink-nav, which is the second thing the shell changed. The picker is a
 * `nav` in packages/ui/partials/evx-explorer.ejs and its six tiles are this page's navigation, so
 * a tile label now reads at the ink a masthead link takes at rest, and the current tile takes the
 * brand exactly as the masthead marks its current item. The label was --ink, which is the ink of a
 * heading: six headings in a row beside the one that is current read as six current items.
 * THE FOUR WAYS OUT OF THE PAGE AT THE FOOT DO NOT TAKE IT, and that is a decision rather than an
 * omission. They are not a `nav` and they are not the footer's link columns in another position.
 * Each carries an arrow and a line saying where it leads, and between them they are the only action
 * this page offers a reader who now believes it. At --ink-nav four exits would look like the footer
 * directly under them. They keep the brand.
 *
 * THE ACTION IS OUTLINED, which is the third. The copy control is the one thing here a reader
 * presses to take something away, so it is drawn as the site's outlined action: a brand border, the
 * brand bright as the label, a full pill and --wash-teal on hover. packages/ui/src/parts/mast.css
 * declares the same control for the masthead. It used to be a grey outlined rectangle at the right
 * hand end of the tab strip, which read as a fourth tab that would not stay pressed.
 *
 * GREEN IS THE WHOLE POINT OF THIS FILE, so nothing below writes var(--ok) at all. The only green
 * on the page arrives through packages/ui/partials/ev.ejs, which refuses to draw an Observed mark
 * without a link to its artefact, and packages/ui/tests/stylesheet.test.ts refuses var(--ok)
 * outside the selectors that mean observed. An instrument reading the estate declaration carries no
 * evidence mark at all and takes the muted ink, because a declared answer drawn as a live one is
 * the single claim this page exists to refuse.
 *
 * WHAT THIS FILE NO LONGER DRAWS. A "how to read this page" band of three cards. Two of the three
 * explained the page's own controls, so apps/site/src/views/evidence.ejs cut the band and moved the
 * third, the signature caveat, up to the lede over the instrument. The .evx-principle rules that
 * dressed the band lived in packages/ui/src/parts/ev-page.css and are deleted there. Restoring the
 * band means restoring those rules and moving the caveat back down, or the page states it twice.
 */

/* ---- Level one: the hero and the instrument ----------------------------------------------------
   Centred, which most of this site is not. The reference centres it and /how-it-works and /live
   already took the same deviation for the same reason: the page has one job above the fold. */
.evx-hero { text-align: center; display: grid; justify-items: center; gap: var(--s3); }
.evx-hero .t-display { margin: 0; max-width: 18ch; text-wrap: balance; }
/* THE LEDE TAKES --ink-lead AND NOT --ink-2. The reference sets `text-[#aebdd2]` on it, which is
   one step under the primary ink; --ink-2 is #8ea3bd, two steps under, and is the ink of a caption. */
.evx-lede { margin: 0; max-width: 52ch; color: var(--ink-lead); text-wrap: balance; }
/* TWO ACTIONS IN ONE ROW, which is the target's own gesture and which this route carried none of:
   it offered a single link, at the foot, after nine hundred words. */
.evx-hero-actions { margin: var(--s2) 0 0; display: flex; flex-wrap: wrap; gap: var(--s3); justify-content: center; }

/* ---- The four identity hues, and the one thing they say ----------------------------------------
 *
 * THE HUE ANSWERS WHICH STAGE A CLAIM BELONGS TO AND NOTHING ELSE. The stage is the estate's own
 * grouping of the capability matrix, and the four stages the matrix carries today, govern,
 * discover, revoke and keys, take one hue each. It is an identity axis: a claim is not better for
 * being blue.
 *
 * THE HUE AND THE EVIDENCE MARK ARE KEPT IN DIFFERENT PARTS OF THE PAGE, and on this route that is
 * a rule rather than a preference. The observed green is #35CC86 and the mint identity hue is
 * #35d9a4; the amber state is #F4A437 and the sand identity hue is #f5b93f. Four points apart on
 * the screen, so a hue drawn inside the column that carries a mark reads as a second, quieter
 * state, on the one page whose subject is the difference between the two. The hue therefore sits in
 * the hero figure, on a ledger group heading and on a row's left edge, and the mark sits in the row
 * and on the artefact card.
 *
 * SEVEN STAGES AND FOUR HUES, so three pairs share. The pairs are chosen so that no two stages the
 * matrix carries today collide: identify with discover, attest with keys, authorise with govern.
 * A row added under identify, attest or authorise would put two stages in one hue in the same
 * figure, and the fix then is a fifth hue in the token file rather than a re-shuffle here.
 */
.evx { --stage: var(--rule); }
.evx [data-stage="identify"] { --stage: var(--d-violet); }
.evx [data-stage="attest"] { --stage: var(--d-magenta); }
.evx [data-stage="govern"] { --stage: var(--d-blue); }
.evx [data-stage="discover"] { --stage: var(--d-violet); }
.evx [data-stage="authorise"] { --stage: var(--d-blue); }
.evx [data-stage="revoke"] { --stage: var(--d-sand); }
.evx [data-stage="keys"] { --stage: var(--d-magenta); }

/* ---- The second identity axis: which component, and the hues are the reference's own ------------
 *
 * WHY THERE ARE TWO AXES ON ONE PAGE. The stage axis above answers which stage a CLAIM belongs to.
 * This one answers which COMPONENT an artefact is about, and the explorer is the only band that
 * carries it: six tiles and the one panel a tile opens. The ledger carries the stage axis and no
 * component, the explorer carries the component axis and prints the stage as a word rather than as
 * the panel's own colour, so no object on the page is asked to carry both.
 *
 * THE SIX VALUES ARE MEASURED FROM THE REFERENCE ROUTE, not chosen. Read off the six component
 * tiles at http://127.0.0.1:4620/evidence on 16 September 2026, as the computed colour of each
 * tile's icon: Agent #22d3ee, Publisher #52a8ff, Authority #9d8bff, Accreditation #35d9a4,
 * Runtime #f5b93f, Platform #22d3ee. Six tiles, five hues: the reference gives the brand to the
 * first and the last, which is why this list repeats --teal-dark rather than reaching for a sixth.
 *
 * WHY THIS BAND WAS CYAN AND NOTHING ELSE BEFORE. All six glyphs read var(--teal-dark), measured
 * as rgb(34, 211, 238) on all six tiles, so the band that occupies half the page had one colour in
 * it. CLAUDE.md names the failure and the reason for it: an identity hue answers "which one of
 * these is this" and carries no meaning of its own, which is exactly what frees it to do this work.
 * A tile carries no evidence mark, so nothing here is a state.
 *
 * WHERE THE HUE IS ALLOWED TO GO, AND THE LIST IS SHORT ON PURPOSE. The tile's glyph, its border,
 * its current label, and the left edge of the sentence inside a declaration workspace. That is all.
 *
 * NOT THE PANEL A TILE OPENS. Tried and measured on 16 September 2026: the Accreditation hue
 * #35d9a4 rang the panel at rgb(53, 217, 164), four points from the observed green #35CC86, around
 * a panel whose Trust mark card reads "Not observed on this tenant". The reference does not hue its
 * panel either. The note in packages/ui/src/parts/ev-page.css records it beside the rule.
 *
 * NOT ANY FLAT GROUND. The contrast gate names grounds by token and cannot see a colour mix, and
 * packages/ui/tests/stylesheet.test.ts refuses a mix in a flat background for that reason. A
 * current tile therefore keeps --wash-teal and takes the hue on its edge.
 *
 * THE DECLARATION WORKSPACE IS SAFE BY CONSTRUCTION, which is why its edge may take a hue while an
 * artefact card's panel may not. apps/site/tests/evidence-explorer.test.ts asserts that a workspace
 * reading the declaration draws no data-ev at all, so there is no mark in that block for a hue to
 * be mistaken for.
 */
.evx { --pick: var(--teal-dark); }
.evx [data-pick="agent"], .evx [data-work="agent"] { --pick: var(--teal-dark); }
.evx [data-pick="publisher"], .evx [data-work="publisher"] { --pick: var(--d-blue); }
.evx [data-pick="authority"], .evx [data-work="authority"] { --pick: var(--d-violet); }
.evx [data-pick="accreditation"], .evx [data-work="accreditation"] { --pick: var(--d-magenta); }
.evx [data-pick="runtime"], .evx [data-work="runtime"] { --pick: var(--d-sand); }
.evx [data-pick="platform"], .evx [data-work="platform"] { --pick: var(--teal-dark); }

/* ---- The hero instrument ----------------------------------------------------------------------
 * Eleven claim tiles in four hued tracks, the artefacts they cite, and the figures read off the
 * same matrix. It replaces the count strip that stood here: the five figures are drawn inside it,
 * so the page states each of them once.
 *
 * IT IS TWO DRAWINGS AND EXACTLY ONE OF THEM IS ON THE PAGE. The wide one lays the four stage
 * tracks beside the artefact hub; the stacked one puts them above it. Scaling the wide drawing into
 * a 358px column takes a 15px label to 5px, and letting the box scroll sideways instead puts the
 * figure's answer off the screen, so the narrow state is drawn rather than derived. Both read the
 * same values, so neither can say something the other does not.
 */
.evx-sp { display: grid; gap: var(--s4); margin-top: var(--s6); width: 100%; justify-self: stretch; }
.evx-sp-scroll { overflow-x: auto; }
.evx-sp-narrow { display: none; }
.evx-sp-svg { display: block; width: 100%; height: auto; }
.evx-sp-wide .evx-sp-svg { min-width: 860px; }
.evx-sp-cap { fill: var(--ink-2); font-size: 15px; font-weight: 600; }
.evx-sp-stage { fill: var(--stage); font-size: 16px; font-weight: 700; }
/* The tile is filled and stroked in the same hue, at a low fill opacity, so eleven tiles read as
   eleven objects rather than as eleven blocks of colour. Opacity rather than a mix, because the
   count of a hue is what says the figure is coloured at all and a mix resolves to neither token. */
.evx-sp-tile { fill: var(--stage); fill-opacity: 0.26; stroke: var(--stage); stroke-width: 1.25; }
.evx-sp-link { stroke: var(--stage); stroke-width: 1.5; opacity: 0.55; }
.evx-sp-head { fill: var(--stage); opacity: 0.8; }
/* The hub is the one brand object in the figure, drawn the way every hub on this site is drawn. */
.evx-sp-hub { fill: var(--wash-teal); stroke: var(--teal-dark); stroke-width: 1; }
.evx-sp-hub-value { fill: var(--ink); font-size: 34px; font-weight: 700; }
.evx-sp-hub-line { fill: var(--ink-2); font-size: 15px; }
.evx-sp-out { stroke: var(--teal-dark); stroke-width: 1.5; opacity: 0.7; }
.evx-sp-out-head { fill: var(--teal-dark); opacity: 0.85; }
/* THE OUTCOME CARD TAKES THE HUB'S EDGE AND NOT A GREY HAIRLINE. Every one of these cards is a
   figure the hub produced, the arrow between them is already drawn in the brand, and a grey box on
   the end of a brand arrow read as a card the figure had finished with. */
.evx-sp-out-card { fill: var(--paper-alt); stroke: var(--teal-dark); stroke-width: 1; stroke-opacity: 0.45; }
.evx-sp-out-value { fill: var(--ink); font-size: 26px; font-weight: 700; }
.evx-sp-out-label { fill: var(--ink-2); font-size: 15px; }

/* The closing bar. It sits where the reference puts its verdict and says the opposite thing, so it
   takes no state colour at all: the page's ground, a hairline, a hollow mark and the muted ink. */
.evx-sp-note {
  margin: 0 auto;
  max-width: 760px;
  display: flex;
  align-items: flex-start;
  gap: var(--s3);
  padding: var(--s3) var(--s5);
  background: var(--paper-alt);
  border: 1px solid var(--hairline);
  border-radius: var(--pill);
  color: var(--ink-2);
  text-align: left;
}
.evx-sp-note .mark { width: 16px; height: 16px; margin-top: 3px; }

/* ---- Level two: the instrument -----------------------------------------------------------------
   Six tiles and one workspace. Every workspace but the current one carries `hidden` in the markup,
   so a reader with no script meets one of them and reaches the rest through the tile's own href. */
.evx-explorer { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s5); }
/* TWO CLASSES, because packages/ui/src/parts/ev-page.css states the same grid at two classes for
   the name this container used to carry. Stating it at the same weight keeps the page's shape in
   one place when that file is next read. */
.evx .evx-explorer { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s5); }

.evx-picker { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: var(--s3); }
.evx-tile {
  display: grid;
  justify-items: center;
  align-content: start;
  gap: var(--s2);
  padding: var(--s4) var(--s2);
  background: var(--paper-alt);
  border: 1px solid var(--rule);
  border-radius: var(--r-2);
  color: var(--ink-2);
  text-decoration: none;
  text-align: center;
  transition: border-color var(--m-hover) ease, background var(--m-hover) ease;
}
.evx-tile:hover { border-color: var(--pick); color: var(--ink); }
/* THE CURRENT TILE'S GROUND STAYS A TOKEN AND ONLY ITS EDGE TAKES THE HUE. --wash-teal is the near
   black the whole site gives a current control, the contrast gate names it, and the reference's own
   current tile is a 9% tint of its hue over the page ground, which is the same near black. The hue
   arrives on the border and the glyph, where it is read as identity rather than as a fill. */
.evx-tile.is-current { background: var(--wash-teal); border-color: var(--pick); color: var(--ink); }
/* THE GLYPH STANDS ON A RINGED PLATE, WHICH IS THE REFERENCE'S TREATMENT AND NOT AN INVENTION.
   Its own figure sets each component icon in a 44px rounded plate at radius 8, filled
   rgba(hue, 0.12) with no border, measured on 16 September 2026. The fill is refused here and the
   ring replaces it: a flat tinted ground would have to be written as a colour mix or as a raw rgba,
   and packages/ui/tests/stylesheet.test.ts refuses the first outright and tolerates the second only
   because the triple happens to match a token, which is a value copied rather than read. A border
   may carry the mix, so the plate is drawn as one. It is also the site's own treatment: CLAUDE.md
   lists ringed icon plates among the eight the target is made of. */
.evx-tile .sc-glyph {
  width: 44px;
  height: 44px;
  box-sizing: border-box;
  padding: 8px;
  border: 1px solid color-mix(in srgb, var(--pick) 34%, transparent);
  border-radius: var(--r-2);
  color: var(--pick);
}
.evx-tile:hover .sc-glyph, .evx-tile.is-current .sc-glyph { border-color: color-mix(in srgb, var(--pick) 70%, transparent); }
/* THE TILE LABEL IS A NAVIGATION LABEL AND TAKES --ink-nav. The picker is a `nav` element in
   packages/ui/partials/evx-explorer.ejs and its six tiles are the page's own navigation, so the
   label takes the same ink the masthead gives a link at rest. It was --ink, which is the colour of
   a heading: six headings in a row beside the one that is current read as six current items. The
   current tile lifts to the brand in ev-page.css, which is the masthead's mark too. */
.evx-tile-label { font-size: var(--t-label); font-weight: var(--t-label-weight); line-height: var(--t-label-line); color: var(--ink-nav); }
/* HOVER LIFTS THE LABEL, and it has to be stated here now. The tile's own hover rule sets `color`
   on the tile, which used to reach the label by inheritance. The label states its own colour since
   it became a navigation label, so the tile's hover stopped touching it and the only tile hover a
   reader could see was the border. That is the masthead's rule too: hover lifts the ink and draws
   no underline, because a hover mark and a current mark must not look like the same thing. */
.evx-tile:hover .evx-tile-label { color: var(--ink); }
.evx-tile.is-current .evx-tile-label { color: var(--pick); }
.evx-tile-reads { color: var(--ink-2); }

.evx-work {
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
  padding: var(--s5);
  display: grid;
  gap: var(--s4);
}
.evx-work[hidden] { display: none; }
.evx-work-head { display: grid; gap: var(--s2); }
.evx-work-title { margin: 0; }
.evx-work-what { margin: 0; color: var(--ink-2); max-width: 60ch; }
/*
 * WHERE THE ARTEFACT CAME FROM, AND IT IS NOT AN EVIDENCE MARK. Both states take the muted ink and
 * a plain border. The one that reads the wire is not green, because the claim "this was observed"
 * belongs to the matrix row under the panel and arrives through partials/ev.ejs with a link to the
 * artefact. A second green thing up here, saying something adjacent but different, is how a reader
 * ends up believing the page checked more than it did.
 */
.evx-source {
  justify-self: start;
  font-size: var(--t-label);
  line-height: var(--t-label-line);
  color: var(--ink-2);
  border: 1px solid var(--hairline);
  border-radius: var(--pill);
  padding: 2px var(--s3);
}
.evx-source[data-reads="artefact"] { border-color: var(--teal-dark); color: var(--ink); }

/* The declared half. No mark, no wash, no state colour: this is what the estate says, not what the
   wire showed. */
.evx-declared { display: grid; gap: var(--s4); }
/* THE EDGE TAKES THE COMPONENT'S HUE, which is the same edge the artefact card takes from its
   stage. A declaration workspace has no stage to draw, so the edge would otherwise be the only
   grey rule inside a panel the tile lit in colour. It is an edge and not a mark: the sentence
   beside it says this tenant publishes no artefact, and nothing in this block carries an evidence
   label at all, which is the rule the declaration workspaces are built on. */
.evx-absent { margin: 0; color: var(--ink); border-left: 3px solid var(--pick); padding-left: var(--s4); max-width: 72ch; }
.evx-declared-rows { margin: 0; display: grid; gap: 0; }
.evx-declared-row { display: grid; grid-template-columns: minmax(0, 20rem) minmax(0, 1fr); gap: var(--s4); padding: var(--s3) 0; border-top: 1px solid var(--hairline); }
.evx-declared-row dt { margin: 0; color: var(--ink-2); }
.evx-declared-row dd { margin: 0; color: var(--ink); overflow-wrap: anywhere; }

/* The artefact chooser, when an instrument carries more than one. */
.evx-choose { display: flex; flex-wrap: wrap; gap: var(--s2); }
.evx-chip {
  font-size: var(--t-label);
  line-height: var(--t-label-line);
  font-weight: var(--t-label-weight);
  color: var(--ink-2);
  background: var(--paper-alt);
  border: 1px solid var(--rule);
  border-radius: var(--pill);
  padding: var(--s2) var(--s4);
  cursor: pointer;
  min-height: 36px;
}
.evx-chip:hover { color: var(--ink); border-color: var(--teal-dark); }
.evx-chip.is-current { background: var(--wash-teal); border-color: var(--teal-dark); color: var(--ink); }

.evx-artefact { display: grid; gap: var(--s4); }
.evx-artefact[hidden] { display: none; }

/* The facts strip. What it is, who publishes it, when it was last read on the wire, when this
   browser read it, and how the matrix supports it. */
.evx-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: var(--s4); border-top: 1px solid var(--hairline); border-bottom: 1px solid var(--hairline); padding: var(--s4) 0; }
.evx-fact { display: grid; gap: var(--s1); align-content: start; }
.evx-fact-term { color: var(--ink-2); }
.evx-fact-value { color: var(--ink); overflow-wrap: anywhere; }
.evx-fact-ev { grid-column: span 2; }

/* ---- The reveals ------------------------------------------------------------------------------
 * Four ways into the artefact, none of them open. The strip that stood here was a tab row whose
 * first tab was always selected, so a card opened on six hundred pixels of decoded claims before a
 * reader had been told what they were looking at. Pressing the open one closes it again, which is
 * why the control cannot behave as a plain tab list even though it carries that role. */
.evx-reveals { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); }
/* THEY ARE DRAWN AS CONTROLS AND NOT AS TABS. A tab strip says one of these is showing, and on this
   card none of them is until a reader presses one. An outlined chip says press me, which is what
   they are: the same shape the artefact chooser above them already uses. */
.evx-reveal {
  font-size: var(--t-label);
  line-height: var(--t-label-line);
  font-weight: var(--t-label-weight);
  color: var(--ink-2);
  background: var(--paper-alt);
  border: 1px solid var(--rule);
  border-radius: var(--r-2);
  padding: var(--s2) var(--s4);
  cursor: pointer;
  min-height: 40px;
}
.evx-reveal:hover { color: var(--ink); border-color: var(--teal-dark); }
.evx-reveal.is-current { background: var(--wash-teal); border-color: var(--teal-dark); color: var(--teal-dark); }
.evx-copy[hidden] { display: none; }
/* COPY IS THE ONE ACTION IN THE PANEL, so it is drawn as the site's outlined action: a full pill, a
   brand border at low alpha, the brand bright as the label, and --wash-teal as the hover ground.
   That is packages/ui/src/parts/mast.css `.masthead-cta` and packages/ui/src/parts/rw.css
   `.rw-btn-quiet`, and this control used to be a grey outlined rectangle that read as a fourth tab.
   The hover ground is a flat token, because the label sits on it and the contrast gate names pairs
   by name and can read nothing through a colour-mix. The border is a mix, which is allowed: no text
   lands on a border. */
.evx-copy {
  margin-left: auto;
  font-size: var(--t-label);
  line-height: var(--t-label-line);
  font-weight: var(--t-label-weight);
  color: var(--brand-strong);
  background: transparent;
  border: 1px solid color-mix(in srgb, var(--teal-dark) 70%, transparent);
  border-radius: var(--pill);
  padding: var(--s2) var(--s4);
  cursor: pointer;
  min-height: 36px;
}
.evx-copy:hover { background: var(--wash-teal); border-color: var(--teal-dark); }

.evx-code { border: 1px solid var(--rule); border-radius: var(--r-2); max-height: clamp(320px, 46vh, 520px); }
/* THE PLAIN READING WRAPS AND THE ARTEFACT DOES NOT, and the two now share a container that scrolls
   sideways, so the split has to be stated here.
   WHY IT BROKE. packages/ui/src/parts/evidence.css sets `.ev-code code { white-space: pre }`, which
   is right for the artefact: a wrapped line changes what the bytes look like to somebody checking
   them. The plain reading beside it prints identifiers in the same `code` font inside sentences, and
   an issuer identifier is 96 characters with no space in it. Measured at 390 with the reading as the
   panel's first tab: the claims column resolved to an 805px track inside a 316px box, so a reader on
   a phone had to scroll sideways to read prose. It was reachable before and it is the default now,
   which is what turned a corner into the first thing a reader meets.
   The grid track is named as well as the wrapping, because `overflow-wrap` lowers what a box can
   shrink to and an auto track still resolves to max-content without it. */
.evx-code .ev-claims { grid-template-columns: minmax(0, 1fr); }
.evx-code .ev-claim-value code,
.evx-code .ev-claim-key,
.evx-code .ev-op code { white-space: normal; overflow-wrap: anywhere; }
.evx-api-note { margin: 0; color: var(--ink-2); }
/* THE ARTEFACT BLOCK IS A `div` AND NOT A `pre`, which is a shape decision rather than a styling
   one: a `pre` block is the documentation form this route carried thirty nine of. The whitespace
   and the face come from packages/ui/src/parts/evidence.css `.ev-code code`, which already sets
   `white-space: pre` on the code element inside, so a reader sees the same bytes in the same
   columns and the page carries no preformatted block. */
.evx-block { margin: 0; }
.evx-code .evx-block[hidden] { display: none; }

/* ---- The artefact card ------------------------------------------------------------------------
 * The default view of an artefact, and it states what the artefact PROVES. The name, what it is,
 * the claim it supports, who publishes it and when it was read. The artefact itself is under the
 * reveals below it.
 *
 * THE STAGE WORD CARRIES THE HUE AND THE FACTS STRIP UNDER IT CARRIES THE MARK. They are two
 * vocabularies and they are two parts of the card, for the reason written at the top of this file. */
/* THE HUE IS ON THE LEFT EDGE AND NOT ON THE TOP, and the two were both drawn before this was
   settled. A rule across the top of the card sits directly under the artefact chips and reads as a
   divider between the two, which is a line saying something about the chips. The left edge is the
   same mark a ledger row carries, so one hue has one shape on this page. */
.evx-proof { display: grid; gap: var(--s4); border-left: 3px solid var(--stage); padding-left: var(--s4); }
.evx-proof[hidden] { display: none; }
.evx-proof-head { display: grid; gap: var(--s2); }
.evx-proof-stage { margin: 0; color: var(--stage); text-transform: uppercase; letter-spacing: 0.08em; }
.evx-proof-title { margin: 0; font-size: var(--t-h3); line-height: var(--t-h3-line); font-weight: 700; color: var(--ink); }
.evx-proof-what { margin: 0; color: var(--ink-lead); max-width: 68ch; }
.evx-proof-supports { margin: 0; color: var(--ink-2); display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s2); }
/* 24px MINIMUM for WCAG 2.2 clause 2.5.8, the rule packages/ui/src/parts/ev-page.css states for the
   two link lists on this page. This link is one line of its own, so neither exemption applies. */
.evx-proof-supports a { display: inline-flex; align-items: center; min-height: 24px; overflow-wrap: anywhere; }

/* ---- Level three: the evidence index ---------------------------------------------------------- */
/* ONE TRACK THAT CAN BE NARROWER THAN ITS CONTENT, on all three. An `auto` track takes the
   max-content width of what sits in it, so the 30rem search box below set the width of the whole
   index: measured at 390 wide, `.evx-index` was 350 and its track 539, and the document scrolled
   sideways by 169px. The measure on the search box is capped by the container as well, because a
   fixed 480 in a 350 box is the thing the track was sizing itself to. */
.evx-ledger { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s4); }
.evx-controls { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s3); }
.evx-controls[hidden] { display: none; }
.evx-search { margin: 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s2); max-width: min(100%, 30rem); }
.evx-search-label { color: var(--ink-2); }
.evx-search-input {
  font: inherit;
  font-size: var(--t-body);
  color: var(--ink);
  background: var(--paper-alt);
  border: 1px solid var(--rule);
  border-radius: var(--r-1);
  padding: var(--s3) var(--s4);
  min-height: 44px;
}
.evx-search-input::placeholder { color: var(--ink-2); }
.evx-filters { display: flex; flex-wrap: wrap; gap: var(--s2); }
.evx-filter {
  font-size: var(--t-label);
  line-height: var(--t-label-line);
  font-weight: var(--t-label-weight);
  color: var(--ink-2);
  background: var(--paper-alt);
  border: 1px solid var(--rule);
  border-radius: var(--pill);
  padding: var(--s2) var(--s4);
  cursor: pointer;
  min-height: 36px;
}
.evx-filter:hover { color: var(--ink); border-color: var(--teal-dark); }
.evx-filter.is-current { background: var(--wash-teal); border-color: var(--teal-dark); color: var(--ink); }
.evx-filter-count { color: var(--ink-2); font-variant-numeric: tabular-nums; }
.evx-filter.is-current .evx-filter-count { color: var(--ink); }
.evx-shown { margin: 0; color: var(--ink-2); }

/* One track that can be narrower than its content, for the reason recorded on `.evx-ledger` above.
   The rows inside are `display: flex; flex-wrap: wrap`, whose max-content width is every cell on
   one unwrapped line: 539px at a 390 viewport, in a box 350 wide. */
.evx-rows { display: grid; grid-template-columns: minmax(0, 1fr); }
/* ---- The ledger -------------------------------------------------------------------------------
 * Eleven claims in four stage groups. The Stage column is gone: the word was printed eleven times
 * and sorted nothing, and a heading over each group prints it four times and gives the hue a place
 * to sit that is nowhere near the evidence mark.
 *
 * A ROW IS A BUTTON AND A PANEL, NOT A DRAWER. `details` is the documentation shape this rebuild
 * removed from the page. The panel carries `hidden` in the markup and the page's `noscript` block
 * puts every panel back for a reader with no script, so no control here can lie about what it does.
 */
.evx-group { display: grid; gap: var(--s2); margin-top: var(--s5); }
.evx-group[hidden] { display: none; }
.evx-group-head {
  margin: 0;
  color: var(--stage);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  border-left: 3px solid var(--stage);
  padding-left: var(--s3);
}
.evx-lrow { border-top: 1px solid var(--hairline); border-left: 3px solid var(--stage); padding-left: var(--s3); }
.evx-lrow:last-child { border-bottom: 1px solid var(--hairline); }
.evx-lrow[hidden] { display: none; }

/* THE FOUR COLUMNS, RE-PROPORTIONED AFTER THE STAGE AND THE SYSTEM CAME OUT OF THE ROW.
 *   THE EVIDENCE LABEL NEVER WRAPS. "Not observed on this tenant" needs 212px and this route is the
 *     legend for that vocabulary, so a label broken over two lines costs a reader meaning.
 *   THE CLAIM KEEPS THE LARGEST SHARE, because it is the sentence a reader scans.
 *   THE DATE IS ONE WORD AND DOES NOT BREAK: a hyphen is a break opportunity and the column split
 *     "2026-09-09" after the year at the old measure. */
.evx-open {
  font: inherit;
  text-align: left;
  background: none;
  border: 0;
  cursor: pointer;
  width: 100%;
  color: var(--ink);
}
.evx-open-tri { width: 0; height: 0; border-top: 6px solid transparent; border-bottom: 6px solid transparent; border-left: 8px solid var(--teal-dark); transition: transform var(--m-drawer) ease; flex: none; }
.evx-open[aria-expanded="true"] .evx-open-tri { transform: rotate(90deg); }
.evx-lsummary {
  display: grid;
  grid-template-columns: 14px minmax(0, 3.95fr) minmax(0, 2.35fr) minmax(0, 0.95fr);
  align-items: center;
  gap: var(--s3);
  min-height: 56px;
  padding: var(--s3) var(--s3) var(--s3) 0;
}
.evx-lsummary:hover .evx-cell-claim { color: var(--teal-dark); }
.evx-cell { min-width: 0; }
.evx-cell-claim { font-size: var(--t-body); font-weight: 600; color: var(--ink); }
.evx-cell-checked { color: var(--ink-2); white-space: nowrap; }
.evx-cell-ev { display: flex; }

/* ---- "Not observed on this tenant" is an absence, and it stopped drawing as a refusal -----------
 *
 * WHAT RALPH SAW. The Trust mark card under the Accreditation tile carries this label beside a last
 * read date, and it drew in rgb(250, 85, 92): "don't know why this is red but that's not good".
 *
 * WHY IT WAS RED. packages/ui/src/ui.css writes `.ev[data-ev="not-observed"] { color: var(--no); }`
 * and packages/ui/tokens/tokens.json gives the evidence word the `no` colour, whose own role line
 * reads "Refused, withdrawn, stopped, gone, not found." Three of those five words are events. This
 * label is none of them: the design requires the thing, the tenant does not show it today, and the
 * row links what the wire returns instead. A refusal and an absence must not look the same, and on
 * this page they were the same colour.
 *
 * WHAT IT DRAWS NOW. The muted ink, on the label and on the cross it inherits. Beside it,
 * "Deployment evidence" keeps the primary ink with a muted hollow circle, so the two quiet labels
 * are still told apart by weight of ink and by silhouette rather than by one of them shouting.
 *
 * WHY THIS IS SCOPED TO .evx AND NOT FIXED AT THE TOKEN. The colour is decided in
 * packages/ui/src/ui.css, which is the shared component sheet, and the same red therefore still
 * draws on /use-cases/when-something-changes, which is the only other route that renders this label
 * (measured 16 September 2026: six marks here, two there, none on the other fifteen routes). That
 * file is not this agent's to edit, so the global change is a message to the lead and this rule is
 * the page Ralph asked about. One class heavier than ui.css's own selector, which is what makes it
 * win without touching the shared sheet.
 */
.evx .ev[data-ev="not-observed"] { color: var(--ink-2); }
/* THE OPEN ROW'S BODY, AND EVERY WIDTH ON IT IS BOUNDED BY THE ROW. It is a flex item of a
   wrapping row and a grid of one auto track, so without these three it took its max-content width
   twice over: the track grew to its longest line and the item refused to shrink below it. Measured
   at 390: the body was 397px inside a row 350 wide. `min-width: 0` lets the flex item shrink,
   `minmax(0, 1fr)` lets the track shrink, and the measure is capped by the container as well as by
   the 80ch it wants on a wide screen. */
.evx-body {
  padding: 0 0 var(--s5) calc(14px + var(--s3));
  display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s4);
  min-width: 0; width: 100%; max-width: min(100%, 80ch);
}
.evx-claim-full { margin: 0; color: var(--ink); }
/* The last track on this chain, and the same rule as the four above it: one column that can be
   narrower than its content. The `pre` inside carries a base64url segment on one line. */
.evx-detail { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s2); }

/* AN IDENTIFIER IN A SENTENCE BREAKS RATHER THAN PUSHING THE PAGE SIDEWAYS. These paragraphs name
   entity identifiers, key ids and URLs inline, and a string with no space in it sets the minimum
   width of the box that holds it. Measured at 390: `p.evx-answered` was 312px wide with a content
   width of 501, painted straight out of the page, and the document scrolled to 559.
   `anywhere` rather than `break-word`: both break the long word, and only `anywhere` also lowers
   the min-content width, which is what the grid tracks above resolve against. */
.evx-body p, .evx-body li, .evx-body dd, .evx-cell { overflow-wrap: anywhere; }
.evx-detail-head { margin: 0; color: var(--ink-2); text-transform: uppercase; }
.evx-artefacts { margin: 0; padding-left: var(--s5); display: grid; gap: var(--s2); color: var(--ink-2); }
.evx-artefacts a { overflow-wrap: anywhere; }
.evx-detail .evx-block { margin: 0; background: var(--paper); border: 1px solid var(--rule); border-radius: var(--r-1); padding: var(--s3) var(--s4); overflow-x: auto; }
.evx-answered, .evx-pages { margin: 0; color: var(--ink-2); }
/* The limitation is the row's own caveat and it is drawn no quieter than the claim above it. A
   caveat in a lighter ink than the thing it qualifies is a caveat somebody chose to soften. */
.evx-limit { margin: 0; color: var(--ink); }
.evx-empty { margin: 0; color: var(--ink-2); }
.evx-empty[hidden] { display: none; }

/* ---- The close ---------------------------------------------------------------------------------
 *
 * WHAT IT REPLACED. A wrapping row of four links, each with a line under it, over a bare command.
 * That row was the reference route's own ending and it is the wrong ending for this site: every
 * other interior page here finishes on one bordered panel that asks the working question and
 * carries the one action. A page whose whole subject is proof, ending on a shell command with
 * nothing to do next, trails off.
 *
 * THE RECIPE IS .arc-panel IN packages/ui/src/parts/arch-page.css, COPIED RATHER THAN APPROXIMATED.
 * A 1fr and 320px grid on a 32px gutter, 32px of padding, a 16px radius, the alternate ground and
 * one hairline. A 24px heading capped at 24ch, a lead under it at small size, the filled pill 24px
 * lower. The second column is headed at label size with 12px between its links, and every link is
 * 24px tall for WCAG 2.2 clause 2.5.8, which no exemption covers here: each row is one link with no
 * sentence around it and the rows sit closer than 24px apart.
 *
 * WHAT IT REFUSES TO DRAW. Any evidence mark, any count, any state colour. Nothing in this band is
 * read from the wire, so green, amber and red are all absent by construction: the band's only
 * accents are the brand on the button and on a link, which every page on this site wears.
 */
/* THE BAND'S OWN SPACING, WRITTEN AT TWO CLASSES ON PURPOSE. packages/ui/src/parts/ev-page.css sets
   `.evx .band { padding-block: 0 }` and then gives each band its space back by name. This file is
   read after that one, so `.evx .evx-close` at the same specificity wins, and a one class selector
   here would lose to it and the band would sit flush against the index above it. */
.evx .evx-close { display: block; padding-block: var(--s7) var(--s8); }
.evx-close-panel {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: var(--s6);
  padding: var(--s6);
  border: 1px solid var(--rule);
  border-radius: 16px;
  background: var(--paper-alt);
}
.evx-close-h {
  margin: 0;
  font-size: 24px; line-height: 1.25; font-weight: 700; letter-spacing: -0.02em;
  max-width: 28ch;
  color: var(--ink);
}
/* --ink-lead is one step above secondary text and it is what the reference sets on every lead. */
.evx-close-line { margin: var(--s2) 0 0; max-width: 44ch; font-size: var(--t-small); line-height: 1.6; color: var(--ink-lead); }
.evx-close-btn { margin-top: var(--s5); }
.evx-close-side-h { margin: 0; font-size: var(--t-label); font-weight: 600; line-height: 1.4; color: var(--ink); }
.evx-close-links { list-style: none; margin: var(--s4) 0 0; padding: 0; display: grid; gap: var(--s3); }
/* 24px MINIMUM, for WCAG 2.2 clause 2.5.8. Neither exemption applies: each row is one link with no
   sentence around it, and the rows sit 12px apart, so the 24px target circles would intersect. */
.evx-close-links a {
  display: inline-flex; align-items: center; gap: var(--s2);
  min-height: 24px;
  font-size: var(--t-label); line-height: 1.4;
  color: var(--teal-dark); text-decoration: none;
  overflow-wrap: anywhere;
}
/* The same arrow every other link on this site draws, so one kind of thing keeps one glyph. */
.evx-close-links a::before {
  content: ""; display: block;
  width: 16px; height: 11px; flex: none;
  background: currentColor;
  -webkit-mask: var(--arrow-right) center / contain no-repeat;
  mask: var(--arrow-right) center / contain no-repeat;
}
.evx-close-links a:hover { text-decoration: underline; text-underline-offset: 0.14em; }
/* THE COMMAND WRAPS AND EVERY OTHER BLOCK ON THIS PAGE SCROLLS, which is a deliberate split rather
   than an inconsistency. The blocks on an artefact card hold artefacts, where a wrapped line changes
   what the bytes look like to a reader checking them. This one is a command to copy, in a 320px
   column, and at that width a horizontal scroller shows about four words of it. It is a `div` and
   not a `pre` for the reason written against .evx-block above. */
.evx-close-cmd {
  margin: var(--s4) 0 0;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--r-1);
  padding: var(--s3) var(--s4);
  color: var(--ink-2);
}
.evx-close-cmd code { white-space: pre-wrap; overflow-wrap: anywhere; }

@media (max-width: 1000px) {
  /* The figure swaps drawings here rather than scaling. The wide one needs 860px to keep its
     labels at the 14px floor and the container is under that from this width down. */
  .evx-sp-wide { display: none; }
  .evx-sp-narrow { display: block; }
  .evx-picker { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  /* The tray wraps to two cells a row. It has no internal dividers at any width: the cells are
     five figures rather than five positions of one control, so nothing separates them but the gap
     the tray already carries. */
  .evx-lsummary { grid-template-columns: 14px minmax(0, 1fr); grid-auto-rows: min-content; row-gap: var(--s2); }
  .evx-cell-checked, .evx-cell-ev { grid-column: 2; }
  .evx-close-panel { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 700px) {
  .evx-picker { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .evx-work { padding: var(--s4); }
  .evx-declared-row { grid-template-columns: minmax(0, 1fr); gap: var(--s1); }
  .evx-close-panel { padding: var(--s5); }
  .evx-fact-ev { grid-column: auto; }
  /* The bar loses its pill at phone width. Three lines of text inside a 999px radius leaves the
     first and last line indented by half the line height, which reads as a mistake. */
  .evx-sp-note { border-radius: var(--r-2); padding: var(--s4); }
}

@media (prefers-reduced-motion: reduce) {
  .evx-open-tri { transition: none; }
  .evx-open[aria-expanded="true"] .evx-open-tri { transform: rotate(90deg); }
  .evx-tile { transition: none; }
}

/* The label legend. A reader wants it at the moment they press a filter and ask what it selects,
   so it sits over the groups rather than in a band above them. It is a key and not a claim, which
   is why it is a bordered tray rather than a row: drawn as a row it read as claim zero, sitting
   above the eleven with an empty date and an empty system, which is what a reader takes for a
   broken row. */
.evx-legend { border: 1px solid var(--rule); border-radius: var(--r-2); background: var(--paper-alt); padding: 0 var(--s4); }
.evx-legend-open { display: flex; align-items: center; gap: var(--s3); min-height: 44px; font-size: var(--t-small); font-weight: 600; }
.evx-legend-open:hover { color: var(--teal-dark); }
.evx-legend .evx-body { padding: 0 0 var(--s4); }
.evx-legend-rows { margin: 0; display: grid; gap: var(--s3); }
.evx-legend-item { display: grid; grid-template-columns: minmax(0, 16rem) minmax(0, 1fr); gap: var(--s4); align-items: baseline; }
.evx-legend-item dt, .evx-legend-item dd { margin: 0; }
.evx-legend-item dd { color: var(--ink); }

@media (max-width: 700px) {
  .evx-legend-item { grid-template-columns: minmax(0, 1fr); gap: var(--s1); }
}

/* ---- src/parts/evb.css ---- */
/* THE CLAIM BOARD on /evidence. packages/ui/partials/evb-board.ejs draws it.
 *
 * Four stage columns, one card per claim. The stage hue is identity and lives on the pedestal, the
 * column head and the card's lit top edge. The evidence mark is state and lives inside the card
 * beside its word, coloured by the site's own `.ev[data-ev]` rules and by nothing in this file.
 *
 * THE STAGE HUES ARE THE SAME MAP THE LEDGER UNDER THE BOARD USES (ev.css, `.evx [data-stage]`), so
 * a claim sits under the same colour in the figure and in the list. They are restated here under
 * `.evb` so the gallery, which has no `.evx` wrapper, draws the same figure.
 */
.evb { --evb-hue: var(--rule); position: relative; margin: 0; display: grid; gap: var(--s5); }
.evb [data-stage="govern"], .evb [data-stage="authorise"] { --evb-hue: var(--d-blue); }
.evb [data-stage="discover"], .evb [data-stage="identify"] { --evb-hue: var(--d-violet); }
.evb [data-stage="revoke"] { --evb-hue: var(--d-sand); }
.evb [data-stage="keys"], .evb [data-stage="attest"] { --evb-hue: var(--d-magenta); }

.evb > * { position: relative; z-index: 1; }
.evb > .evb-glow { position: absolute; z-index: 0; top: 30%; left: 50%; transform: translateX(-50%); width: 90%; max-width: none; }

/* THE KEY. The four evidence words, each beside its silhouette in the muted ink. No state colour
   and no count: a coloured mark here would link nothing, and the counts are the filter row's. */
.evb-key { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s2) var(--s5); }
.evb-key-i { display: inline-flex; align-items: center; gap: var(--s2); font-size: 14px; font-weight: 600; color: var(--ink-2); white-space: nowrap; }
.evb-key-i .mark { width: 14px; height: 14px; color: var(--ink-2); }

.evb-cols { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s4); align-items: start; }
.evb-col { --hue: var(--evb-hue); display: grid; gap: var(--s3); min-width: 0; }

.evb-head { display: grid; justify-items: center; gap: 2px; text-align: center; }
.evb-head .evb-ped { margin-bottom: var(--s1); }
.evb-h { margin: 0; font-weight: 600; letter-spacing: 0.22em; text-transform: uppercase; color: var(--evb-hue); font-size: 14px; }
.evb-n { margin: 0; font-size: 14px; color: var(--ink-2); }

.evb-cards { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s3); }

/* THE CARD, the reference's environment card: a vertical gradient, a hairline, and the top edge lit
   in the stage hue. The hue stops at the top edge; the row the mark sits on carries none of it. */
.evb-card {
  position: relative; border-radius: 10px; min-width: 0;
  border: 1px solid color-mix(in srgb, var(--ink) 10%, transparent);
  border-top-color: color-mix(in srgb, var(--evb-hue) 55%, transparent);
  background: linear-gradient(180deg, color-mix(in srgb, var(--evb-hue) 7%, var(--paper-alt, transparent)) 0%, var(--paper, transparent) 100%);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--evb-hue) 40%, transparent);
  transition: border-color var(--m-drawer, 160ms) ease, transform var(--m-drawer, 160ms) ease;
}
.evb-card:hover { border-color: color-mix(in srgb, var(--evb-hue) 45%, transparent); transform: translateY(-1px); }
.evb-link { display: grid; gap: var(--s3); padding: var(--s4); color: var(--ink); text-decoration: none; min-height: 100%; }
.evb-link:focus-visible { outline: 2px solid var(--teal-dark); outline-offset: 2px; border-radius: 10px; }
.evb-claim { font-size: 15px; font-weight: 600; line-height: 1.35; overflow-wrap: anywhere; }
.evb-link:hover .evb-claim { color: var(--teal-dark); }
.evb-foot { display: grid; justify-items: start; gap: var(--s1); padding-top: var(--s3); border-top: 1px solid var(--hairline); }
.evb-foot .ev { font-size: 14px; white-space: nowrap; }
/* The location an Available chip names ("extended capability") is the chip's own text, and it may
   wrap under the word rather than push the card wider. */
.evb-foot .ev .where { white-space: normal; }
.evb-date { font-size: 14px; color: var(--ink-2); white-space: nowrap; font-variant-numeric: tabular-nums; }

.evb-cap { margin: 0; text-align: center; font-size: 14px; color: var(--ink-2); }

/* THE NARROW STATES. Four columns need about 900px to hold a label on one line. Under that each
   stage becomes a band: the pedestal and the head on the left, the cards in a grid on the right. */
@media (max-width: 900px) {
  .evb-cols { grid-template-columns: minmax(0, 1fr); gap: var(--s5); }
  .evb-col { grid-template-columns: 120px minmax(0, 1fr); align-items: start; gap: var(--s4); padding-top: var(--s4); border-top: 1px solid color-mix(in srgb, var(--evb-hue) 35%, transparent); }
  .evb-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .evb-col { grid-template-columns: minmax(0, 1fr); gap: var(--s3); }
  .evb-head { grid-template-columns: auto 1fr auto; justify-items: start; align-items: center; text-align: left; column-gap: var(--s3); }
  .evb-head .evb-ped { height: 44px; width: 44px; margin: 0; }
  .evb-head .evb-ped::before { width: 44px; height: 30px; filter: blur(14px); }
  .evb-head .evb-ped::after { width: 40px; height: 7px; bottom: 5px; }
  .evb-head .evb-ped .rw-ped-contact { width: 32px; height: 4px; bottom: 6px; }
  .evb-head .evb-ped .rw-ped-i { margin-bottom: 8px; }
  .evb-head .evb-ped .rw-ped-i svg { width: 24px; height: 24px; }
  .evb-cards { grid-template-columns: minmax(0, 1fr); gap: var(--s2); }
  .evb-key { justify-content: flex-start; }
  /* A PHONE READS THE BOARD AS A COMPACT LIST: the claim and its label, no date. The date is one
     press away on the ledger row the card links, and dropping it here halves the board's height. */
  .evb-link { gap: var(--s2); padding: var(--s3) var(--s4); }
  .evb-foot { padding-top: var(--s2); }
  .evb-date { display: none; }
}
@media (prefers-reduced-motion: reduce) { .evb-card { transition: none; } .evb-card:hover { transform: none; } }

/* THE OPEN STATEMENT ON A NOT OBSERVED ROW of the ledger (evx-ledger.ejs). It sits under the row's
   face, aligned with the claim text, and reads at the body measure. */
.evx-claim-open { margin: 0 0 var(--s4); padding-left: calc(14px + var(--s3)); max-width: min(100%, 80ch); color: var(--ink-2); overflow-wrap: anywhere; }

/* THE BOARD'S BAND on /evidence, directly under the hero and one band with it. */
.evx .evx-band-board { position: relative; z-index: 1; border-top: 0; padding-top: var(--s7); }
/* A row reached by its address stops under the masthead rather than behind it. */
.evx .evx-lrow { scroll-margin-top: 128px; }
/* THE BOARD TAKES MORE WIDTH THAN THE PAGE'S READING COLUMN when the screen has it. Four columns in
   the 1036px column leave each card 245px and stretch the tallest column to five cards of three
   lines each; at 1280 the claims set on two lines and the board fits nearer one screen. Fixed
   pixels rather than 100vw, because 100vw counts the scroll bar and would push the page sideways. */
@media (min-width: 1380px) { .evx .evx-band-board { margin-inline: -122px; } }

/* ---- src/parts/evf.css ---- */
/* THE EVIDENCE FIGURES: packages/ui/partials/evf-matrix.ejs and evf-checks.ejs.
 *
 * Two figures any evidence route can declare through `evidenceFigures`, which
 * apps/site/src/views/uc-evidence.ejs reads. They were built for /use-cases/wherever-it-runs/evidence
 * and they are general on purpose: every later evidence route rebuild draws with them.
 *
 * THE TREATMENTS ARE components/diagram-section.tsx's, from the reference build, by class from
 * rw.css: the lit card, the small pedestal, the hub, the ambient pool. This file places them.
 *
 * IDENTITY HUES ONLY. Each subject or group carries its hue in `--hue` on its own element. A hue says
 * which one. Nothing here is a reading from a run, so --ok, --att and --no appear nowhere.
 *
 * EVERY SIZE IS 14PX OR MORE. The reference sets 12.5 and 13 on a card's second line, and the floor
 * is a readability rule, so those hold at 14.
 */

/* rw.css SORTS AFTER THIS FILE, so a rule here that restyles an rw- class at equal weight loses to
   it. Every such rule below names its figure as well: .evf-mx .evf-mx-card, .evf-ck .evf-ck-result.
   Measured before: the result card centred its words under rw-hub's text-align. */

/* ================================================================
   evf-matrix: subjects side by side, the same rows in each.
   ================================================================ */
.evf-mx { position: relative; margin: 0; container-type: inline-size; min-width: 0; }
.evf-mx-glow { top: 60px; }

/* THE ROWS LINE UP ACROSS CARDS BECAUSE THE CARDS SHARE ONE GRID. Each column spans every row of the
   parent grid and passes the tracks down through the card to the list, so a value that wraps to two
   lines in one card moves that row in every card. Measured before this: four independent cards put
   the "In the token" row at four different heights. */
.evf-mx-cards {
  position: relative; z-index: 1;
  display: grid;
  grid-template-columns: repeat(var(--n), minmax(0, 1fr));
  column-gap: var(--s4);
}
.evf-mx-col { display: grid; grid-row: span calc(var(--rows) + 2); grid-template-rows: subgrid; min-width: 0; }
.evf-mx-ped { height: 64px; }
.evf-mx .evf-mx-card {
  display: grid; grid-row: span calc(var(--rows) + 1); grid-template-rows: subgrid;
  padding: var(--s4) var(--s4) var(--s3);
}
.evf-mx-head { padding-bottom: var(--s3); }
.evf-mx-t { margin: 0; font-size: 17px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.evf-mx-s { margin: 4px 0 0; font-size: 14px; line-height: 1.45; color: var(--ink-2); }
.evf-mx-rows { display: grid; grid-row: span var(--rows); grid-template-rows: subgrid; margin: 0; }
.evf-mx-row { padding: 10px 0; border-top: 1px solid var(--hairline); min-width: 0; }
.evf-mx-row dt {
  margin: 0; font-size: 14px; line-height: 1.35; font-weight: 600;
  color: var(--ink-2);
}
.evf-mx-row dd { margin: 4px 0 0; display: flex; gap: var(--s2); align-items: baseline; font-size: 15px; line-height: 1.45; color: var(--ink); min-width: 0; }
.evf-mx-v { min-width: 0; overflow-wrap: anywhere; }
.evf-mx-mono { font-family: var(--mono); font-size: 14px; }

/* THE DOT, for a row whose answer is on or off. Filled is on, hollow is off, and the value beside it
   carries the word. IT IS INK, NOT THE SUBJECT'S HUE. An on or off answer is a state, and a filled
   glowing dot in the workstation's green beside "Passes" read as an Observed mark: a reviewer
   measured rgb(53, 217, 164) on it at 1440. The hue stays on the card's edge and pedestal, where it
   says which subject. */
.evf-mx-dot { flex: 0 0 auto; width: 10px; height: 10px; border-radius: 50%; border: 2px solid var(--ink-2); transform: translateY(1px); }
.evf-mx-dot[data-mark="on"] { background: var(--ink-2); }

/* THE NARROW STATE: A STRIP THE READER SWIPES. The grid keeps its columns and its shared rows and
   scrolls sideways inside the figure, each card 78 per cent of the figure so the next one shows at the
   edge. The page itself never scrolls sideways. The strip is focusable so a keyboard reader can
   scroll it with the arrow keys, and it shows a ring when focused. */
.evf-mx-note { margin: var(--s4) 0 0; font-size: 14px; line-height: 1.5; color: var(--ink-2); }
.evf-mx-cards:focus-visible { outline: 2px solid var(--brand-strong); outline-offset: 4px; border-radius: 12px; }
@container (max-width: 760px) {
  .evf-mx-n4 .evf-mx-cards { grid-template-columns: repeat(var(--n), 78%); overflow-x: auto; scroll-snap-type: x mandatory; padding-bottom: var(--s3); }
  .evf-mx-n4 .evf-mx-col { scroll-snap-align: start; }
}
@container (max-width: 560px) {
  .evf-mx-cards { grid-template-columns: repeat(var(--n), 78%); overflow-x: auto; scroll-snap-type: x mandatory; padding-bottom: var(--s3); }
  .evf-mx-col { scroll-snap-align: start; }
}

/* ================================================================
   evf-checks: ordered groups of checks on one rail, ending in the result.
   ================================================================ */
.evf-ck { position: relative; margin: 0; container-type: inline-size; min-width: 0; }
.evf-ck-glow { top: 120px; }
.evf-ck > * { position: relative; z-index: 1; }
.evf-ck > .evf-ck-glow { position: absolute; z-index: 0; }

.evf-ck-actor {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s3) var(--s4);
  padding: var(--s3) var(--s4);
  border-radius: 12px;
  border: 1px solid var(--hairline);
  border-left: 3px solid var(--hue);
  background: linear-gradient(180deg, var(--paper-alt) 0%, var(--paper) 100%);
}
.evf-ck-actor-i { display: inline-flex; color: var(--hue); filter: drop-shadow(0 0 8px var(--hue)); }
.evf-ck-actor-i svg { width: 30px; height: 30px; }
.evf-ck-actor-w { display: flex; flex-direction: column; flex: 1 1 14rem; min-width: 0; }
.evf-ck-actor-t { font-size: 17px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.evf-ck-actor-l { font-size: 14px; line-height: 1.45; color: var(--ink-2); }
.evf-ck-rule {
  flex: 0 1 auto;
  padding: 4px var(--s3); border-radius: 999px;
  border: 1px solid var(--hairline);
  font-size: 14px; line-height: 1.4; color: var(--ink-2);
}

/* THE PIPELINE. One row of groups, each as wide as its share of the checks, so every node is the
   same width. A line in the group's hue runs through the centres of its nodes, and the lines of
   neighbouring groups meet across the gap, so the run reads as one line in five colours. */
.evf-ck-run { list-style: none; margin: var(--s5) 0 0; padding: 0; display: flex; flex-wrap: wrap; row-gap: var(--s5); min-width: 0; }
/* A GROUP IS NEVER NARROWER THAN 70PX A NODE, OR 100PX FOR ITS TITLE, so a two word label such as "Publisher signature"
   breaks between its words and never inside one, and fourteen nodes still fit one row of the
   evidence route's 1036px measure. Measured before: "Challenge" broke as "Challeng e" at 1440. A
   narrower figure wraps the run to a second row. */
.evf-ck-group { flex: var(--k) 1 max(calc(var(--k) * 70px), 100px); min-width: 0; }
/* THE TITLE KEEPS TWO LINES OF ROOM AND SITS AT THEIR FOOT, so a title that wraps does not push its
   nodes below the nodes of its neighbours. */
.evf-ck-gt { display: flex; align-items: flex-end; min-height: 2.6em; margin: 0 0 var(--s3); padding-inline: 2px; font-size: 14px; line-height: 1.3; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--hue); }
.evf-ck-nodes { list-style: none; margin: 0; padding: 0; display: flex; position: relative; }
.evf-ck-nodes::before { content: ""; position: absolute; left: 0; right: 0; top: 15px; height: 2px; background: var(--hue); opacity: 0.8; box-shadow: 0 0 6px var(--hue); }
.evf-ck-node-i { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: var(--s2); text-align: center; position: relative; padding-inline: 1px; }
.evf-ck-dot {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border-radius: 50%;
  border: 2px solid var(--hue); background: var(--paper);
  box-shadow: 0 0 10px var(--hue);
  font-size: 14px; font-weight: 700; color: var(--ink);
}
.evf-ck-lab { font-size: 14px; line-height: 1.3; color: var(--ink); overflow-wrap: normal; }

.evf-ck .evf-ck-result {
  display: flex; align-items: center; gap: var(--s4); text-align: left;
  margin: var(--s5) 0 0; padding: var(--s4) var(--s5);
}
.evf-ck-result-i { display: inline-flex; color: var(--teal-dark); filter: drop-shadow(0 0 10px var(--teal-dark)); }
.evf-ck-result-i svg { width: 34px; height: 34px; }
.evf-ck-result-w { display: flex; flex-direction: column; min-width: 0; }
.evf-ck-result-t { font-size: 18px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.evf-ck-result-l { font-size: 15px; line-height: 1.5; color: var(--ink-2); }

/* THE DETAIL, in the drawer under the result: number, the name the code refuses with, the sentence. */
.evf-ck > .drawer { margin-top: var(--s4); max-width: none; }
.evf-ck-detail { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s2); }
.evf-ck-detail li { display: grid; grid-template-columns: 2.25rem minmax(0, 16rem) minmax(0, 1fr); gap: var(--s3); align-items: baseline; padding-left: var(--s3); border-left: 3px solid var(--hue); }
.evf-ck-dn { font-size: 14px; font-weight: 700; color: var(--ink); }
.evf-ck-id { font-family: var(--mono); font-size: 14px; line-height: 1.4; color: var(--ink); overflow-wrap: anywhere; background: none; padding: 0; }
.evf-ck-l { font-size: 14px; line-height: 1.45; color: var(--ink-2); }

/* THE NARROW STATE: THE PIPELINE RUNS DOWN. Each group's title, then its nodes one under another on
   one rail in the group's hue, the label beside each node. */
@container (max-width: 760px) {
  /* ONE RAIL, NOT FIVE. The line runs down the whole run in the brand and on into the result card,
     and each group's nodes sit on it; the titles stand to the right of it. Review found five
     separate lines with gaps under each title, the last one short of the result. */
  .evf-ck-run { flex-direction: column; flex-wrap: nowrap; gap: var(--s4); position: relative; }
  .evf-ck-run::before { content: ""; position: absolute; left: 15px; top: 16px; bottom: calc(-1 * var(--s5)); width: 2px; background: var(--teal-dark); opacity: 0.7; box-shadow: 0 0 6px var(--teal-dark); }
  .evf-ck-nodes::before { display: none; }
  .evf-ck-gt { padding-left: 44px; }
  .evf-ck-group { flex: none; }
  .evf-ck-nodes { flex-direction: column; gap: var(--s3); }
  .evf-ck-nodes::before { left: 15px; right: auto; top: 0; bottom: 0; width: 2px; height: auto; }
  .evf-ck-node-i { flex-direction: row; text-align: left; gap: var(--s3); padding-inline: 0; }
  .evf-ck-gt { min-height: 0; }
  .evf-ck-detail li { grid-template-columns: 2rem minmax(0, 1fr); }
  .evf-ck-detail .evf-ck-l { grid-column: 2; }
}

/* ---- src/parts/evidence.css ---- */
/* The artefact reader on /evidence: the JSON block and the plain English column beside it.
 *
 * WHAT IT IS. Two halves of one panel. The left is a signed statement printed as coloured JSON. The
 * right is the same artefact read back in the words a buyer uses, one claim at a time, each with a
 * control that finds its key in the bytes on the left. The shell around them, the count strip, the
 * six way picker, the workspace and the index, is packages/ui/src/parts/ev.css and
 * packages/ui/src/parts/ev-page.css. Markup: packages/ui/partials/ev-instrument.ejs and the
 * translator in apps/site/src/views/evidence.ejs, which writes .ev-claim, .ev-group, .ev-op and the
 * .j- spans from script.
 *
 * WHAT IT NO LONGER DRAWS, AND THIS FILE LOST TWO THIRDS OF ITS LINES ON 16 SEPTEMBER. It used to
 * hold the whole previous page as well: a hero, a band head, a three column viewer, a 250px artefact
 * rail, a fixed height panel, a bordered plain English column, an overview of the four evidence
 * classes as four cards, a stage list and three sets of narrow rules for all of it. That page was
 * replaced by the explorer and every one of those classes stopped being rendered. They stayed here
 * and shipped in the built stylesheet, so /evidence carried about a hundred and thirty rules for
 * markup that no page emits, and the next reader of "the evidence stylesheet" met the old page
 * first. Checked before deleting: the served bytes of /evidence carry ev-block, ev-claim,
 * ev-claim-head, ev-claim-key, ev-claim-term, ev-claim-value, ev-claims, ev-code, ev-group, ev-op,
 * ev-pane, ev-part and the four .j- spans, and no other ev- name. Only those are kept.
 *
 * COLOUR. Nothing here carries a state colour. Green under Observed and nowhere else is a site rule;
 * on this page it is the page's subject, so a tint suggesting a verdict would be a lie in the site's
 * own language. The syntax colours are the brand accent and the two inks, which carry no meaning at
 * all, rather than the state tokens, whose meaning would attach itself to whichever claim happened
 * to be a string.
 *
 * THE CODE GROUND IS A FLAT TOKEN, never a colour-mix. packages/ui/tools/contrast.mjs gates token
 * pairs by name and can read nothing through a mix, so every word in the block would be gated by
 * nothing, and a block of small mono text is the last place on the site to leave unwatched.
 */

/* ---- The artefact, as bytes -------------------------------------------- */
/* A focusable region, because it scrolls in both directions and a keyboard has to reach it. That is
   what axe's scrollable-region-focusable asks for. */
.ev-code { background: var(--paper); margin: 0; overflow: auto; min-height: 0; }
.ev-code:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: -2px; }
/* THE TRACK IS minmax(0, 1fr) AND NOT auto, WHICH IS WHAT KEEPS THIS BOX INSIDE THE VIEWPORT.
   A grid track sized `auto` takes the max-content width of what sits in it, and a single column
   grid with no template is exactly that. Something inside that will not wrap, a `pre` of one long
   line or a nowrap row, then makes the track wider than the box and the whole document scrolls
   sideways. Measured: /evidence at 390 wide took the document to 559px, because this pane holds a signed statement on one line and the track grew to 8299px. `minmax(0, 1fr)` lets the track be narrower than its content, and the
   scrolling container inside it does its job. */
.ev-pane { padding: var(--s4) var(--s5); display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s2); }
.ev-part { margin: 0; font-size: var(--t-label); font-weight: 600; line-height: var(--t-label-line); color: var(--ink-2); text-transform: uppercase; }
/* EVERY ev-block SCROLLS, WHEREVER IT IS DRAWN. It holds a signed statement, a base64url segment
   or a curl line, which are the longest unbroken strings on this site and cannot wrap. One instance
   had the rule (`.evx-detail pre.ev-block` in ev.css) and the rest did not, so a block outside that
   one container painted its content straight out of the page: measured on /evidence at 390, a 312px
   block held a 1050px line and the document scrolled sideways to 559. The property belongs to the
   block rather than to one of the places it appears. */
.ev-block { overflow-x: auto; max-width: 100%; }
.ev-part + .ev-block { margin-bottom: var(--s4); }
.ev-code pre.ev-block { margin: 0; font-size: 13px; line-height: 1.62; }
.ev-code code { font-family: inherit; white-space: pre; overflow-wrap: normal; display: block; }

/* JSON. Keys take the accent, every value the primary ink, punctuation the secondary ink. One hue
 * and two inks, and no state colour: a string tinted with --att would have said "in progress" about
 * whichever claim happened to be a string.
 *
 * NUMBERS USED TO TAKE --cyan-light AND THAT WAS THE DARK REMAP BOUNDARY BUG, in the shape the lead
 * found in `.raw`. --cyan-light is not one of the names darkCss redefines, so it stayed a light
 * palette value while the ground under it, --paper, became the near black dark ground. It measured
 * 10.65 and was therefore safe, but safe by where the light value happened to sit rather than by
 * design, and no pair in contrast.mjs named it. Every colour here now moves with its ground and
 * every pairing is gated by name: ink on d-ground 15.94, ink-2 on d-ground 6.33, accent on
 * d-ground 10.00. The cost is that a number no longer reads differently from a string; the dates
 * that matter, exp and iat, are printed in words in the column beside this one. */
.ev-code .j-k { color: var(--cyan); }
.ev-code .j-s, .ev-code .j-n { color: var(--ink); }
.ev-code .j-p { color: var(--ink-2); }

/* ---- The same artefact, in plain English ------------------------------- */
.ev-claims { display: grid; gap: var(--s4); }
/* A GROUP HEAD, AND THE GROUPS ARE NOT IN THE ARTEFACT'S OWN ORDER. The payload comes first and the
   header last, because a reader who opens this column wants the ceiling and the superiors; the
   algorithm and the key identifier matter, and they matter second. */
.ev-group {
  margin: var(--s3) 0 0; font-size: var(--t-label); font-weight: 700;
  line-height: var(--t-label-line); letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--teal-dark);
}
.ev-group:first-child { margin-top: 0; }
/* THE SEPARATOR BETWEEN TWO CLAIMS IS --hairline AND NOT --rule. It divides two rows of a reading
   column. Nothing here is a card edge and nothing here is pressed, so losing the line entirely
   would cost a reader nothing, which is this token's definition. --rule drew a bright line between
   every claim and turned the column into a table. */
.ev-group + .ev-claim { border-top: 0; padding-top: 0; }
.ev-claim { display: grid; gap: 3px; padding-top: var(--s3); border-top: 1px solid var(--hairline); }
.ev-claim:first-of-type { border-top: 0; padding-top: 0; }
.ev-claim-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s2); margin: 0; }
.ev-claim-term { font-size: var(--t-label); font-weight: 600; color: var(--ink); }
/* THE CLAIM KEY IS A CONTROL, NOT A LABEL. Pressing it finds the same key in the artefact beside it
   and marks the line, which is the join this page exists to make: this word, that byte. A row whose
   name is not a line of the artefact keeps its name and loses the control, and the script swaps the
   button for a `code` element, which the rule under this one draws without the affordance. */
.ev-claim-key {
  appearance: none; background: transparent; border: 0; padding: 0; cursor: pointer;
  font-family: var(--mono); font-size: var(--t-mono); line-height: var(--t-mono-line);
  color: var(--cyan); text-decoration: underline; text-underline-offset: 2px;
}
code.ev-claim-key { text-decoration: none; cursor: auto; }
/* The line the reader asked for. An outline rather than a colour change: the key keeps the accent
   it has everywhere else in the block, so the mark reads as "here" and never as a verdict. */
.ev-code .j-k.is-found { background: var(--wash-teal); outline: 2px solid var(--teal-dark); border-radius: 2px; }
.ev-claim p { margin: 0; }
.ev-claim-value { color: var(--ink); overflow-wrap: anywhere; }
.ev-claim-value code { color: var(--ink); }
.ev-op { color: var(--ink-2); }
.ev-op code { color: var(--cyan); }

/* ---- Narrow ------------------------------------------------------------
   Nothing scrolls sideways at 390: the block scrolls inside its own focusable box and every long
   identifier breaks. The ceiling stops a sixty line artefact taking a phone screen and a half
   before the reading beside it starts. */
@media (max-width: 1100px) {
  .ev-code { max-height: 420px; }
}
@media (max-width: 560px) {
  .ev-pane { padding: var(--s3) var(--s4); }
}

/* ---- src/parts/fl-films.css ---- */
/* /films and /films/<id>: the film index, the film page, and their two partials,
 * packages/ui/partials/fl-card.ejs and packages/ui/partials/fl-reel.ejs.
 * Views: apps/site/src/views/films.ejs and apps/site/src/views/film.ejs.
 *
 * THE TREATMENTS ARE components/diagram-section.tsx's. No artefact in the reference build draws a
 * film gallery or a player, so the composition is ours and every surface is one of the reference's:
 * the environment card lit from above in its hue, the ringed play mark from its hero pills, the
 * ambient pool behind the instrument, and the uppercase tracked side panel title.
 *
 * THE HUE IS THE USE CASE'S, AND IT IS IDENTITY ONLY. Each card and each reel carries `--hue` on its
 * own element, set from `work.art` in apps/site/content/home.md, so a use case wears one hue on the
 * home page, /use-cases, /working-session and here. No state token appears in this file.
 *
 * THE CARD AND THE REEL CLASSES ARE PREFIXED fl-, and the page rules are scoped under .fl-page,
 * which only the two film views write.
 */

/* ---- THE HERO ---- */
.fl-page .fl-hero { position: relative; overflow: hidden; padding-block: var(--s9) var(--s6); }
.fl-page .fl-hero-in { position: relative; z-index: 1; display: grid; gap: var(--s4); justify-items: start; }
.fl-page .fl-hero-in > * { margin: 0; }
.fl-page .fl-hero .eyebrow { letter-spacing: 0.22em; }
.fl-page .fl-hero .eyebrow a { color: inherit; text-decoration: none; }
.fl-page .fl-hero .eyebrow a:hover { text-decoration: underline; text-underline-offset: 0.18em; }
.fl-page .fl-headline { max-width: var(--measure-display); line-height: 1.02; letter-spacing: -0.035em; }
.fl-page .fl-headline .accent { display: block; }
.fl-page .fl-lead { max-width: 36rem; font-size: 17px; line-height: 1.55; color: var(--ink-lead); }
.fl-page .fl-lead p { margin: 0; }
.fl-page .fl-note { font-size: 15px; color: var(--ink-2); }
.fl-page .fl-actions { display: flex; flex-wrap: wrap; gap: var(--s4); margin-top: var(--s2); }

/* ---- THE GRID ---- */
.fl-page .fl-band-head { display: grid; gap: var(--s2); margin-bottom: var(--s6); }
.fl-page .fl-band-head > * { margin: 0; }
.fl-page .fl-band-head p { font-size: 15px; color: var(--ink-2); }
.fl-grid { display: grid; gap: 24px; grid-template-columns: minmax(0, 1fr); }
@media (min-width: 760px) { .fl-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1190px) { .fl-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* ---- THE CARD: the reference's environment card, lit from above in its hue ---- */
.fl-card {
  position: relative; display: flex; flex-direction: column; min-width: 0;
  border-radius: 16px; overflow: hidden;
  border: 1px solid color-mix(in srgb, var(--hue) 24%, transparent);
  border-top-color: color-mix(in srgb, var(--hue) 55%, transparent);
  background: linear-gradient(180deg, color-mix(in srgb, var(--hue) 10%, transparent), transparent 45%), var(--paper-alt);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--hue) 45%, transparent), 0 24px 60px -30px rgba(0, 0, 0, 0.7);
  transition: border-color 160ms ease, transform 160ms ease;
}
.fl-card:hover { border-color: color-mix(in srgb, var(--hue) 55%, transparent); transform: translateY(-2px); }
.fl-card:focus-within { border-color: color-mix(in srgb, var(--hue) 70%, transparent); }

/* The poster. The frame is the film's own first picture at 16:9, with a pool of the hue rising from
   its foot, so seven dark title cards read as seven films rather than one film seven times. */
.fl-poster {
  position: relative; display: block; aspect-ratio: 16 / 9; overflow: hidden;
  background: var(--paper);
  border-bottom: 1px solid color-mix(in srgb, var(--hue) 30%, transparent);
}
.fl-poster img { display: block; width: 100%; height: 100%; object-fit: cover; transition: transform 400ms ease; }
/* EVERY POSTER ENDS IN A 16 PIXEL BRAND BAR, burnt into the picture. Under a hue of its own the
   bar says every film is the brand's colour, so the frame is cropped to the 1064 rows above it. */
.fl-poster img { height: calc(100% * 1080 / 1064); object-position: top; }
.fl-card:hover .fl-poster img { transform: scale(1.025); }
.fl-poster::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(90% 70% at 70% 110%, color-mix(in srgb, var(--hue) 34%, transparent), transparent 70%);
}
/* The play mark: the reference's ringed triangle, larger, in the hue, standing on a soft glow. */
.fl-play {
  position: absolute; z-index: 1; left: 72%; top: 50%; transform: translate(-50%, -50%);
  display: flex; align-items: center; justify-content: center;
  width: 64px; height: 64px; border-radius: 50%;
  border: 1.5px solid var(--hue);
  background: radial-gradient(circle, color-mix(in srgb, var(--hue) 22%, transparent), color-mix(in srgb, var(--paper) 70%, transparent));
  box-shadow: 0 0 32px color-mix(in srgb, var(--hue) 45%, transparent);
  color: var(--hue);
  transition: transform 160ms ease, box-shadow 160ms ease;
}
.fl-play svg { width: 24px; height: 24px; margin-left: 3px; fill: currentColor; }
.fl-card:hover .fl-play { transform: translate(-50%, -50%) scale(1.08); box-shadow: 0 0 44px color-mix(in srgb, var(--hue) 60%, transparent); }
.fl-runtime {
  position: absolute; z-index: 1; right: 12px; bottom: 12px;
  padding: 3px 9px; border-radius: 999px;
  background: var(--paper); border: 1px solid color-mix(in srgb, var(--hue) 45%, transparent);
  font-family: var(--mono); font-size: 14px; line-height: 1.4; color: var(--ink);
}
.fl-poster-none { background: radial-gradient(80% 90% at 36% 100%, color-mix(in srgb, var(--hue) 16%, transparent), transparent 70%), var(--paper); }
/* THE FRAME WITH NO POSTER: the use case's glyph on its pedestal, left of the play mark, so the two
   do not sit on one another. */
.fl-poster-none .rw-ped { position: absolute; left: 36%; bottom: 22%; transform: translateX(-50%); }

.fl-body { display: flex; flex-direction: column; gap: var(--s3); flex: 1; padding: var(--s5) 22px 22px; }
.fl-body > * { margin: 0; }
.fl-kicker {
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px var(--s3);
  font-size: 14px; font-weight: 600; letter-spacing: 0.18em; text-transform: uppercase; color: var(--hue);
}
.fl-kicker-sep { width: 4px; height: 4px; border-radius: 50%; background: var(--ink-2); }
.fl-kicker-meta { letter-spacing: 0.02em; text-transform: none; font-weight: 500; color: var(--ink-2); }
.fl-q { font-size: 20px; font-weight: 700; line-height: 1.25; color: var(--ink); text-wrap: pretty; }
.fl-q a { color: inherit; text-decoration: none; }
/* THE HEADING IS THE CARD'S ONE CONTROL, and its hit area is the whole card. The use case link in
   the rows sits above this layer, so it stays its own target. */
.fl-q a::after { content: ""; position: absolute; inset: 0; z-index: 2; border-radius: 16px; }
.fl-q a:focus-visible::after { outline: 2px solid var(--brand-strong); outline-offset: 3px; }

.fl-rows { display: grid; gap: 0; margin-top: auto; padding-top: var(--s2); }
.fl-rows > div {
  display: grid; grid-template-columns: 76px minmax(0, 1fr); gap: var(--s3); align-items: baseline;
  padding: 9px 0; border-top: 1px solid var(--hairline);
}
.fl-rows dt { font-size: 14px; font-weight: 600; color: var(--ink-2); }
.fl-rows dd { margin: 0; font-size: 15px; line-height: 1.45; color: var(--ink); }
.fl-rows dd a { position: relative; z-index: 3; color: var(--brand-strong); text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--brand-strong) 40%, transparent); text-underline-offset: 0.18em; }
.fl-rows dd a:hover { text-decoration-color: currentColor; }
.fl-stages { display: flex; flex-wrap: wrap; gap: 6px; }
.fl-stage {
  padding: 1px 9px; border-radius: 999px; font-size: 14px; line-height: 1.5;
  border: 1px solid color-mix(in srgb, var(--hue) 45%, transparent); color: var(--ink);
}

/* ---- THE FEATURE CARD: one wide lead film, poster and copy side by side ---- */
.fl-card-feature .fl-q { font-size: 30px; line-height: 1.15; letter-spacing: -0.02em; }
.fl-card-feature .fl-play { width: 88px; height: 88px; left: 76%; }
.fl-card-feature .fl-play svg { width: 32px; height: 32px; margin-left: 4px; }
/* THE PILL SITS ABOVE THE HEADING'S HIT AREA, so it is its own target on any card that has one. */
.fl-act { position: relative; z-index: 3; margin-top: var(--s2); }
.fl-act .rw-btn { display: inline-flex; align-items: center; gap: var(--s3); }
.fl-act-play { display: flex; align-items: center; justify-content: center; width: 22px; height: 22px; border-radius: 50%; border: 1.5px solid currentColor; }
.fl-act-play svg { width: 11px; height: 11px; margin-left: 2px; fill: currentColor; }
@media (min-width: 1000px) {
  .fl-card-feature { display: grid; grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr); }
  .fl-card-feature .fl-poster { border-bottom: 0; border-right: 1px solid color-mix(in srgb, var(--hue) 30%, transparent); }
  .fl-card-feature .fl-body { padding: var(--s6) var(--s6) var(--s5); justify-content: center; }
  .fl-card-feature .fl-rows { margin-top: var(--s3); }
}
@media (max-width: 640px) {
  .fl-card-feature .fl-q { font-size: 24px; }
  .fl-play, .fl-card-feature .fl-play { width: 56px; height: 56px; left: 76%; }
  .fl-card-feature .fl-play svg { width: 22px; height: 22px; }
}

/* ---- THE INTRODUCTION: two parts side by side, one pair, larger than a grid card ---- */
.fl-intro { display: grid; gap: 24px; grid-template-columns: minmax(0, 1fr); }
@media (min-width: 900px) { .fl-intro { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.fl-card-intro .fl-q { font-size: 26px; line-height: 1.18; letter-spacing: -0.02em; }
.fl-card-intro .fl-play { width: 80px; height: 80px; }
.fl-card-intro .fl-play svg { width: 30px; height: 30px; margin-left: 4px; }
.fl-card-intro .fl-body { padding: var(--s5) var(--s6) var(--s6); }
@media (max-width: 640px) {
  .fl-card-intro .fl-q { font-size: 22px; }
  .fl-card-intro .fl-play { width: 56px; height: 56px; }
  .fl-card-intro .fl-play svg { width: 22px; height: 22px; }
  .fl-card-intro .fl-body { padding: var(--s5) 22px 22px; }
}

/* ---- THE REEL: the film page's instrument ---- */
.fl-reel { position: relative; margin: 0; display: grid; gap: var(--s4); }
/* THE AMBIENT POOL, in the use case's hue. A flat token at an opacity would be the brand; the pool
   is a gradient so it can take the hue, and it carries no text, so the contrast gate has nothing to
   read on it. */
.fl-reel-glow {
  position: absolute; left: 35%; top: 40%; transform: translate(-50%, -50%);
  width: 1100px; max-width: 100%; height: 520px; pointer-events: none; filter: blur(90px); opacity: 0.55;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--hue) 55%, transparent), transparent);
}
.fl-reel-grid { position: relative; display: grid; gap: var(--s5); }
@media (min-width: 1100px) { .fl-reel-grid { grid-template-columns: minmax(0, 1fr) 340px; align-items: start; } .fl-reel-solo { grid-template-columns: minmax(0, 1fr); } }
.fl-reel-screen {
  min-width: 0; overflow: hidden; border-radius: 16px;
  border: 1px solid color-mix(in srgb, var(--hue) 30%, transparent);
  border-top-color: color-mix(in srgb, var(--hue) 65%, transparent);
  background: var(--paper);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--hue) 50%, transparent), 0 0 0 1px rgba(0, 0, 0, 0.2), 0 40px 90px -40px rgba(0, 0, 0, 0.85), 0 0 80px -30px color-mix(in srgb, var(--hue) 60%, transparent);
}
.fl-reel-main { display: grid; gap: var(--s3); min-width: 0; }
.fl-reel-screen .player { margin: 0; border: 0; border-radius: 0; box-shadow: none; }
.fl-reel-screen video { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; background: var(--paper); }
.fl-reel-screen .player-meta { display: flex; justify-content: flex-end; gap: var(--s4); margin: 0; padding: 10px 16px; border-top: 1px solid var(--hairline); font-size: 14px; }
.fl-reel-screen .player-meta:not(:has(*)) { display: none; }

/* The side panel: the reference's side panel, vertical gradient and a tracked title. */
.fl-reel-side {
  position: relative; min-width: 0; border-radius: 16px; padding: var(--s4) var(--s3) var(--s3);
  border: 1px solid color-mix(in srgb, var(--hue) 22%, transparent);
  background: linear-gradient(180deg, color-mix(in srgb, var(--hue) 8%, transparent), transparent 60%), var(--paper-alt);
}
.fl-reel-h {
  display: flex; align-items: center; justify-content: space-between; margin: 0 var(--s2) var(--s3);
  font-size: 14px; font-weight: 600; letter-spacing: 0.2em; text-transform: uppercase; color: var(--ink-2);
}
.fl-reel-count { font-family: var(--mono); letter-spacing: 0; color: var(--hue); }
.fl-chap { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.fl-chap button {
  display: grid; grid-template-columns: 26px minmax(0, 1fr) auto; gap: var(--s3); align-items: center;
  width: 100%; min-height: 44px; padding: 8px var(--s2); border: 0; border-radius: 10px;
  background: transparent; color: var(--ink); font: inherit; text-align: left; cursor: pointer;
}
.fl-chap button:hover { background: var(--surface-panel); }
.fl-chap button:focus-visible { outline: 2px solid var(--brand-strong); outline-offset: 1px; }
.fl-chap-n {
  display: flex; align-items: center; justify-content: center; width: 26px; height: 26px; border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--hue) 45%, transparent);
  font-family: var(--mono); font-size: 14px; color: var(--ink);
}
.fl-chap-t { font-size: 15px; line-height: 1.35; }
.fl-chap time { font-family: var(--mono); font-size: 14px; color: var(--ink-2); }
.fl-chap button.is-now { background: linear-gradient(90deg, color-mix(in srgb, var(--hue) 18%, transparent), transparent), var(--paper-alt); }
.fl-chap button.is-now .fl-chap-n { border-color: var(--hue); box-shadow: 0 0 12px color-mix(in srgb, var(--hue) 55%, transparent); }
@media (min-width: 640px) and (max-width: 1099px) { .fl-chap { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--s3); } }

/* The timeline. One bar, one segment per chapter at its true length, and a fill to the playhead. */
.fl-line {
  position: relative; display: flex; gap: 3px; height: 44px; padding: 3px;
  border-radius: 12px; border: 1px solid var(--hairline); background: var(--paper-alt); overflow: hidden;
}
.fl-line-fill {
  position: absolute; left: 0; top: 0; bottom: 0; width: 0; pointer-events: none;
  background: linear-gradient(90deg, color-mix(in srgb, var(--hue) 10%, transparent), color-mix(in srgb, var(--hue) 28%, transparent));
  border-right: 2px solid var(--hue);
}
.fl-seg {
  position: relative; flex-basis: 0; min-width: 0; overflow: hidden; padding: 0; border: 0; border-radius: 8px; cursor: pointer;
  background: linear-gradient(180deg, color-mix(in srgb, var(--hue) 14%, transparent), color-mix(in srgb, var(--hue) 4%, transparent)), var(--paper);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--hue) 35%, transparent);
  color: var(--ink-2); font-family: var(--mono); font-size: 14px;
}
.fl-seg:hover { color: var(--ink); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--hue) 60%, transparent); }
.fl-seg:focus-visible { outline: 2px solid var(--brand-strong); outline-offset: 2px; }
.fl-seg.is-now { color: var(--ink); box-shadow: inset 0 0 0 1px var(--hue), 0 0 16px color-mix(in srgb, var(--hue) 45%, transparent); }

/* ---- THE FILM PAGE ---- */
.fl-page .fl-top-band { padding-bottom: 0; }
.fl-page .fl-top { position: relative; padding-bottom: var(--s6); display: grid; gap: var(--s3); }
/* THE PLAYER BELONGS TO THE HEADING ABOVE IT, so the two share one band and no rule parts them. */
.fl-page .fl-reel-band { padding-top: 0; border-top: 0; }
.fl-page .fl-top > * { margin: 0; }
.fl-page .fl-top .eyebrow { letter-spacing: 0.22em; color: var(--hue); }
.fl-page .fl-top .eyebrow a { color: inherit; text-decoration: none; }
.fl-page .fl-top .eyebrow a:hover { text-decoration: underline; text-underline-offset: 0.18em; }
.fl-page .fl-top-h { max-width: var(--measure-display); line-height: 1.02; letter-spacing: -0.035em; }
.fl-page .fl-meta { display: flex; flex-wrap: wrap; gap: 6px var(--s4); font-size: 15px; color: var(--ink-2); }
.fl-page .fl-meta span + span::before { content: ""; display: inline-block; width: 4px; height: 4px; margin-right: var(--s4); border-radius: 50%; background: var(--ink-2); vertical-align: middle; }
.fl-page .fl-meta a { color: var(--brand-strong); text-underline-offset: 0.18em; }
@media (max-width: 640px) {
  /* One fact per line at a phone width, so no separator dot starts a wrapped line. */
  .fl-page .fl-meta { display: grid; gap: 4px; }
  .fl-page .fl-meta span + span::before { display: none; }
}

.fl-page .fl-transcript { margin-top: var(--s5); }
.fl-page .fl-transcript section + section { margin-top: var(--s5); }
.fl-page .fl-transcript h2 { display: flex; gap: var(--s3); align-items: baseline; margin: 0 0 var(--s2); font-size: 17px; font-weight: 700; line-height: 1.4; letter-spacing: 0; color: var(--ink); }
.fl-page .fl-transcript h2 time { font-family: var(--mono); font-size: 14px; font-weight: 500; color: var(--ink-2); }
.fl-page .fl-transcript p { margin: 0; max-width: var(--measure-body); font-size: 16px; line-height: 1.65; color: var(--ink-lead); }

/* The two panels under the reel: the use case the film belongs to, and the next film. */
.fl-page .fl-after { display: grid; gap: 24px; }
@media (min-width: 900px) { .fl-page .fl-after { grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); align-items: start; } }
.fl-page .fl-uc {
  position: relative; display: grid; gap: var(--s3); align-content: start; padding: var(--s6);
  border-radius: 16px; border: 1px solid color-mix(in srgb, var(--hue) 24%, transparent);
  border-top-color: color-mix(in srgb, var(--hue) 55%, transparent);
  background: radial-gradient(120% 100% at 15% 0%, color-mix(in srgb, var(--hue) 13%, transparent), transparent 55%), var(--paper-alt);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--hue) 40%, transparent);
}
.fl-page .fl-uc > * { margin: 0; }
.fl-page .fl-uc-e { font-size: 14px; font-weight: 600; letter-spacing: 0.2em; text-transform: uppercase; color: var(--hue); }
.fl-page .fl-uc-h { font-size: 26px; font-weight: 700; line-height: 1.15; letter-spacing: -0.02em; color: var(--ink); }
.fl-page .fl-uc-l { font-size: 15px; line-height: 1.5; color: var(--ink-2); max-width: 40rem; }
.fl-page .fl-uc .fl-actions { margin-top: var(--s3); }

/* THE CORRECTION LINE. What the film says and what this estate shows, beside the film it corrects.
   It carries no state colour: it states a fact about a film, not a state of the estate, and it is
   written out in words. A hairline and the page's hue at the left edge say it belongs to this film. */
.fl-page .fl-fix {
  display: grid; gap: 6px; max-width: 60rem; margin-top: var(--s2); padding: var(--s4) var(--s5);
  border: 1px solid var(--hairline); border-left: 3px solid var(--hue); border-radius: 12px;
  background: var(--paper-alt);
}
.fl-page .fl-fix > p { margin: 0; font-size: 15px; line-height: 1.55; color: var(--ink-lead); }
.fl-page .fl-fix .fl-fix-e { font-size: 14px; font-weight: 600; letter-spacing: 0.2em; text-transform: uppercase; color: var(--ink-2); }
.fl-page .fl-fix-k { font-weight: 700; color: var(--ink); }
.fl-page .fl-fix a { color: var(--brand-strong); text-underline-offset: 0.18em; }
.fl-page .fl-remade { max-width: 52rem; }

/* ---- src/parts/foot.css ---- */
/* THE FOOTER.
 *
 * WHAT IT IS. The last band of every route, on the target build's shape: one row of link columns,
 * a quiet note, then the bar. The bar is components/site-footer.tsx measured rather than
 * remembered: max width 1536 through .wrap, padding top 48, padding bottom 32, one border top over
 * a 24px gap, a drawn wordmark at 18px, and two uppercase tracked lines, the left in the faintest
 * text and the right in a QUIET brand tint. The target sets that second line to #5ab7c6 and not to
 * its own brand #22d3ee, which it uses everywhere else: at full brand the last line of the page
 * competes with the call to action above it. --slate is that tint and it was declared in tokens.json
 * and mapped by nothing, so it resolved to a light mode value on a dark ground.
 *
 * WHAT IT REFUSES TO DRAW. A ground OF ITS OWN. It sets --paper, which IS the page ground, so the
 * footer paints nothing a reader can see and cannot inherit a card colour from a surface it is
 * dropped inside. An earlier version of this comment said it painted no background at all while the
 * rule below set one, which is the kind of comment that survives the change it describes.
 * A second rule. The target draws one
 * line in the whole footer and ours draws one too, above the bar; the column dividers are hairlines
 * that a reader is not meant to see. A size under 14px. The target sets its two lines at 11px and
 * 14px is this system's floor, so the lines hold the target's weight, tracking and colour and take
 * this system's size.
 *
 * EVERY DIVIDER IS --hairline AND NOT --rule. --rule clears the component floor of 3 and is correct
 * for the edge of a card or anything a person operates. Used on a footer it drew a bright band
 * across the bottom of every page, where the target's line is almost not there.
 */

/* 29. Footer */
/* NO TOP MARGIN. It carried 64px, the last band of a page carries its own bottom margin, and the
   two added up to most of a screen of empty page between the last words and the footer. The footer
   opens with its own 48px of padding, which is the target's. */
.site-foot { background: var(--paper); padding-top: var(--s7); padding-bottom: var(--s6); font-size: var(--t-small); color: var(--ink-2); }

/* The link columns. The target has none. This site serves about nineteen routes, so a footer with
   no navigation would strand most of them. Three columns, divided by hairlines. */
.site-foot .foot-cols { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s6); }
.site-foot .foot-col + .foot-col { border-left: 1px solid var(--hairline); padding-left: var(--s6); }
.site-foot .foot-col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s2); }
.site-foot .foot-col a { color: var(--ink-nav); text-decoration: none; }
.site-foot .foot-col a:hover { color: var(--ink); text-decoration: underline; }
.site-foot .foot-title { font-size: var(--t-label); font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-2); margin: 0 0 var(--s3); }

/* The environment note: what this estate is and that its organisations are fictional. It is the
   only place on the site that says so, so it is quiet rather than absent. Held to a reading measure
   so it does not run the full 1536. */
.site-foot .foot-note { margin-top: var(--s6); max-width: 92ch; }
.site-foot .foot-note a { color: var(--teal-dark); }
/* --ink-2 AND NOT --faint. --faint is #5f748f and reaches 4.17 against the page ground, under the
   4.5 this system holds normal text to, and its declared role is the one uppercase line in the bar.
   These paragraphs are the only place on the site that says Tarnbrook, Aldercross, Quillon and
   Larkspur are invented, so they are the last text here that may be hard to read. */
.site-foot .foot-note { font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-2); }

/* The bar. One rule over a 24px gap, then the wordmark and the two lines. */
.site-foot .foot-bar { margin-top: var(--s7); padding-top: var(--s5); border-top: 1px solid var(--hairline); display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s3) var(--s5); }
.site-foot .foot-bar-left { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s5); }

/* The Raidiam logo, the same asset the masthead draws, at the height the target gives its own
   footer mark. See the note in packages/ui/src/parts/mast.css for why the target's drawn word is
   not used here. */
.site-foot .foot-mark { height: 18px; width: auto; display: block; }

/* The two lines. The target sets 11px weight 500 uppercase on 0.22em tracking; the size holds at
   the 14px floor and everything else is the target's. */
/* --ink-2 AND NOT --faint, WHICH IS THE TARGET'S VALUE AND FAILS HERE. The target sets this line at
   #5f748f, 11px, uppercase. At 11px that is decorative; at this system's 14px floor it is running
   text, and #5f748f reaches 4.17 against the page ground where normal text is held to 4.5. Axe
   named it as a serious violation on seven explorer routes. The weight, the tracking and the case
   are still the target's. */
.site-foot .foot-line { margin: 0; font-size: var(--t-label); font-weight: 500; line-height: 1.4; letter-spacing: 0.22em; text-transform: uppercase; color: var(--ink-2); }
.site-foot .foot-line-brand { color: var(--slate); }

/* THE BAR STACKS ON A PHONE, which the target does at 640px and this did not do at all. The left
   line runs 44 characters at 0.22em tracking, and the tracking survived the lift from the target's
   11px to this system's 14px floor, so the line is about 550px wide. Beside a wordmark on one flex
   row it wrapped to three lines on a 375px screen. */
@media (max-width: 640px) {
  .site-foot .foot-bar { flex-direction: column; align-items: flex-start; gap: var(--s4); }
  .site-foot .foot-bar-left { flex-direction: column; align-items: flex-start; gap: var(--s3); }
}
@media (max-width: 900px) {
  .site-foot .foot-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .site-foot .foot-col:nth-child(3) { border-left: 0; padding-left: 0; }
}
@media (max-width: 560px) {
  .site-foot .foot-cols { grid-template-columns: minmax(0, 1fr); }
  .site-foot .foot-col + .foot-col { border-left: 0; padding-left: 0; }
}

/* ---- src/parts/ft-page.css ---- */
/* THE THREE BANDS OF /use-cases/find-and-trust.
 *
 * THE REFERENCE IS /tmp/claude-501/rw-live/app/use-cases/01/page.tsx, read whole on
 * 16 September 2026 and measured in a browser at 1440 on the same day. Every number below was taken
 * from that source or from `getBoundingClientRect` on the running page, never estimated from a
 * screenshot, and each one is named beside the rule that states it. The reference draws five
 * sections and this page draws three, because the reference's first three are one argument:
 *
 *   1  the claim and the instrument      the reference's sections one, two and three in one band:
 *                                        a centred hero, then the count bar in the box its search
 *                                        field had, then its two column grid of a figure beside one
 *                                        deep record
 *   2  a hairline, a 24px head, and a four column row of 56px ringed marks
 *   3  a wide closing panel
 *
 * WHY THE FIRST THREE ARE ONE BAND. The instrument is the drawing of the page's own statement, that
 * approving software and issuing it an identity are two decisions with two owners. A reader who has
 * just read that sentence should meet the drawing of it without a section break in between, and the
 * redesign tracker measures the hero figure inside the FIRST section. The reference's own spacing
 * between those three sections is kept, as margins inside the band rather than as band padding.
 *
 * FOUR KINDS OF VALUE ARE HELD RATHER THAN COPIED, AND EACH ONE IS A RULE HERE.
 *
 *   A SIZE UNDER 14px BECOMES 14px. The reference sets 13px on its eyebrow, its card subtitle and
 *   its step body, 12px on a panel row's value and its mono list, and 11px on a badge. 14px is the
 *   floor and packages/ui/tests/stylesheet.test.ts enforces it across the bundle.
 *
 *   A COLOUR LITERAL BECOMES A TOKEN. packages/ui/tools/contrast.mjs enumerates token pairs by name
 *   and can see nothing through a hex value, so a literal is a colour no gate can read. The
 *   reference's #aebdd2 lead is --ink-lead and its #cddcee row value is --ink-row: both tokens were
 *   added on 16 September 2026 for exactly this, and before them every builder reached for --ink-2,
 *   two steps down, which made a lead read as a caption.
 *
 *   A GREEN OR AMBER BADGE IS NOT DRAWN AT ALL. Green means Observed on this site and an Observed
 *   mark links its artefact. The reference paints Verified and Pending freely over a comp that read
 *   nothing. The listing chip here carries a real difference the declaration makes, in the brand
 *   family, and claims no event.
 *
 *   THE MEASURE IS THIS ROUTE'S FAMILY, NOT THE REFERENCE'S BOX. The reference writes
 *   `max-w-[1200px] px-8` on every section, a box of 1200 whose content is 1136. The three families
 *   on this site are already set and may not be changed: 1216 for the use case pages, whose content
 *   is 1152. The reading panel holds the reference's fixed column at 360 rather than its 400, and
 *   the rule that sets it says why: the fluid column here carries a figure rather than a list of one
 *   line cards, and at 400 the figure's two identity cards fall to 288. Measured at 1440: the figure
 *   takes 832 and each card 320.
 *
 * IT REFUSES THE REFERENCE'S CONTENT. Its agents, organisations, capability strings, filter
 * taxonomy and status words are invented for a comp. Nothing here draws any of them: the page reads
 * the estate through apps/site/src/live-compat.ts and this file styles what that produces.
 *
 * EVERY RULE HERE IS SCOPED UNDER .ftp, which apps/site/src/views/find-and-trust.ejs writes on the
 * page wrap and no other view writes at all. A rule written here cannot reach another route's
 * markup, which is the condition parallel rebuilds depend on.
 *
 * CONTRAST. Every pair below is one contrast.mjs already enumerates:
 *   ink       on paper, on paper-alt, on white   headings, card names, row labels
 *   ink-lead  on paper                           the hero lead
 *   ink-row   on white, on paper-alt             the value in a labelled row
 *   ink-2     on paper, on paper-alt, on white   captions, the refused row
 *   teal-dark on paper, on white                 the headline accent, a ring, a chip
 */

/* ---- THE PAGE MEASURE ----
   The use case family. The masthead and the footer keep 1472, which is what the reference does: its
   SiteHeader and SiteFooter are wider than its page body. */
.ftp { --page-max: 1216px; }

/* ================================================================================================
 * 1. THE HERO, over the reference's grid ground.
 *
 * The reference runs a 44px grid behind the hero at low contrast and fades it with a radial mask, so
 * the texture reads at the centre and never at the edge where the words are.
 * ============================================================================================= */
.ftp .ftp-band-hero { position: relative; overflow: hidden; padding-block: var(--s7) 0; }
.ftp .ftp-band-hero > * { position: relative; z-index: 1; }
/* The ground runs one gutter past the wrap on each side rather than the full viewport width. 100vw
   includes the scrollbar, which is a horizontal scroll on the whole document for two pixels of
   texture. */
.ftp .ftp-grid {
  /* THE GROUND STOPS UNDER THE COPY RATHER THAN RUNNING THE WHOLE BAND. The hero, the count bar,
     the instrument and the reading panel are one section now, so `inset: 0` would run a 44px grid
     behind the two identity cards and their pedestals, which is where the figure's own light is.
     Measured at 1440: the band is about 1500 tall and the copy ends at 380. */
  position: absolute; inset: 0 calc(-1 * var(--gutter)) auto; height: 26rem; z-index: 0; pointer-events: none;
  background-image:
    linear-gradient(to right, color-mix(in srgb, var(--rule) 30%, transparent) 1px, transparent 1px),
    linear-gradient(to bottom, color-mix(in srgb, var(--rule) 30%, transparent) 1px, transparent 1px);
  background-size: 44px 44px;
  -webkit-mask-image: radial-gradient(ellipse at center, var(--ink) 0%, transparent 78%);
  mask-image: radial-gradient(ellipse at center, var(--ink) 0%, transparent 78%);
}

/* THE HERO IS CENTRED AND CARRIES NO FIGURE, which is the reference and is also a measurement: a
   diagram beside the headline pushed the estate below the fold at 1440 on the one page whose subject
   is the estate. The two actions sit side by side, because the reference sets them in one row and
   the pair is one gesture. */
.ftp .ftp-hero-copy { display: grid; justify-items: center; text-align: center; }
/* THE AMBIENT POOL, the fifth of the reference build's treatments. It sits behind the instrument
   rather than behind the headline: the grid ground above already carries the copy, and the thing
   that reads flat without it is the figure. */
.ftp .ftp-hero-glow { top: 27rem; }

/* THE HERO TYPE AND ITS RHYTHM, taken from the reference line by line. In order down the column it
   sets: eyebrow 13px weight 600 uppercase tracking 0.28em; h1 mt-4 max-w-[760px] 52px weight 700
   line height 1.05 tracking -0.03em; lead mt-4 max-w-[520px] 16px line height 1.6 colour #aebdd2;
   actions mt-8 gap-4.
   TWO VALUES ARE HELD. The eyebrow is 14px, not 13px, because 14px is the floor. The lead takes
   --ink-lead, which IS the reference's #aebdd2: the token exists now and this page is the reason it
   was asked for.
   THE EYEBROW ON THIS PAGE IS MUTED, NOT BRAND. The reference sets it #8ea3bd here and #7fd8e6 on
   use cases 02, 03 and 06. That is the reference's own difference and it is kept. */
.ftp .ftp-hero-copy .sc-eyebrow { letter-spacing: 0.28em; color: var(--ink-2); }
.ftp .ftp-hero-copy .sc-headline {
  margin-top: var(--s4);
  max-width: 47.5rem;
  font-size: 52px; line-height: 1.05; letter-spacing: -0.03em;
}
.ftp .ftp-hero-copy .sc-lead {
  margin: var(--s4) auto 0;
  max-width: 32.5rem;
  font-size: 16px; line-height: 1.6;
  color: var(--ink-lead);
}
.ftp .ftp-hero-copy .sc-actions { justify-content: center; margin-top: var(--s6); gap: var(--s4); }
@media (max-width: 760px) {
  /* The reference is not designed narrow. 52px in a 360px column breaks a headline mid word, so the
     display scale takes over below the width its own measure stops working at. */
  .ftp .ftp-hero-copy .sc-headline { font-size: var(--t-display); line-height: var(--t-display-line); }
}

/* ================================================================================================
 * THE BAR, which holds the box the reference gives its search field. It is a block inside the first
 * band now rather than a band of its own.
 *
 * The reference draws a read only input at 1002 wide and a Filters button at 118, both 53 tall, both
 * `rounded-xl` on a 12px radius with `px-4 py-3.5` and a hairline edge. Both controls are refused in
 * the view, with the reasoning there. What holds the box is the estate's own count sentence, at the
 * same height, the same radius and the same edge, running the full measure.
 * ============================================================================================= */
.ftp .ftp-bar {
  margin-top: var(--s7);
  /* IT WRAPS RATHER THAN CRUSHING. Without `flex-wrap` the two counts hold their width and the
     sentence beside them is squeezed to zero at 500px, which renders as a column of single letters.
     Measured at 500 before the rule and after it. */
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s3);
  min-height: 53px;
  padding: 14px var(--s4);
  border-radius: 12px;
  border: 1px solid var(--hairline);
  background: var(--white);
  font-size: var(--t-small); line-height: var(--t-small-line);
  color: var(--ink-2);
}
.ftp .ftp-bar-i { color: var(--ink-2); }
.ftp .ftp-bar-i .sc-glyph { width: 20px; height: 20px; }
/* The reference's row is a wide element beside a compact one, so the sentence takes the width its
   search field had and the two counts take the box its Filters button had. */
.ftp .ftp-bar-t { flex: 1 1 22rem; min-width: 0; }
.ftp .ftp-bar-t b { color: var(--ink); font-weight: 600; }
.ftp .ftp-bar-org { color: var(--ink-row); }
.ftp .ftp-bar-counts { display: flex; flex-wrap: wrap; gap: var(--s4); }
/* A dot in front of each count, in the same two hues the two cards take, so the sentence and the
   pair under it are visibly about the same two routes. */
.ftp .ftp-bar-count { white-space: nowrap; }
.ftp .ftp-bar-count b { color: var(--ink); font-weight: 600; }
.ftp .ftp-bar-count::before { content: ""; display: inline-block; width: 6px; height: 6px; margin-right: 8px; border-radius: 50%; vertical-align: 0.15em; background: var(--teal-dark); }
.ftp .ftp-bar-count[data-listed="root"]::before { background: var(--slate); }

/* ================================================================================================
 * THE INSTRUMENT AND ITS READING PANEL, the third block of the first band.
 *
 * The reference's grid rule verbatim: `lg:grid-cols-[1fr_400px]` on `gap-6`. Measured on the running
 * page at 1440 it resolves to 712px and 400px with a 24px gap inside a 1136 content width. Here the
 * content is 1152, so the fluid column is 728 and the fixed one is still 400.
 * ============================================================================================= */
/* The line over the figure, which the reference does not have because its list needs no explanation.
   This one does: two cards that carry the same name are the argument only once a reader knows they
   are the same release. */
.ftp .ftp-pair-head { margin-top: var(--s7); margin-bottom: var(--s4); }
.ftp .ftp-pair-eyebrow {
  margin: 0; font-size: var(--t-label); line-height: var(--t-label-line); font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.22em; color: var(--teal-dark);
}
.ftp .ftp-pair-line { margin: var(--s2) 0 0; max-width: 56ch; font-size: 16px; line-height: 1.6; color: var(--ink-lead); }

/* THE PANEL IS 360 RATHER THAN THE REFERENCE'S 400. The reference puts a list of four one line
   cards in the fluid column; this one puts a hub, two wires and two cards that each carry three
   labelled rows, and at 400 the two cards fall to 388 and their values break mid line. CLAUDE.md
   rule 7 states the bound on the other side: a panel narrow enough to read as an afterthought
   beside the instrument is the fault, and 360 is not that. */
.ftp .ftp-split { display: grid; grid-template-columns: minmax(0, 1fr) 360px; gap: var(--s5); align-items: start; }
.ftp .ftp-split > * { min-width: 0; }

/* ---- THE INSTRUMENT: ONE HUB, TWO WIRES, TWO IDENTITY CARDS ----
 *
 * WHAT IT DRAWS AND WHY IT IS THIS PICTURE. The page statement is that approving software and
 * issuing it an identity are two decisions with two owners. The hub is the release, which is the
 * object of the first decision. The two cards are the two governed identities stood up from it,
 * which are the object of the second. The rail names each decision and its owner, level with the
 * row of the figure it is about.
 *
 * THE TREATMENTS ARE THE REFERENCE BUILD'S, FROM packages/ui/src/parts/rw.css RATHER THAN REDRAWN
 * HERE. `rw-hub` is the object every connector leaves, `rw-wires` and `rw-wire` are the connector
 * layer, `rw-card` is the environment card lit from above by its own hue, `rw-ped` is the icon
 * standing on light, and `rw-glow` is the ambient pool. Three pages had each grown their own
 * version of those before that file existed, and the differences were accidents.
 *
 * WHAT REPLACED WHAT. The band held a flex column of two list cards in the reference's own list card
 * recipe, a title beside a 44px box with three rows under it. Those cards said one release under two
 * operators only to a reader who read the line above them. They are the same three rows on the same
 * two agents, hanging off one hub by two wires, which says it without the line.
 * ============================================================================================= */
.ftp .ftp-fig {
  position: relative;
  display: grid;
  grid-template-columns: 9.5rem minmax(0, 1fr);
  column-gap: var(--s5);
  align-items: start;
}
/* Each part is placed by row rather than by source order, so the rail marker sits level with the
   thing it names and the wire layer sits between the two rows it joins. */
.ftp .ftp-lane-1 { grid-column: 1; grid-row: 1; align-self: center; }
.ftp .ftp-hub { grid-column: 2; grid-row: 1; }
.ftp .ftp-wires { grid-column: 2; grid-row: 2; }
.ftp .ftp-lane-2 { grid-column: 1; grid-row: 3; }
.ftp .ftp-owners { grid-column: 2; grid-row: 3; }

/* ---- The rail ----
   EACH MARKER TAKES THE COLOUR OF THE ROW IT NAMES, which keeps every colour on this figure doing
   one job. Lane 01 names the hub, which is the brand object every wire leaves, so it takes the
   brand. Lane 02 names the two identity cards, so its bar runs from one card's hue to the other's
   and its numeral takes the first of them.
   THE OTHER TWO IDENTITY HUES ARE NOT USED HERE, AND THE REASON IS THE WORDS RATHER THAN THE
   COLOURS. --d-magenta is a green and --d-sand is an amber, close enough to --d-ok and --d-att to
   be read as them. Green means Observed on every surface of this site and amber means in progress.
   Lane 01 reads "Approve the software", which is a verdict word, and a green numeral beside it
   would say a verdict was reached. Both hues keep their identity job on the payoff row below, where
   the four outcomes carry no verb a colour could be read as answering. */
.ftp .ftp-lane { --hue: var(--teal-dark); }
.ftp .ftp-lane-2 { --hue: var(--d-blue); padding-top: var(--s4); }
.ftp .ftp-lane-2::before { background: linear-gradient(90deg, var(--d-blue), var(--d-violet)); }
.ftp .ftp-lane-n {
  margin: 0; font-family: var(--mono); font-size: var(--t-label); line-height: 1.2; font-weight: 600;
  letter-spacing: 0.1em; color: var(--hue);
}
.ftp .ftp-lane-t { margin: var(--s2) 0 0; font-size: 15px; line-height: 1.35; font-weight: 700; color: var(--ink); }
.ftp .ftp-lane-o { margin: var(--s1) 0 0; font-size: var(--t-label); line-height: 1.45; color: var(--ink-2); }
/* The marker is tied to its row by a short bar in its own hue, so the rail reads as two lanes of a
   figure rather than as two captions floating beside it. */
.ftp .ftp-lane::before {
  content: ""; display: block; width: 28px; height: 2px; margin-bottom: var(--s3);
  background: var(--hue);
}

/* ---- The hub ----
   `rw-hub` carries the radial gradient, the brand edge, the outer glow and the inset highlight. The
   width is held because a hub running the full 800 of the fluid column stops reading as one object
   with two things hanging off it. */
.ftp .ftp-hub { max-width: 26rem; margin-inline: auto; }
.ftp .ftp-hub-i { display: inline-flex; color: var(--teal-dark); }
.ftp .ftp-hub-i .sc-glyph { width: 28px; height: 28px; }
.ftp .ftp-hub-eyebrow {
  margin: var(--s2) 0 0; font-size: var(--t-label); line-height: var(--t-label-line); font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.18em; color: var(--teal-dark);
}
.ftp .ftp-hub-name { margin: var(--s2) 0 0; font-size: 20px; line-height: 1.25; font-weight: 700; color: var(--ink); }
/* The label is the dim half and the estate's value is the bright one, which is the pairing
   --ink-row was declared for: the reader came for the publisher, not for the words Published by. */
.ftp .ftp-hub-pub { margin: var(--s2) 0 0; font-size: var(--t-label); line-height: 1.5; color: var(--ink-2); }
.ftp .ftp-hub-pub b { font-weight: 600; color: var(--ink-row); }
.ftp .ftp-hub-foot { margin: var(--s3) 0 0; font-size: var(--t-label); line-height: 1.5; color: var(--ink-2); }

/* ---- The wires ----
   One cubic bezier per identity, in a 100 by 100 box with preserveAspectRatio none, so an svg unit
   is a percent of the layer on both axes and the ends land on the two columns whatever the width.
   EACH WIRE TAKES ITS CARD'S IDENTITY HUE. Two identical strokes would leave a reader matching a
   line to a card by position; a blue line into the blue card and a violet line into the violet one
   needs no matching at all. */
.ftp .ftp-wires { position: relative; height: 5rem; }
.ftp .ftp-wires-svg { height: 100%; }
.ftp .ftp-wire { --hue: var(--d-blue); stroke: var(--hue); }
.ftp .ftp-wire[data-listed="root"] { --hue: var(--d-violet); }
/* preserveAspectRatio none would squash an svg marker with the box, so each arrowhead is a
   positioned element with a clip path instead. */
.ftp .ftp-head {
  position: absolute; bottom: 0; transform: translateX(-50%);
  width: 11px; height: 9px;
  --hue: var(--d-blue);
  background: var(--hue);
  clip-path: polygon(50% 100%, 0 0, 100% 0);
}
.ftp .ftp-head[data-listed="root"] { --hue: var(--d-violet); }

/* ---- The two identity cards ----
   `rw-card` is the reference's environment card: a vertical gradient panel, a hairline edge, and an
   inset top highlight with the top border tinted in the card's own hue, so it reads as lit from
   above rather than as a flat rectangle.
   WHO LISTED THE AGENT DECIDES THE HUE, AND THE HUES ARE THE REFERENCE'S OWN. An earlier version of
   this page used two shades of the brand here, on the reasoning that an environment colour "would
   read as a state". That reasoning is wrong and CLAUDE.md carries the correction: green means
   Observed, amber means in progress and red means refused, and those three are STATE. --d-blue and
   --d-violet carry no meaning anywhere in this system, which is exactly what frees them to carry
   identity.
   THE TWO CARDS AGREE ON EVERY ROW BUT ONE, WHICH IS THE DESIGN AND NOT AN ACCIDENT OF THE ESTATE.
   Same publisher, same runtime, same detail types. The supplier's card carries a fourth row the
   other has not. A contrast between two things that are otherwise identical needs no arrow pointing
   at it, which is what a CISO asked for twice: one denial persuades more than six approvals. */
/* THE TWO CARDS SIZE TO THEIR OWN CONTENT RATHER THAN STRETCHING TO THE TALLER, which is the one
   place this figure lets the estate set a measurement. Stretched, the enterprise card carried about
   100px of empty ground under its last row because the supplier card has a fourth. Sized to content
   the supplier's card is visibly the taller of the two, and what makes it taller is the row the
   authority did not grant. Measured at 1440. */
.ftp .ftp-owners { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s4); align-items: start; }
.ftp .ftp-owner { --hue: var(--d-blue); }
.ftp .ftp-owner[data-listed="root"] { --hue: var(--d-violet); }
/* The supplier half is the card the record panel opens. A brighter edge says which of the two the
   panel beside it is about, without a control that does nothing. */
.ftp .ftp-owner[data-focus="true"] { border-color: color-mix(in srgb, var(--hue) 50%, transparent); }
.ftp .ftp-owner-ped { width: 100%; margin-bottom: var(--s2); }
.ftp .ftp-owner-ped .sc-glyph { width: 44px; height: 44px; }
/* THE NAME AND THE CHIP STACK RATHER THAN SITTING ON ONE LINE, and that is a measurement rather
   than a preference. Side by side, "Tarnbrook Financial Group" pushed its chip onto a second line
   and "Quillon Software" did not, so the three labelled rows under the two cards started 22px
   apart and the pair stopped reading as a comparison. Measured at 1440. Stacked, it is also the
   title and subtitle CLAUDE.md asks a card for. */
.ftp .ftp-owner-h { display: grid; justify-items: start; gap: var(--s2); margin: 0; }
.ftp .ftp-owner-name { font-size: 16px; line-height: 1.4; font-weight: 700; color: var(--ink); }

/* THE THREE LABELLED ROWS ON THE FACE, which is a site rule rather than a preference. CLAUDE.md
   states it: a card carries a title, a subtitle and three labelled rows, and a card that shows a
   chip and hides the rest makes a reader press something to learn anything. Who listed the agent is
   the chip beside the operator's name, so the three rows are the publisher, the runtime and the
   envelope.
   THE GRANTED TYPES AND THE ASKED FOR ONE ARE TWO ROWS, NOT ONE. Drawn together the supplier's card
   read "May request" over three chips, one of which is exactly what it may not request. */
.ftp .ftp-owner-rows { display: grid; gap: var(--s3); margin-top: var(--s4); padding-top: var(--s4); border-top: 1px solid var(--hairline); }
.ftp .ftp-owner-row dt { font-size: var(--t-label); line-height: var(--t-label-line); color: var(--ink-2); }
.ftp .ftp-owner-row dd { margin: 2px 0 0; font-size: var(--t-label); line-height: 1.45; font-weight: 600; color: var(--ink-row); }
.ftp .ftp-owner-row-types dd { display: flex; flex-wrap: wrap; gap: 6px; font-weight: 400; }
/* The fourth row, on the one card that has one. Its own dashed edge separates it from the three the
   other card also draws, so the difference is visible before a word of it is read. */
.ftp .ftp-owner-row-outside {
  margin-top: var(--s1); padding-top: var(--s3);
  border-top: 1px dashed var(--bound);
}

/* The reference's tag row: `mt-3 flex flex-wrap gap-2`, each tag `rounded-md bg-ink-2 px-2 py-0.5`.
   Radius 6, padding 2px 8px, 12px text held here at the 14px floor. The tags carry the estate's
   authorization detail types, which are identifiers, so they are set in the mono face. */
.ftp .ftp-type {
  padding: 2px 8px; border-radius: 6px;
  background: var(--paper-alt);
  font-family: var(--mono); font-size: var(--t-label); line-height: var(--t-label-line);
  color: var(--ink-row);
}
/* THE TYPE THE OPERATOR ASKS FOR AND THE AUTHORITY DID NOT GRANT, on the face of the card so the
   pair reads as a contrast before the panel is read. It is drawn as an absence, a dashed outline
   over the page ground, rather than in a state colour: red means refused on a wire that somebody
   watched, and this page has watched nothing. */
.ftp .ftp-type-outside {
  background: transparent;
  border: 1px dashed var(--bound);
  color: var(--ink-2);
}

/* THE CHIP BESIDE THE OPERATOR'S NAME. The reference's badge, at the floor rather than its 11px, and
   carrying a listing rather than a verification. It is an outline in the card's own hue: a filled
   chip in this system is the product marker and means something else. */
.ftp .ftp-chip {
  display: inline-flex; align-items: center;
  padding: 2px 10px; border-radius: var(--pill);
  border: 1px solid color-mix(in srgb, var(--hue, var(--teal-dark)) 45%, transparent);
  font-size: var(--t-label); line-height: var(--t-label-line); font-weight: 600;
  color: var(--hue, var(--teal-dark));
}
.ftp .ftp-chip[data-listed="authority"] { --hue: var(--d-blue); }
.ftp .ftp-chip[data-listed="root"] { --hue: var(--d-violet); }

/* ---- The record panel ----
   The reference: `rounded-2xl border border-line bg-panel/60 p-6` on a 400px column. Measured:
   radius 16, padding 24, width 400. */
.ftp .ftp-record {
  border-radius: 16px;
  border: 1px solid color-mix(in srgb, var(--rule) 55%, transparent);
  background: var(--white);
  padding: var(--s5);
}
/* The header: `flex items-center gap-3`, a 40px box at radius 8 with a brand edge and a 20px glyph,
   a 15px bold name and a 12px organisation held at the floor. */
.ftp .ftp-record-head { display: flex; align-items: center; gap: var(--s3); }
.ftp .ftp-record-i {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; flex: none; border-radius: 8px;
  border: 1px solid color-mix(in srgb, var(--teal-dark) 40%, transparent);
  color: var(--teal-dark);
}
.ftp .ftp-record-i .sc-glyph { width: 20px; height: 20px; }
.ftp .ftp-record-h { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); margin: 0; }
.ftp .ftp-record-name { font-size: 15px; line-height: 1.5; font-weight: 700; color: var(--ink); }
.ftp .ftp-record-op { margin: 0; font-size: var(--t-label); line-height: 1.4; color: var(--ink-2); }

/* THE TAB ROW, CARRYING ONE LABEL. The reference sets `mt-5 flex gap-6 border-b border-line` and
   marks the live tab with a 2px brand bar at the foot of the label. Its other two tabs open nothing,
   so only the treatment is kept: one label, its bar, and the hairline across the panel. */
.ftp .ftp-record-tab {
  margin: var(--s5) 0 0; padding-bottom: 10px;
  border-bottom: 1px solid var(--hairline);
  font-size: var(--t-label); line-height: var(--t-label-line); font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.14em;
  color: var(--teal-dark);
}
.ftp .ftp-record-tab span { position: relative; display: inline-block; }
.ftp .ftp-record-tab span::after { content: ""; position: absolute; left: 0; right: 0; bottom: -11px; height: 2px; background: var(--teal-dark); }

/* THE PORTRAIT LEFT THE PANEL ON 16 SEPTEMBER 2026. The reference draws a 162px box holding a 96px
   rounded square with a glow in it, and it carried no information: its own note in this file said
   so, and defended it as the reason the panel read as the record of one thing. The instrument beside
   the panel now draws the same agent glyph twice, once on each identity card, each standing on a lit
   pedestal. A third copy of one robot in one band is repetition, and the panel reads as a record
   because of the name and the chip at its head. */

/* THE ROWS. The reference: `mt-4 space-y-3`, each row `flex items-center gap-3 rounded-lg border
   border-line bg-ink-2 px-4 py-3`. Radius 8, padding 12px 16px, gap 12, a 20px brand glyph.
   THE LABEL IS THE DIM HALF AND THE VALUE IS THE BRIGHT ONE, WHICH IS ONE STEP OFF THE REFERENCE.
   It sets the fixed word white and the estate value #8ea3bd under it, so the label shouts and the
   fact whispers. --ink-row exists for the value in a labelled row beside a dimmer label, and these
   rows are exactly that: the reader came for the organisation name, not for the word Operator. */
.ftp .ftp-rows { display: grid; gap: var(--s3); margin-top: var(--s4); }
.ftp .ftp-row {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3) var(--s4); border-radius: 8px;
  border: 1px solid var(--hairline);
  background: var(--paper-alt);
}
.ftp .ftp-row > div { min-width: 0; }
.ftp .ftp-row-i { color: var(--teal-dark); flex: none; }
.ftp .ftp-row-i .sc-glyph { width: 20px; height: 20px; }
.ftp .ftp-row dt { font-size: var(--t-label); line-height: var(--t-label-line); color: var(--ink-2); }
.ftp .ftp-row dd { margin: 2px 0 0; font-size: var(--t-label); line-height: 1.45; font-weight: 600; color: var(--ink-row); }
.ftp .ftp-row-types { align-items: flex-start; }
.ftp .ftp-row-types dd { display: flex; flex-wrap: wrap; gap: 6px; font-weight: 400; }
.ftp .ftp-mono {
  padding: 1px 8px; border-radius: 6px;
  background: var(--paper);
  font-family: var(--mono); font-size: var(--t-label); line-height: 1.5;
  color: var(--ink-row);
}

/* THE REFUSAL, AND IT IS THE LARGEST OBJECT ON THE PANEL ON PURPOSE. One denial carries further than
   six approvals, which is what a business panel said about the version of this page that drew six
   near identical cards of approvals with one line of refusal inside the third.
   IT IS A HOLE IN THE PANEL, NOT A STATE. --no means refused, withdrawn or gone and it marks
   something a reader can go and check. Nothing was refused on a wire here: the declaration records
   what the operator asks for and the ceiling its root holds, and this page has read neither. A
   dashed edge over the page ground says not granted and claims no event. */
.ftp .ftp-outside {
  margin-top: var(--s3);
  padding: var(--s4); border-radius: 8px;
  border: 1px dashed var(--bound);
  background: var(--paper);
}
.ftp .ftp-outside-h {
  margin: 0; font-size: var(--t-label); line-height: var(--t-label-line); font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.14em; color: var(--ink-2);
}
.ftp .ftp-outside-types { display: flex; flex-wrap: wrap; gap: 6px; margin: var(--s2) 0 0; }
.ftp .ftp-outside-types .ftp-mono { background: transparent; border: 1px dashed var(--bound); color: var(--ink-2); }
.ftp .ftp-outside-l { margin: var(--s3) 0 0; font-size: var(--t-label); line-height: 1.5; color: var(--ink-2); }

/* The reference's action at the foot of the panel is a 12px radius rectangle filled #2a7fff, a blue
   this site does not carry and a shape CLAUDE.md settles: every button on this site is a full pill,
   filled in the brand with dark text. So the site's own control takes the slot, at the reference's
   `mt-5` and running the panel's width. */
.ftp .ftp-record-cta { margin-top: var(--s5); width: 100%; justify-content: center; }

/* THE CLOSED RECORD AND ITS TABLE LEFT THIS PAGE ON 16 SEPTEMBER 2026. It was a disclosure holding
   all six agents with seven columns each, and a drawer on a claim page is the documentation shape
   this rebuild removes. The record is a topic of the `## technical` section of
   apps/site/content/journey-1-find-and-trust.md now, which /use-cases/find-and-trust/evidence
   renders through packages/ui/partials/drawer.ejs and styles from its own part file. Nothing that
   table carried left the site, and apps/site/src/views/find-and-trust.ejs refuses to serve this page
   if the moved table stops naming every agent the estate declares. */

/* The provenance line, at the foot of the thing it is about. packages/ui/partials/ft-hero.ejs draws
   it and packages/ui/src/parts/ft.css centres it; this rule only gives it the space this band wants. */
.ftp .ft-claim { margin: var(--s5) auto 0; }

/* ================================================================================================
 * 2. THE PAYOFF ROW.
 *
 * The reference: `pt-14` (56px), `border-t border-line/70`, `pt-10` (40px), a 24px bold heading at
 * tracking -0.02em, then `mt-6` (24px) and a four column row. Each column is centred with a 56px
 * ring at `border-brand/40`, a 24px glyph, a 15px bold title at `mt-3` and a 13px body.
 *
 * NO ARROWS BETWEEN THE COLUMNS. The reference puts one between each of its four because those four
 * are steps in an order: Discover, Verify, Understand, Connect. These four are outcomes and have
 * none, so an arrow would assert a sequence this page does not claim. A vertical hairline separates
 * without ordering, which is what the reference's own benefits row does on use cases 02 and 03.
 *
 * THE LINE OVER THIS BAND IS THE FAINT ONE. The reference draws it `border-line/70`, the same almost
 * absent line it puts between the columns under it. The token note on --d-hairline names this case
 * in so many words.
 * ============================================================================================= */
.ftp .ftp-band-payoff { display: grid; gap: var(--s5); }
/* The reference sets this heading across the full measure and it fits on one line there. A measure
   of 24ch, which is the display measure, broke it in two over a row that is four columns wide. */
.ftp .ftp-payoff-line { margin: 0; font-size: 24px; max-width: none; }
.ftp .ftp-outcomes {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
}
.ftp .ftp-outcomes li {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  padding-inline: var(--s5); min-width: 0;
}
/* The separators are decorative, so they take the hairline token rather than the rule token, which
   marks the edge of something a person operates. */
.ftp .ftp-outcomes li + li { border-left: 1px solid var(--hairline); }
/* THE RING. Without the border the row is four line drawings against text; the reference's row is
   four objects standing on a page, and the ring is the whole of that difference. The stroke is a
   graphic boundary, so its floor is the 3 to 1 of WCAG 1.4.11. */
/* FOUR RINGS, FOUR HUES, IN THE REFERENCE'S OWN ORDER. Its benefits row draws each outcome in its
   own environment colour, which is what stops a row of four circles reading as one repeated object.
   None of the four makes a claim: they say which outcome this is, not what is true of it. */
.ftp .ftp-outcome-i {
  display: inline-flex; align-items: center; justify-content: center;
  width: 56px; height: 56px; flex: none; border-radius: 50%;
  --hue: var(--d-blue);
  border: 1px solid color-mix(in srgb, var(--hue) 45%, transparent);
  color: var(--hue);
}
.ftp .ftp-outcomes li:nth-child(2) .ftp-outcome-i { --hue: var(--d-violet); }
.ftp .ftp-outcomes li:nth-child(3) .ftp-outcome-i { --hue: var(--d-magenta); }
.ftp .ftp-outcomes li:nth-child(4) .ftp-outcome-i { --hue: var(--d-sand); }
.ftp .ftp-outcome-i .sc-glyph { width: 24px; height: 24px; }
.ftp .ftp-outcome-t { margin: var(--s3) 0 0; font-size: 15px; line-height: 1.4; font-weight: 700; color: var(--ink); }
.ftp .ftp-outcome-l { margin: var(--s1) 0 0; max-width: 16.25rem; font-size: var(--t-label); line-height: 1.5; color: var(--ink-2); }

/* ================================================================================================
 * THE SECTION RHYTHM, AND THE RULE THE REFERENCE DOES NOT DRAW.
 *
 * `.band` in the base sheet gives every band 64px above, 64px below and a full width rule across the
 * top. None of the four reference use case pages draws a rule between two sections. Measured on the
 * running reference rather than remembered: its five sections run pt-12, pt-8, pt-8, pt-14, pt-12,
 * and its only horizontal line is the one immediately above the payoff row.
 *
 * SO A BAND STATES ITS TOP SPACE AND NO BOTTOM SPACE. The gap between two bands is then one number
 * rather than the sum of two, which is how the reference sets it. The last band takes its bottom
 * space back, because the footer under it has none of its own.
 *
 * THE BASE RULE IS NOT TOUCHED. `.band` is shared by seventeen routes. `.wrap.ftp > .band` is three
 * classes against one and cannot reach any of them.
 * ============================================================================================= */
.wrap.ftp > .band { border-top: 0; padding-block: var(--s6) 0; }
/* The four bands whose own top space the reference states. They are restated at this specificity
   rather than left where they were written, because `.wrap.ftp > .band` is three classes and
   `.ftp .ftp-band-hero` is two, so the blanket above would otherwise beat all four. */
.wrap.ftp > .ftp-band-hero { padding-block: var(--s7) 0; }
.wrap.ftp > .ftp-band-close { padding-block: var(--s7) 0; }
/* The one line the reference does draw, with its own pt-14 over it and pt-10 under it. It is the
   hairline token rather than the rule token: a rule marks the edge of something a person operates
   and this separates reading. */
.wrap.ftp > .ftp-band-payoff {
  border-top: 1px solid var(--hairline);
  margin-top: 3.5rem;
  padding-block: 2.5rem 0;
}
.wrap.ftp > .band:last-child { padding-bottom: var(--s8); }

/* ================================================================================================
 * THE NARROW STATES.
 *
 * The reference switches its grid at its `lg` breakpoint, 1024px, and has no design below that at
 * all. These are designed rather than stacked.
 * ============================================================================================= */
@media (max-width: 1239px) {
  /* One column, and the breakpoint is measured rather than taken from the reference's `lg`.
     The reference breaks at 1024 because its fluid column holds a list of one line cards, which
     survives 570px. This one holds a rail, a hub and two cards carrying three labelled rows each.
     Measured at 1024 with the reference's own breakpoint: the two cards fell to 192px and every
     value in them broke over three lines. Two columns need a 1175 wrap to keep a card near 490,
     which is a 1239 viewport at this gutter.
     The reading panel then loses its fixed 360 and runs the measure. */
  .ftp .ftp-split { grid-template-columns: minmax(0, 1fr); }
  .ftp .ftp-record { max-width: 32rem; }
}
@media (max-width: 860px) {
  /* THE RAIL GOES OVER THE FIGURE RATHER THAN BESIDE IT. Below this width an 8.5rem rail beside two
     cards leaves each card about 300 and their labelled values break mid line. The two markers then
     run as a row above the figure, which keeps them as a pair rather than stacking them into two
     stray captions. */
  .ftp .ftp-fig { grid-template-columns: minmax(0, 1fr); row-gap: var(--s4); }
  .ftp .ftp-lane-1 { grid-column: 1; grid-row: 1; align-self: start; }
  .ftp .ftp-hub { grid-column: 1; grid-row: 2; }
  .ftp .ftp-wires { grid-column: 1; grid-row: 3; }
  .ftp .ftp-lane-2 { grid-column: 1; grid-row: 4; padding-top: 0; }
  .ftp .ftp-owners { grid-column: 1; grid-row: 5; }
}
@media (max-width: 680px) {
  /* The two cards stack, and the wires with them: two beziers into one column would cross. The
     figure keeps its hub and its rail and drops the connector layer, which draws nothing a reader
     loses when the cards are one under the other. */
  .ftp .ftp-owners { grid-template-columns: minmax(0, 1fr); }
  .ftp .ftp-wires { height: var(--s6); }
  .ftp .ftp-wires-svg, .ftp .ftp-head { display: none; }
}
@media (max-width: 1000px) {
  .ftp .ftp-outcomes { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s6) 0; }
  /* The vertical rule belongs between two columns of one row. At two columns it would also fall
     between the two rows, so only the second column of each pair keeps it. */
  .ftp .ftp-outcomes li + li { border-left: 0; }
  .ftp .ftp-outcomes li:nth-child(even) { border-left: 1px solid var(--hairline); }
}
@media (max-width: 620px) {
  /* The mark sits on the first line of the sentence rather than in the middle of a wrapped block. */
  .ftp .ftp-bar { align-items: flex-start; }
  .ftp .ftp-bar-i { margin-top: 2px; }
  .ftp .ftp-outcomes { grid-template-columns: minmax(0, 1fr); }
  .ftp .ftp-outcomes li:nth-child(even) { border-left: 0; }
  .ftp .ftp-outcomes li { padding-inline: 0; }
  .ftp .ftp-record { max-width: none; }
}

/* ================================================================================================
 * THE IDENTITY HUES ON THE RECORD PANEL AND THE COUNT BAR.
 *
 * WHAT THIS SECTION IS. The last two monochrome sets on this route. The four labelled rows inside
 * the record panel were four identical brand cyan marks, and the panel's own head, portrait and the
 * count bar above the pair were the same cyan again, so the panel read as one colour and the two
 * cards beside it read as two. The rows take one identity hue each; the panel takes the hue of the
 * card it opens; the two dots in the count bar take the hues those two listing kinds already carry.
 *
 * WHY. Measured at 1440 on 16 September 2026, this route drew 139 of the four identity hues, all of
 * them on the two cards and the payoff row, and none at all inside the record panel, which is the
 * object the page is built around. The cards were already fixed on the same day for the same
 * reason; the panel beside them was not.
 *
 * WHAT AN IDENTITY HUE IS. --d-blue, --d-violet, --d-magenta and --d-sand carry no meaning anywhere
 * in this system. They answer WHICH ONE of a set of peers this is. Green means Observed, amber
 * means in progress and red means refused, and all three sit beside the word that says so. Nothing
 * below carries any of the three: the refusal on this panel stays a dashed edge over the page
 * ground with its own words, because nothing here was read on a wire.
 *
 * THE PANEL READS ITS HUE FROM THE CHIP IT CARRIES rather than from a value written here. The chip
 * names the listing kind, the cards beside the panel already take their hue from the same attribute,
 * so the panel and the card it opens cannot disagree about which colour that agent is. One source
 * drives both.
 *
 * CONTRAST, computed from packages/ui/tokens/tokens.json with the formula in
 * packages/ui/tools/contrast.mjs. All four are gated against the three dark grounds at the 4.5 TEXT
 * floor. On d-card, the lightest and therefore the one that decides: d-blue 7.35, d-violet 6.62,
 * d-magenta 10.16, d-sand 10.41.
 * ============================================================================================= */

/* The panel takes the hue of the agent it is the record of. */
.ftp .ftp-record { --hue: var(--d-blue); }
.ftp .ftp-record:has(.ftp-chip[data-listed="root"]) { --hue: var(--d-violet); }
.ftp .ftp-record-i {
  border-color: color-mix(in srgb, var(--hue) 40%, transparent);
  color: var(--hue);
}
/* The four labelled rows. Each one answers a different question about the same agent: who operates
   it, which root it chains to, what it may ask for. The hue says which row a reader is in, and the
   label beside it says what the row is. */
.ftp .ftp-rows .ftp-row:nth-child(1) { --hue: var(--d-blue); }
.ftp .ftp-rows .ftp-row:nth-child(2) { --hue: var(--d-violet); }
.ftp .ftp-rows .ftp-row:nth-child(3) { --hue: var(--d-magenta); }
.ftp .ftp-rows .ftp-row:nth-child(4) { --hue: var(--d-sand); }
.ftp .ftp-rows .ftp-row-i { color: var(--hue); }

/* The two dots in the count bar name the two listing kinds, which is what the two cards under it
   name. They took the brand and a brand tint, two shades of one colour for two different things.
   They take the two hues those kinds already carry on the cards. */
.ftp .ftp-bar-count::before { background: var(--d-blue); }
.ftp .ftp-bar-count[data-listed="root"]::before { background: var(--d-violet); }

/* ---- src/parts/ft.css ---- */
/*
 * THE INSTRUMENT ON /use-cases/find-and-trust: one anchor, and every agent that reaches it.
 *
 * `ft-` is this page and nothing else on the site uses the prefix, so this part cannot reach another
 * component and another component cannot reach it. apps/site/src/views/find-and-trust.ejs draws the
 * markup; packages/ui/partials/ft-hero.ejs draws the one line at its foot.
 *
 * THE TREATMENTS ARE packages/ui/src/parts/rw.css's AND ARE NOT RESTATED HERE. The card is .rw-card,
 * the anchor is .rw-hub, the icon stands on .rw-ped, the connectors are .rw-wires and .rw-wire, the
 * pool behind the band is .rw-glow and the outcome badge is .rw-ring. This file states only what is
 * particular to this figure: how many columns, which hue means what, and the type inside a card.
 * A seventh copy of the pedestal is how six figures end up subtly different from each other.
 *
 * WHAT THIS FILE NO LONGER STYLES, AND WHY. It carried a search field, a Filters control, four
 * selectors, a pill row, a card list, a record column, a tab strip and six record panels. That band
 * opened the page with a control over six agents before the page had said what changes for the
 * reader, and a business panel read it and scrolled past. The controls are gone and their rules went
 * with them. packages/ui/partials/ft-discover.ejs is the partial that drew them and nothing renders
 * it now; it and its gallery example should go in the same sweep.
 *
 * THREE THINGS THE TARGET ASSERTS THAT THIS FIGURE MUST NOT.
 *
 *   THE GREEN VERIFIED TICK. Green means Observed on every surface of this site and an Observed mark
 *   links the artefact it was read from. Nothing on a card here has been read: every value is the
 *   estate DECLARATION, and NO GREEN APPEARS IN THIS FILE AT ALL. What the declaration does carry is
 *   who lists the agent, which is a real difference between two cards, and it takes the decorative
 *   palette rather than the state palette.
 *
 *   THE BUSINESS DOMAIN PILLS. Finance, Payments, Data, Research, Productivity. The estate declares
 *   none of them. The third row of every card holds the authorization detail types it does declare,
 *   which are the exact strings a platform compares against the agent's envelope.
 *
 *   THE BLUE ACCENT. The target's filled control measures a true blue and the dark system has one
 *   accent, the brand cyan. A hue is a token decision across nineteen routes, so it is recorded as a
 *   deviation rather than taken.
 *
 * CONTRAST. Every pair below is one packages/ui/tools/contrast.mjs already enumerates by name:
 *   ink       on paper   a card name, an anchor name, a row value
 *   ink-2     on paper   an operator line, a row label, the foot line
 *   teal-dark on paper   a detail type, the anchor glyph, an agent name in the record
 *   brand-strong on paper  an agent name in the record, under the pointer
 *   ink       on white   nothing on this figure, kept for the row of chips if one returns
 */

/* ---- The line at the foot of the figure ----
   packages/ui/partials/ft-hero.ejs carries the reason it exists: a reader who meets the estate on a
   page about trust assumes something resolved, and nothing here did. */
.ft-claim {
  margin: var(--s3) 0 0;
  max-width: 62ch;
  justify-self: center;
  text-align: center;
  font-size: var(--t-small); line-height: var(--t-small-line);
  color: var(--ink-2);
  text-wrap: balance;
}
.ft-claim b { color: var(--ink); font-weight: 600; }

/* ---- The figure ----
   `isolation` keeps the ambient pool behind the cards without a z-index on every child. */
.ft { position: relative; isolation: isolate; display: grid; gap: var(--s4); }
.ft > * { position: relative; z-index: 1; }
.ft .rw-glow { z-index: 0; }

/* ---- The anchor ----
   The object every connector leaves. .rw-hub gives it the radial gradient, the brand edge, the outer
   glow and the inset highlight; this sets its width and the type inside it. */
.ft-anchor { justify-self: center; max-width: 440px; display: grid; justify-items: center; gap: var(--s2); }
.ft-anchor-i {
  display: inline-grid; place-items: center;
  width: 48px; height: 48px; border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--teal-dark) 45%, transparent);
  color: var(--teal-dark);
}
.ft-anchor-i .sc-glyph { width: 24px; height: 24px; }
.ft-anchor-eyebrow {
  margin: 0; color: var(--ink-2);
  font-size: var(--t-label); line-height: var(--t-label-line);
  font-weight: 600; text-transform: uppercase; letter-spacing: 0.18em;
}
.ft-anchor-name { margin: 0; font-size: var(--t-h3); line-height: var(--t-h3-line); font-weight: 700; color: var(--ink); }
/* The two halves of the anchor's line, each with the count the view computed in front of it. The dot
   carries the hue of the cards that half is about, so the sentence and the cards are joined by
   colour as well as by the number. */
.ft-anchor-line { margin: 0; display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s2) var(--s4); }
.ft-anchor-count {
  display: inline-flex; align-items: baseline; gap: 6px;
  font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-2);
}
.ft-anchor-count::before {
  content: ""; align-self: center;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--hue, var(--teal-dark)); flex: none;
}
.ft-anchor-count b { color: var(--ink); font-weight: 600; }

/* ---- The connectors ----
   One svg in a 100 by 100 box with preserveAspectRatio none, so a path coordinate is a percent of
   the layer and every end lands on a column centre whatever the width. The stroke, the glow and the
   weight are .rw-wire's. */
.ft-wires { position: relative; height: 56px; }
.ft-wires svg { width: 100%; height: 100%; display: block; overflow: visible; }
/* THE ARROWHEAD IS AN HTML ELEMENT, NOT AN SVG MARKER. The layer scales x and y independently, and a
   marker drawn in that space is squashed with it. */
.ft-heads { position: absolute; inset: 0; pointer-events: none; }
.ft-head {
  position: absolute; bottom: -1px; transform: translateX(-50%);
  width: 0; height: 0;
  border-left: 5px solid transparent; border-right: 5px solid transparent;
  border-top: 7px solid var(--hue, var(--teal-dark));
}

/* ---- The cards ----
   Six in one row at the width the wires are drawn for. .rw-card gives each one the vertical
   gradient, the hairline edge and the lit top border in its own hue. */
.ft-agents {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: var(--s3);
  align-items: stretch;
}
.ft-agent { display: grid; align-content: start; gap: var(--s2); min-width: 0; }
.ft-agent-name { margin: 0; font-size: var(--t-body); line-height: 1.25; font-weight: 700; color: var(--ink); overflow-wrap: anywhere; }
.ft-agent-op { margin: 0; font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-2); overflow-wrap: anywhere; }

/* The three rows the target puts on the face of every card. They are stacked rather than set in two
   columns: a 220px card cannot hold a label and "Operated by its organisation" side by side, and the
   target stacks them too. */
.ft-agent-rows { margin: var(--s3) 0 0; display: grid; gap: var(--s3); min-width: 0; }
.ft-agent-row { display: grid; gap: 2px; min-width: 0; }
.ft-agent-row dt { font-size: 14px; line-height: 1.3; color: var(--ink-2); }
.ft-agent-row dd { margin: 0; font-size: 14px; line-height: 1.35; color: var(--ink); overflow-wrap: anywhere; }

/* An authorization detail type is a value a platform compares, so it is set in the mono face, which
   is what says it is a string rather than a phrase. */
.ft-types { display: flex; flex-wrap: wrap; gap: 4px; }
.ft-type {
  display: inline-flex; align-items: center;
  padding: 1px 6px; border-radius: var(--r-1);
  border: 1px solid var(--rule);
  font-family: var(--mono); font-size: var(--t-mono); line-height: 1.5;
  color: var(--teal-dark);
  overflow-wrap: anywhere;
}

/* THE ONE AGENT WHOSE OPERATOR ASKS BEYOND THE CEILING ITS ROOT HOLDS. It is muted rather than
   coloured: nothing was refused on a wire here, so a warning colour would be the green tick's
   mistake in the other direction. The dashed edge says the type is claimed and outside. */
.ft-outside {
  margin: var(--s3) 0 0; padding-top: var(--s3);
  border-top: 1px dashed var(--rule);
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  font-size: 14px; line-height: 1.35; color: var(--ink-2);
}
.ft-outside .ft-type { border-style: dashed; color: var(--ink-2); }

/* A HUE PER LISTING KIND, AND IT IS IDENTITY RATHER THAN STATUS.
   Green means Observed, amber means in progress and red means refused, on every surface of this
   site, and packages/ui/tests/stylesheet.test.ts refuses a palette built out of those three.
   --d-blue and --d-violet carry no meaning anywhere in this system, which is exactly what lets them
   carry identity here. --d-sand is out of the set because it sits a few degrees from --att and would
   read as pending. */
.ft [data-listed="authority"] { --hue: var(--d-blue); }
.ft [data-listed="root"] { --hue: var(--d-violet); }

/* ---- The record behind each agent, closed ----
   THE FACTS IN IT LEAVE NO PAGE. The publisher of an agent's release is a different party from its
   operator on one of the six, and the declared task labels are the words the estate uses for what
   each agent does. Neither is on the face of a card and neither is anywhere else on this site in
   full, so the claim page keeps them behind one disclosure rather than dropping them. A reader who
   wants the rest of the record follows the link in each row to the live demonstration. */
.ft-records { margin: 0; }
.ft-records > summary { font-size: var(--t-small); }
.ft-records-table { width: 100%; border-collapse: collapse; margin-top: var(--s4); }
.ft-records-table th, .ft-records-table td {
  text-align: left; vertical-align: top;
  padding: var(--s3) var(--s4) var(--s3) 0;
  border-bottom: 1px solid var(--hairline);
  font-size: var(--t-small); line-height: var(--t-small-line);
}
.ft-records-table th { color: var(--ink-2); font-weight: 600; }
.ft-records-table td { color: var(--ink); }
.ft-records-table ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
/* THE WAY TO THAT AGENT ON THE LIVE DEMONSTRATION IS THE NAME ITSELF, and the sentence saying so is
   printed once above the table. Every row carried the same six word label under the name, which is
   one control repeated six times in a table twelve lines tall. */
.ft-records-note { margin: 0 0 var(--s3); font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-2); }
.ft-records-link { color: var(--teal-dark); text-decoration: none; border-bottom: 1px solid color-mix(in srgb, var(--teal-dark) 45%, transparent); }
.ft-records-link:hover, .ft-records-link:focus-visible { color: var(--brand-strong); border-bottom-color: currentColor; }
/* A table narrower than its own columns wraps a hostname down the page. It scrolls inside its own
   box instead, which is the one place the base sheet allows a sideways scroll. */
.ft-records-scroll { overflow-x: auto; }

/* ---- Narrow ----
   THE WIRE LAYER GOES WHERE THE CARDS STOP BEING ONE ROW. A connector drawn to a column that is no
   longer under it points between two cards, and a diagram that points at the wrong card is worse
   than one with no connectors at all. The anchor then sits directly over the cards, which is the
   same reading in less width. */
@media (max-width: 1320px) {
  .ft-wires { display: none; }
  .ft-agents { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s4); }
}
@media (max-width: 900px) {
  .ft-agents { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .ft-agents { grid-template-columns: minmax(0, 1fr); }
  .ft-anchor { max-width: 100%; }
}

/* ---- src/parts/fte.css ---- */
/* THE FIGURES OF /use-cases/find-and-trust/evidence: packages/ui/partials/fte-issue.ejs,
 * fte-accredit.ejs, fte-policy.ejs, fte-timeline.ejs and fte-agents.ejs.
 *
 * THE TREATMENTS ARE components/diagram-section.tsx's, by class from rw.css: the lit card, the small
 * pedestal, the hub, the ambient pool. This file places them.
 *
 * IDENTITY HUES FOR IDENTITY. Each party, role, lane or listing route carries its hue in `--hue`. The
 * one state colour here is --no on the word Refused, beside the word.
 *
 * EVERY SIZE IS 14PX OR MORE.
 *
 * rw.css SORTS AFTER THIS FILE, so every rule that restyles an rw- class names its figure as well.
 */

.fte-is, .fte-ac, .fte-po, .fte-tl, .fte-ag { position: relative; margin: 0; container-type: inline-size; min-width: 0; }
.fte-is > *, .fte-ac > *, .fte-po > *, .fte-tl > *, .fte-ag > * { position: relative; z-index: 1; }
.fte-is > .rw-glow, .fte-ac > .rw-glow, .fte-po > .rw-glow, .fte-tl > .rw-glow, .fte-ag > .rw-glow { position: absolute; z-index: 0; }
.fte-mark { margin: var(--s4) 0 0; font-size: 14px; line-height: 1.5; color: var(--ink-2); }
.fte-is code, .fte-ac code, .fte-po code, .fte-ag code { background: none; padding: 0; }

/* ================================================================
   fte-issue: approve, issue, resolve.
   ================================================================ */
.fte-is-glow { top: 40px; }
.fte-is-steps {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: var(--tracks, 1fr 1.35fr 1fr); gap: var(--s6);
  align-items: start;
}
.fte-is-step { position: relative; display: flex; flex-direction: column; min-width: 0; }
.fte-is-ped { height: 68px; }
.fte-is .fte-is-card, .fte-is .fte-is-hub { padding: var(--s4) var(--s5) var(--s5); text-align: left; }
.fte-is-n { margin: 0; font-size: 14px; line-height: 1.3; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: var(--hue); }
.fte-is-num { color: var(--ink-2); margin-right: 4px; }
.fte-is-t { margin: var(--s2) 0 0; font-size: 19px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.fte-is-l { margin: 6px 0 0; font-size: 15px; line-height: 1.5; color: var(--ink-2); }
.fte-is-fields { list-style: none; margin: var(--s4) 0 0; padding: var(--s3) 0 0; border-top: 1px solid var(--hairline); display: grid; gap: 8px; }
.fte-is-fields li { display: flex; gap: var(--s2); align-items: baseline; font-size: 15px; line-height: 1.45; color: var(--ink); }
.fte-is-fields li::before { content: ""; flex: 0 0 auto; width: 7px; height: 7px; border-radius: 50%; background: var(--brand-strong); box-shadow: 0 0 6px var(--brand-strong); transform: translateY(-1px); }

/* THE WIRE, from the right edge of one card to the left edge of the next, level with the card tops
   plus a little, with a filled arrowhead. It spans the grid gap exactly. */
.fte-is-wire {
  position: absolute; top: calc(68px + 40px); right: calc(-1 * var(--s6)); width: var(--s6); height: 2px;
  background: var(--teal-dark); box-shadow: 0 0 6px var(--teal-dark);
}
.fte-is-wire::after {
  content: ""; position: absolute; right: -1px; top: -5px;
  border-left: 9px solid var(--brand-strong); border-top: 6px solid transparent; border-bottom: 6px solid transparent;
}
@container (max-width: 760px) {
  .fte-is-steps { grid-template-columns: minmax(0, 1fr); gap: var(--s6); }
  .fte-is-wire { top: auto; bottom: calc(-1 * var(--s6)); right: auto; left: 50%; width: 2px; height: var(--s6); }
  .fte-is-wire::after { right: auto; top: auto; bottom: -1px; left: -5px; border-left: 6px solid transparent; border-right: 6px solid transparent; border-top: 9px solid var(--brand-strong); border-bottom: 0; }
}

/* ================================================================
   fte-accredit: the chain of grants, and three writes against it.
   ================================================================ */
.fte-ac-glow { top: 40px; }
.fte-ac-grid { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--s6); align-items: start; }
.fte-ac-chain { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s5); }
.fte-ac .fte-ac-tier { display: flex; gap: var(--s3); align-items: center; padding: var(--s3) var(--s4); border-left: 3px solid var(--hue); }
/* The connector between tiers: a short glowing line down from each tier to the next. */
.fte-ac-tier + .fte-ac-tier::before {
  content: ""; position: absolute; left: 30px; top: calc(-1 * var(--s5) - 1px); width: 2px; height: var(--s5);
  background: var(--teal-dark); box-shadow: 0 0 6px var(--teal-dark);
}
.fte-ac-i { display: inline-flex; color: var(--hue); filter: drop-shadow(0 0 8px var(--hue)); }
.fte-ac-i svg { width: 28px; height: 28px; }
.fte-ac-tw { display: flex; flex-direction: column; min-width: 0; }
.fte-ac-tt { font-size: 16px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.fte-ac-tl { font-size: 14px; line-height: 1.45; color: var(--ink-2); }

.fte-ac-writes { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s3); counter-reset: w; }
.fte-ac-w {
  counter-increment: w;
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s2) var(--s4);
  padding: var(--s3) var(--s4); border-radius: 10px;
  border: 1px solid var(--hairline);
  background: linear-gradient(180deg, var(--paper-alt) 0%, var(--paper) 100%);
}
.fte-ac-ref { font-size: 15px; line-height: 1.45; color: var(--ink); min-width: 0; }
.fte-ac-ref::before { content: counter(w); display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; margin-right: var(--s3); border-radius: 50%; border: 1px solid var(--hairline); font-size: 14px; font-weight: 700; color: var(--ink-2); }
.fte-ac-ans { display: inline-flex; align-items: center; gap: var(--s2); }
.fte-ac .fte-ac-code { font-family: var(--mono); font-size: 14px; font-weight: 700; padding: 2px 8px; border-radius: 6px; border: 1px solid var(--hairline); color: var(--ink); }
.fte-ac-word { font-size: 14px; font-weight: 600; color: var(--ink); }
.fte-ac-w[data-refused="true"] { border-color: color-mix(in srgb, var(--no) 45%, transparent); }
.fte-ac-w[data-refused="true"] .fte-ac-word { color: var(--no); }
.fte-ac-quote { margin: var(--s4) 0 0; padding: var(--s3) var(--s4); border-left: 3px solid var(--no); border-radius: 0 8px 8px 0; background: var(--paper-alt); }
.fte-ac-quote { display: flex; gap: var(--s3); align-items: flex-start; }
.fte-ac-qn { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: 50%; border: 1px solid var(--hairline); font-size: 14px; font-weight: 700; color: var(--ink-2); }
.fte-ac-quote code { font-family: var(--mono); font-size: 14px; line-height: 1.55; color: var(--ink-2); overflow-wrap: break-word; min-width: 0; }
@container (max-width: 760px) {
  .fte-ac-grid { grid-template-columns: minmax(0, 1fr); }
}
/* ON A PHONE EVERY ANSWER TAKES ITS OWN LINE UNDER ITS REFERENCE, so the three writes read alike
   rather than wrapping wherever each reference happens to end. */
@container (max-width: 480px) {
  .fte-ac-w { flex-direction: column; align-items: flex-start; }
}

/* ================================================================
   fte-policy: roles fold into the statement.
   ================================================================ */
.fte-po-glow { top: 60px; }
.fte-po-grid { display: grid; grid-template-columns: minmax(0, 5fr) 48px minmax(0, 7fr); align-items: center; }
.fte-po-roles { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s3); }
.fte-po .fte-po-role { display: flex; flex-direction: column; gap: 4px; padding: var(--s3) var(--s4); border-left: 3px solid var(--hue); }
.fte-po-name-w { display: flex; align-items: center; gap: var(--s2); min-width: 0; }
.fte-po .fte-po-name { font-family: var(--mono); font-size: 15px; font-weight: 700; color: var(--hue); overflow-wrap: anywhere; }
/* THE LETTER, which carries the role for a reader who cannot tell the hues apart. */
.fte-po-key { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; min-width: 20px; height: 20px; padding: 0 4px; border-radius: 4px; background: var(--hue); color: var(--paper); font-size: 14px; font-weight: 700; line-height: 1; }
.fte-po-note { font-size: 14px; line-height: 1.45; color: var(--ink-2); }
.fte-po-wire { position: relative; height: 2px; margin: 0 6px; background: var(--teal-dark); box-shadow: 0 0 6px var(--teal-dark); }
.fte-po-wire::after { content: ""; position: absolute; right: -1px; top: -5px; border-left: 9px solid var(--brand-strong); border-top: 6px solid transparent; border-bottom: 6px solid transparent; }
.fte-po .fte-po-hub { text-align: left; padding: var(--s5); }
.fte-po-ht { margin: 0; font-size: 18px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.fte-po-hs { margin: 4px 0 0; }
.fte-po-hs code { font-family: var(--mono); font-size: 14px; color: var(--ink-2); }
.fte-po-rows { margin: var(--s4) 0 0; display: grid; gap: 0; }
.fte-po-row { padding: 10px 0; border-top: 1px solid var(--hairline); min-width: 0; }
.fte-po-row dt { margin: 0; font-size: 14px; line-height: 1.4; color: var(--ink); }
.fte-po-row dt code { font-family: var(--mono); font-size: 14px; font-weight: 600; overflow-wrap: anywhere; }
.fte-po-op { margin-left: 6px; font-size: 14px; color: var(--ink-2); }
.fte-po-row dd { margin: 6px 0 0; display: flex; flex-wrap: wrap; gap: 6px; }
.fte-po .fte-po-v {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 14px; line-height: 1.4; color: var(--ink);
  padding: 2px 8px 2px 4px; border-radius: 6px;
  border: 1px solid color-mix(in srgb, var(--hue) 55%, transparent);
  overflow-wrap: anywhere;
}
.fte-po .fte-po-v code { font-family: var(--mono); font-size: 14px; min-width: 0; overflow-wrap: anywhere; }
.fte-po-v .fte-po-key { min-width: 18px; height: 18px; }
@container (max-width: 760px) {
  .fte-po-grid { grid-template-columns: minmax(0, 1fr); gap: var(--s4); }
  .fte-po-roles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .fte-po-wire { justify-self: center; width: 2px; height: 32px; margin: 0; }
  .fte-po-wire::after { right: auto; top: auto; bottom: -1px; left: -5px; border-left: 6px solid transparent; border-right: 6px solid transparent; border-top: 9px solid var(--brand-strong); border-bottom: 0; }
}
@container (max-width: 480px) {
  .fte-po-roles { grid-template-columns: minmax(0, 1fr); }
}

/* ================================================================
   fte-timeline: what was served after each write.
   ================================================================ */
.fte-tl-glow { top: 40px; }
.fte-tl { display: grid; gap: var(--s4); }
.fte-tl .fte-tl-track { padding: var(--s4) var(--s5) var(--s5); }
.fte-tl-t { margin: 0 0 var(--s4); font-size: 16px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.fte-tl-events { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(var(--n), minmax(0, 1fr)); position: relative; }
.fte-tl-e { position: relative; display: flex; flex-direction: column; align-items: flex-start; gap: var(--s2); padding-right: var(--s4); min-width: 0; }
/* The lane: a line through every dot, in the lane's hue. Each event draws the stretch from its own
   dot to the next one, so the line ends at the last dot rather than at the card edge. */
.fte-tl-e:not(:last-child)::after {
  /* The dot's centre: the time label's line box (14px on 1.4), the gap, then half the 16px dot, less
     half the line. Written in px because em here resolves on the list item, not the label. */
  content: ""; position: absolute; left: 7px; right: -7px; top: calc(19.6px + var(--s2) + 7px); height: 2px;
  background: var(--hue); opacity: 0.8; box-shadow: 0 0 6px var(--hue);
}
.fte-tl-time { font-family: var(--mono); font-size: 14px; line-height: 1.4; font-weight: 700; color: var(--ink); white-space: nowrap; }
.fte-tl-dot { position: relative; z-index: 1; width: 16px; height: 16px; border-radius: 50%; border: 2px solid var(--hue); background: var(--paper); box-shadow: 0 0 8px var(--hue); }
.fte-tl-first .fte-tl-dot { background: var(--hue); }
.fte-tl-word { font-size: 15px; line-height: 1.45; color: var(--ink-2); }
.fte-tl-first .fte-tl-word { color: var(--ink); }
.fte-tl > .fte-mark { margin-top: 0; }
.fte-tl-gap { margin: 0; padding: var(--s3) var(--s4); border-radius: 10px; border: 1px dashed var(--hairline); font-size: 15px; line-height: 1.5; color: var(--ink); }
.fte-tl-gap-m { margin-right: var(--s2); }
@container (max-width: 700px) {
  .fte-tl-events { grid-template-columns: minmax(0, 1fr); gap: var(--s4); }
  .fte-tl-e { display: grid; grid-template-columns: 16px minmax(0, 1fr); grid-template-rows: auto auto; column-gap: var(--s3); row-gap: 2px; padding-right: 0; }
  .fte-tl-dot { grid-column: 1; grid-row: 1; margin-top: 2px; }
  .fte-tl-time { grid-column: 2; grid-row: 1; }
  .fte-tl-word { grid-column: 2; grid-row: 2; }
  .fte-tl-e:not(:last-child)::after { left: 7px; right: auto; top: 18px; bottom: calc(-1 * var(--s4) - 2px); width: 2px; height: auto; }
}

/* ================================================================
   fte-agents: every agent, by listing route.
   ================================================================ */
.fte-ag-glow { top: 80px; }
.fte-ag-groups { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s6); }
.fte-ag-gt { margin: 0 0 var(--s3); padding-bottom: var(--s2); border-bottom: 2px solid var(--hue); font-size: 14px; line-height: 1.3; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: var(--hue); }
.fte-ag-gn { color: var(--ink); margin-right: 4px; }
.fte-ag-list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s3); }
.fte-ag .fte-ag-card { padding: var(--s3) var(--s4) var(--s4); display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.fte-ag-name { margin: 0; font-size: 16px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.fte-ag-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s2); }
.fte-ag-rt { flex: 0 0 auto; display: inline-flex; color: var(--hue); filter: drop-shadow(0 0 6px var(--hue)); }
.fte-ag .fte-ag-rt svg { width: 22px; height: 22px; }
/* uc-glyph wraps its svg in a sized span, and its layers glyph runs edge to edge where the evf-icon
   glyphs leave a margin. Both are held to the same box here, the layers one a little inside it. */
.fte-ag .fte-ag-rt .sc-glyph { display: inline-flex; width: 22px; height: 22px; padding: 2px; }
.fte-ag .fte-ag-rt .sc-glyph svg { width: 18px; height: 18px; }
.fte-ag-key { list-style: none; margin: var(--s4) 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--s2) var(--s5); }
.fte-ag-key li { display: inline-flex; align-items: center; gap: var(--s2); font-size: 14px; line-height: 1.4; color: var(--ink-2); }
.fte-ag-key .fte-ag-rt { color: var(--ink-2); filter: none; }
.fte-ag-op { margin: 0; font-size: 14px; line-height: 1.45; color: var(--ink); }
.fte-ag-pub { color: var(--hue); }
.fte-ag-types, .fte-ag-out { margin: 4px 0 0; display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.fte-ag .fte-ag-type { font-family: var(--mono); font-size: 14px; line-height: 1.4; padding: 2px 8px; border-radius: 6px; border: 1px solid var(--hairline); color: var(--ink); }
.fte-ag-out { padding-top: 8px; border-top: 1px dashed var(--hairline); }
.fte-ag-out-l { width: 100%; font-size: 14px; font-weight: 600; color: var(--ink-2); }
.fte-ag-out .fte-ag-type { border-style: dashed; color: var(--ink-2); }
@container (max-width: 1000px) {
  .fte-ag-list { grid-template-columns: minmax(0, 1fr); }
}
@container (max-width: 640px) {
  .fte-ag-groups { grid-template-columns: minmax(0, 1fr); }
}

/* ---- src/parts/gb.css ---- */
/* /governance: the instrument, packages/ui/partials/gb-bounds.ejs.
 *
 * THE TREATMENTS ARE components/diagram-section.tsx's, taken from rw.css by class: the pedestal
 * under each party, the lit card, the hub every wire lands on, the glowing wires and the ambient
 * pool. This file places them.
 *
 * FOUR IDENTITY HUES AND NO STATE COLOUR. Each party carries its hue in `--hue` and every card it
 * sets takes the same one, so a reader matches a card to its owner by colour. Nothing on the figure
 * is a reading from a run, so --ok, --att and --no appear nowhere in this file.
 */
.gb { position: relative; margin: 0; min-width: 0; }
.gb-glow { top: 160px; width: 1100px; }

/* ---- THE PARTY ROW ---- */
.gb-parties {
  position: relative; list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(var(--gb-n), minmax(0, 1fr)); column-gap: var(--s4);
}
.gb-party { display: flex; flex-direction: column; align-items: center; text-align: center; min-width: 0; }
.gb-party .rw-ped { width: 100%; }
.gb-party-t { margin: var(--s2) 0 0; font-size: 17px; font-weight: 700; color: var(--ink); letter-spacing: -0.01em; }
.gb-party-s { margin: 2px 0 0; font-size: 14px; color: var(--ink-2); }

/* ---- THE WIRES ---- */
.gb-wires { display: block; width: 100%; overflow: visible; }
.gb-wires-up { height: 56px; margin-top: var(--s2); }
.gb-wires-down { height: 64px; filter: drop-shadow(0 0 5px color-mix(in srgb, var(--teal-dark) 70%, transparent)); }
.gb-wire {
  fill: none; stroke: var(--hue, var(--teal-dark)); stroke-width: 2; stroke-linecap: round; opacity: 0.85;
  vector-effect: non-scaling-stroke;
}
.gb-wires-up g { filter: drop-shadow(0 0 4px var(--hue)); }
.gb-wire-head { fill: var(--hue, var(--brand-strong)); }
.gb-wire-in { stroke: var(--teal-dark); }
.gb-wire-in-head { fill: var(--brand-strong); }

/* ---- THE SIX CARDS ---- */
.gb-cards {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(var(--gb-n), minmax(0, 1fr)); column-gap: var(--s4);
}
.gb-card {
  position: relative; min-width: 0;
  display: flex; flex-direction: column; gap: var(--s4);
  padding: var(--s5) var(--s4);
  border-radius: 14px;
  border: 1px solid color-mix(in srgb, var(--ink) 10%, transparent);
  border-top-color: color-mix(in srgb, var(--hue) 55%, transparent);
  background: linear-gradient(180deg, color-mix(in srgb, var(--hue) 7%, var(--paper-alt)) 0%, var(--paper) 100%);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--hue) 40%, transparent);
}
.gb-tag { display: inline-flex; margin: 0; align-items: center; gap: var(--s2); font-size: 14px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-row); }
.gb-tag-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--hue); box-shadow: 0 0 8px var(--hue); }
.gb-head { display: flex; align-items: flex-start; gap: var(--s3); }
.gb-head > div { display: grid; min-width: 0; }
.gb-n {
  flex: none; display: inline-grid; place-items: center; width: 34px; height: 34px; border-radius: 50%;
  border: 1.5px solid var(--hue); color: var(--ink); font-size: 14px; font-weight: 700; font-variant-numeric: tabular-nums;
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--hue) 12%, transparent);
}
.gb-name { margin: 0; font-size: 18px; line-height: 1.25; font-weight: 700; color: var(--ink); letter-spacing: -0.01em; }
.gb-sub { margin: 2px 0 0; font-size: 14px; line-height: 1.4; color: var(--ink-2); }
.gb-rows { margin: 0; display: grid; gap: var(--s3); border-top: 1px solid var(--hairline); padding-top: var(--s4); }
.gb-row { display: grid; gap: 2px; min-width: 0; }
.gb-row dt { font-size: 14px; color: var(--ink-2); }
.gb-row dd { margin: 0; font-size: 14px; line-height: 1.45; font-weight: 600; color: var(--ink); overflow-wrap: break-word; }
.gb-row dd.gb-mono { font-family: var(--mono); font-weight: 500; color: var(--ink-row); }

/* ---- THE HUB ---- */
.gb .gb-hub { max-width: 760px; margin: 0 auto; text-align: left; }
.gb-hub-head { display: flex; align-items: flex-start; gap: var(--s4); }
.gb-hub-i { flex: none; display: inline-flex; color: var(--teal-dark); filter: drop-shadow(0 0 10px var(--teal-dark)); }
.gb-hub-i svg { width: 34px; height: 34px; display: block; }
.gb-hub-t { margin: 0; font-size: 22px; font-weight: 700; color: var(--ink); letter-spacing: -0.01em; }
.gb-hub-l { margin: var(--s1, 4px) 0 0; font-size: 15px; line-height: 1.5; color: var(--ink-lead); }
.gb-chips { list-style: none; margin: var(--s4) 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--s2); }
.gb-chip {
  display: inline-flex; align-items: baseline; gap: var(--s2);
  padding: 6px 12px; border-radius: var(--pill);
  border: 1px solid color-mix(in srgb, var(--teal-dark) 35%, transparent);
  background: var(--paper);
  font-size: 14px;
}
.gb-chip-l { color: var(--ink-2); }
.gb-chip-v { font-family: var(--mono); font-weight: 600; color: var(--brand-strong); }

/* ---- NARROW: the party moves onto each card, the wires go ---- */
/* ABOVE THE BREAK THE PARTY ROW CARRIES THE OWNER, so the tag on each card is hidden from sight and
   kept for a screen reader, which cannot follow a wire. */
@media (min-width: 1280px) {
  .gb-tag { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; }
}
/* SIX ACROSS NEEDS 1280. Measured at 1100: a card is 157px and "Accreditation" ran 24px past its
   edge under the next card. */
@media (max-width: 1279px) {
  .gb-parties, .gb-wires-up { display: none; }
  .gb-cards { grid-template-columns: repeat(3, minmax(0, 1fr)); row-gap: var(--s4); }
  .gb-wires-down { display: none; }
  .gb .gb-hub { margin-top: var(--s5); max-width: none; }
}
@media (max-width: 860px) {
  .gb-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* ON A PHONE THE CARDS RUN DOWN A SPINE that ends on the hub, so the fan in still reads as one
   direction: every card lands on the platform. */
@media (max-width: 600px) {
  .gb-cards { grid-template-columns: minmax(0, 1fr); row-gap: var(--s3); padding-left: 22px; position: relative; }
  .gb-cards::before {
    content: ""; position: absolute; left: 7px; top: 12px; bottom: -28px; width: 2px;
    background: linear-gradient(180deg, color-mix(in srgb, var(--teal-dark) 30%, transparent), var(--teal-dark));
    box-shadow: 0 0 8px var(--teal-dark);
  }
  .gb-card::before {
    content: ""; position: absolute; left: -20px; top: 28px; width: 10px; height: 10px; border-radius: 50%;
    background: var(--hue); box-shadow: 0 0 8px var(--hue);
  }
  .gb-card { padding: var(--s4); }
  .gb .gb-hub { margin-top: var(--s5); padding: var(--s5) var(--s4); }
}

/* ---- THE WITHDRAWAL FIGURE, packages/ui/partials/gb-withdraw.ejs, on /governance/evidence ----
   Three columns joined by two wires. The state chips are the base sheet's .state[data-state], so a
   state colour here means what it means everywhere and always sits beside its word. */
.gbw {
  position: relative; margin: 0;
  display: grid; grid-template-columns: minmax(180px, 0.7fr) 56px minmax(0, 1.3fr) 56px minmax(0, 1.1fr);
  align-items: center;
}
.gbw-actor { display: flex; flex-direction: column; align-items: center; text-align: center; }
.gbw-actor .rw-ped { width: 100%; }
.gbw-actor-t { margin: var(--s2) 0 0; font-size: 17px; font-weight: 700; color: var(--ink); }
.gbw-actor-s { margin: 2px 0 0; font-size: 14px; color: var(--ink-2); max-width: 16rem; }
.gbw-link { position: relative; height: 2px; background: var(--teal-dark); box-shadow: 0 0 8px var(--teal-dark); }
.gbw-link::after {
  content: ""; position: absolute; right: -2px; top: 50%; transform: translateY(-50%);
  border-left: 9px solid var(--brand-strong); border-top: 6px solid transparent; border-bottom: 6px solid transparent;
}
.gbw-surfaces { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s3); }
.gbw-card {
  display: grid; gap: var(--s2); padding: var(--s4) var(--s5); border-radius: 12px;
  border: 1px solid color-mix(in srgb, var(--ink) 10%, transparent);
  background: linear-gradient(180deg, var(--paper-alt) 0%, var(--paper) 100%);
}
.gbw-card > * { margin: 0; }
.gbw-consumer { border-color: color-mix(in srgb, var(--teal-dark) 35%, transparent); box-shadow: 0 0 32px color-mix(in srgb, var(--teal-dark) 12%, transparent), inset 0 1px 0 color-mix(in srgb, var(--brand-strong) 30%, transparent); }
.gbw-t { font-size: 16px; font-weight: 700; color: var(--ink); }
.gbw-l { font-size: 14px; line-height: 1.5; color: var(--ink-lead); }
.gbw-code code { font-family: var(--mono); font-size: 14px; color: var(--ink-row); overflow-wrap: anywhere; }
.gbw-foot { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2) var(--s3); }
@media (max-width: 999px) {
  .gbw { grid-template-columns: minmax(0, 1fr); row-gap: var(--s4); }
  .gbw-link { width: 2px; height: 32px; justify-self: center; }
  .gbw-link::after { right: auto; left: 50%; top: auto; bottom: -2px; transform: translateX(-50%); border-top: 9px solid var(--brand-strong); border-left: 6px solid transparent; border-right: 6px solid transparent; border-bottom: 0; }
}

/* ---- src/parts/gg.css ---- */
/* /estate: the page and its one instrument, packages/ui/partials/gg-graph.ejs.
 *
 * THE TREATMENTS ARE components/diagram-section.tsx's, from the reference build: the environment card
 * lit from above in its hue, the pedestal, beziers with filled arrowheads under a glow, the ambient
 * pool, the side panel and the ringed benefits row. The shared parts come from rw.css by class.
 *
 * FOUR IDENTITY HUES AND NO STATE COLOUR IN THE FIGURE. Each card and each line carries `--hue` on
 * its own element: the enterprise blue (--d-blue), a publisher violet (--d-violet), a partner green
 * (--d-magenta) and the scheme amber (--d-sand). A line the reading did not find is dashed and says
 * so in words; it takes no state colour, because nothing about it was refused.
 *
 * EVERY RULE IS UNDER .gg OR .ggp, so nothing here reaches another route.
 */

/* ---- THE FIGURE ---- */
.gg { position: relative; margin: 0; }
.gg-sr {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; margin: 0;
}

/* THE WIDE STATE, from 1200px. Eight equal columns and four tiers. Below that the narrow state. */
.gg-wide { position: relative; display: none; padding: var(--s2) 0 0; }
.gg-narrow { display: block; }
@media (min-width: 1200px) {
  .gg-wide { display: block; }
  .gg-narrow { display: none; }
}
.gg-glow { top: 30%; width: 1100px; height: 520px; opacity: 0.18; }
.gg-wires {
  position: absolute; inset: 0; z-index: 1; pointer-events: none; overflow: visible;
  filter: drop-shadow(0 0 4px color-mix(in srgb, var(--teal-dark) 45%, transparent));
}
.gg-grid {
  position: relative; z-index: 2;
  display: grid; grid-template-columns: repeat(8, minmax(0, 1fr));
  column-gap: 16px; row-gap: 64px;
  align-items: stretch;
}
.gg-t-anchor { grid-row: 1; }
.gg-t-authority, .gg-recognises { grid-row: 2; }
.gg-t-root, .gg-tier-note { grid-row: 3; }
.gg-t-agent { grid-row: 4; }
/* The channel above the agents holds the routed lines, so it is the widest gap. */
.gg-grid { grid-template-rows: auto auto auto auto; }
.gg-t-root { margin-bottom: 20px; margin-top: 24px; }

/* 2. THE ENVIRONMENT CARD, in the card's own hue. */
.gg-card {
  position: relative; min-width: 0; border-radius: 10px;
  border: 1px solid color-mix(in srgb, var(--ink) 10%, transparent);
  border-top-color: color-mix(in srgb, var(--hue) 55%, transparent);
  background: linear-gradient(180deg, var(--paper-alt) 0%, var(--paper) 100%);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--hue) 40%, transparent);
  padding: 14px 14px 16px;
  transition: opacity 240ms ease, box-shadow 240ms ease, border-color 240ms ease;
}
.gg-t-anchor, .gg-t-authority {
  background: radial-gradient(120% 90% at 50% 0%, color-mix(in srgb, var(--hue) 14%, var(--paper-alt)) 0%, var(--paper) 70%);
  border-color: color-mix(in srgb, var(--hue) 35%, transparent);
  box-shadow: 0 0 36px color-mix(in srgb, var(--hue) 10%, transparent), inset 0 1px 0 color-mix(in srgb, var(--hue) 45%, transparent);
  padding: 16px 20px 18px;
}
.gg-kicker {
  display: flex; align-items: center; gap: 8px; margin: 0;
  font-size: 14px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--hue);
}
.gg-glyph { display: inline-flex; color: var(--hue); }
.gg-glyph svg { width: 18px; height: 18px; }
.gg-name { margin: 6px 0 0; font-size: 16px; font-weight: 700; line-height: 1.25; letter-spacing: -0.01em; color: var(--ink); overflow-wrap: anywhere; }
.gg-t-anchor .gg-name, .gg-t-authority .gg-name { font-size: 18px; }
.gg-name a { color: inherit; text-decoration: none; }
.gg-name a:hover, .gg-name a:focus-visible { text-decoration: underline; text-underline-offset: 3px; }
.gg-op { margin: 2px 0 0; font-size: 14px; line-height: 1.35; color: var(--ink-2); }
.gg-rows { margin: 12px 0 0; display: grid; gap: 8px; }
.gg-row { display: grid; gap: 1px; padding-left: 10px; border-left: 2px solid color-mix(in srgb, var(--hue) 45%, transparent); }
.gg-row dt { font-size: 14px; line-height: 1.3; color: var(--ink-2); }
.gg-row dd { margin: 0; font-size: 14px; line-height: 1.35; font-weight: 600; color: var(--ink); }
.gg-rows-inline { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 16px; }

/* 1. THE PEDESTAL under each anchor, left of its words. */
.gg-anchor-in { display: flex; align-items: center; gap: 18px; }
.gg-ped { flex: 0 0 92px; }
.gg-anchor-t { min-width: 0; flex: 1; }

.gg-recognises {
  grid-column: 5; align-self: center; justify-self: center; margin: 0;
  position: relative; z-index: 3;
  padding: 6px 10px; border-radius: 999px;
  background: var(--paper); border: 1px dashed color-mix(in srgb, var(--d-blue) 50%, transparent);
  font-size: 14px; line-height: 1.3; text-align: center; color: var(--ink-lead);
}
.gg-tier-note {
  position: relative; z-index: 3; align-self: center; margin: 0; padding: 4px 10px; border-radius: 6px; background: var(--paper);
  font-size: 14px; line-height: 1.4; color: var(--ink-2); text-align: right; font-style: italic;
}
.gg-note-direct { justify-self: end; max-width: 16rem; }

/* 4. THE CONNECTORS. */
.gg-w-line { fill: none; stroke: var(--hue); stroke-width: 1.75; stroke-linecap: round; opacity: 0.8; transition: opacity 240ms ease, stroke-width 240ms ease; }
.gg-w-head { fill: var(--hue); opacity: 0.9; transition: opacity 240ms ease; }
.gg-w-recognises .gg-w-line { stroke-dasharray: 2 6; stroke-width: 2; }
.gg-w[data-line="unread"] .gg-w-line { stroke-dasharray: 6 6; opacity: 0.45; }

/* THE LIT CHAIN. With an agent active, its lines and cards stay at full strength and the rest step
   back. Every word stays readable: a dimmed card keeps its text above the contrast floor because the
   step back is on the lines and the card edge, never on the text. */
.gg[data-active] .gg-w .gg-w-line { opacity: 0.16; }
.gg[data-active] .gg-w .gg-w-head { opacity: 0.2; }
.gg[data-active] .gg-w.is-lit .gg-w-line { opacity: 1; stroke-width: 2.75; }
.gg[data-active] .gg-w.is-lit .gg-w-head { opacity: 1; }
.gg[data-active] .gg-card { border-color: color-mix(in srgb, var(--ink) 6%, transparent); box-shadow: none; }
.gg[data-active] .gg-card.is-lit {
  border-color: color-mix(in srgb, var(--hue) 70%, transparent);
  box-shadow: 0 0 28px color-mix(in srgb, var(--hue) 22%, transparent), inset 0 1px 0 color-mix(in srgb, var(--hue) 60%, transparent);
}

.gg-foot { position: relative; z-index: 2; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s4); margin-bottom: var(--s5); }
.gg-hint { margin: 0; font-size: 14px; color: var(--ink-2); }
.gg-pause {
  min-height: 36px; padding: 0 var(--s4); border-radius: 999px; cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--teal-dark) 45%, transparent);
  background: transparent; color: var(--brand-strong); font: inherit; font-size: 14px; font-weight: 600;
}
.gg-pause:hover { background: var(--wash-teal); }

/* ---- THE NARROW STATE ---- */
.gg-n-domains { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.gg-n-domain {
  display: grid; justify-items: start; gap: 6px; padding: 14px;
  border-radius: 10px; border: 1px solid color-mix(in srgb, var(--hue) 35%, transparent);
  background: radial-gradient(120% 90% at 50% 0%, color-mix(in srgb, var(--hue) 14%, var(--paper-alt)) 0%, var(--paper) 75%);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--hue) 45%, transparent);
}
.gg-n-top { margin: 0; display: grid; gap: 2px; min-width: 0; }
.gg-n-top .gg-kicker { font-size: 14px; letter-spacing: 0.1em; }
.gg-n-top-n { font-size: 15px; font-weight: 700; line-height: 1.3; color: var(--ink); overflow-wrap: anywhere; }
.gg-n-top-n a { color: inherit; }
.gg-n-down { width: 2px; height: 16px; margin-left: 10px; background: var(--hue); opacity: 0.7; }
.gg-n-agents { list-style: none; margin: 16px 0 0; padding: 0; display: grid; gap: 10px; }
@media (min-width: 720px) {
  .gg-n-agents { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.gg-n-agent {
  padding: 14px 14px 14px 18px; border-radius: 10px; position: relative;
  border: 1px solid color-mix(in srgb, var(--ink) 10%, transparent);
  border-left: 3px solid var(--hue);
  background: linear-gradient(180deg, var(--paper-alt) 0%, var(--paper) 100%);
}
.gg-n-name { margin: 0; font-size: 16px; font-weight: 700; color: var(--ink); }
.gg-n-name a { color: inherit; }
.gg-n-paths { list-style: none; margin: 12px 0 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; }
/* ONE LADDER PER CHAIN, read top to bottom from the agent's first superior to the anchor. Each rung
   is a dot in the hue of the party that signs it, joined by a short rail. */
.gg-n-path {
  display: flex; flex-direction: column; padding: 10px 12px; border-radius: 8px;
  background: var(--paper-alt);
  border: 1px solid color-mix(in srgb, var(--ink) 8%, transparent);
}
.gg-n-step {
  position: relative; display: block; padding-left: 20px;
  font-size: 14px; line-height: 1.35; color: var(--ink);
}
.gg-n-step::before {
  content: ""; position: absolute; left: 1px; top: 0.35em; width: 10px; height: 10px; border-radius: 50%;
  background: var(--hue); box-shadow: 0 0 6px var(--hue);
}
.gg-n-sep { display: block; width: 2px; height: 10px; margin: 2px 0 2px 5px; background: var(--rule); }

/* ---- THE KEY ---- */
.gg-key { position: relative; z-index: 2; display: flex; flex-wrap: wrap; gap: var(--s3) var(--s6); margin-top: var(--s5); padding-top: var(--s4); border-top: 1px solid color-mix(in srgb, var(--ink) 10%, transparent); }
.gg-key-parties, .gg-key-lines { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--s2) var(--s5); }
.gg-key-p, .gg-key-l { display: inline-flex; align-items: center; gap: 8px; font-size: 14px; line-height: 1.35; color: var(--ink-lead); }
.gg-key-sw { width: 12px; height: 12px; border-radius: 3px; background: var(--hue); box-shadow: 0 0 8px var(--hue); flex: 0 0 auto; }
.gg-key-line { width: 26px; height: 0; border-top: 2px solid var(--ink-2); flex: 0 0 auto; }
.gg-key-dot { border-top-style: dotted; }
.gg-key-dash { border-top-style: dashed; }

@media (prefers-reduced-motion: reduce) {
  .gg-card, .gg-w-line, .gg-w-head { transition: none; }
}

/* ---- THE PAGE ---- */
.ggp { --page-max: 1472px; }
.ggp-top { position: relative; padding-block: 3.5rem var(--s6); }
.ggp-top-in { display: grid; gap: var(--s5) var(--s7, 4rem); margin-top: var(--s4); }
@media (min-width: 1100px) {
  .ggp-top-in { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); align-items: start; }
  .ggp-top-side { padding-top: 6px; }
}
.ggp-eyebrow { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s3); margin: 0; font-size: 14px; font-weight: 600; letter-spacing: 0.22em; text-transform: uppercase; color: var(--brand-strong); }
.ggp-eyebrow-rule { color: var(--ink-2); }
.ggp-eyebrow-accent { color: var(--ink-2); }
.ggp-headline { margin: 0; line-height: 1.02; letter-spacing: -0.035em; max-width: 18ch; }
.ggp-headline .accent { display: block; }
.ggp-lead { margin: 0; max-width: 36rem; font-size: 17px; line-height: 1.55; color: var(--ink-lead); }
.ggp-lead p { margin: 0; }
.ggp-actions { margin: var(--s5) 0 0; display: flex; flex-wrap: wrap; gap: var(--s4); }
.ggp-read { margin: var(--s4) 0 0; font-size: 14px; line-height: 1.5; color: var(--ink-2); }

.ggp-figure { position: relative; padding-block: var(--s5) var(--s7, 4rem); }

.ggp-panels { display: grid; gap: var(--s5); padding-block: 0 var(--s7, 4rem); }
@media (min-width: 900px) {
  .ggp-panels { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.ggp-pins { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s5); }
.ggp-pin-h { margin: 0; display: flex; align-items: center; gap: 10px; font-size: 16px; font-weight: 700; color: var(--ink); }
.ggp-pin-sw { width: 12px; height: 12px; border-radius: 3px; background: var(--hue); box-shadow: 0 0 8px var(--hue); }
.ggp-pin-list { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.ggp-pin {
  display: inline-flex; align-items: center; gap: 6px; min-height: 28px; padding: 2px 10px; border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--hue) 40%, transparent);
  font-size: 14px; color: var(--ink);
}
.ggp-pin-for { margin: 10px 0 0; font-size: 14px; color: var(--ink-2); }
.ggp-keys { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s4); }
.ggp-key { display: grid; gap: 2px; padding-left: 12px; border-left: 2px solid color-mix(in srgb, var(--teal-dark) 45%, transparent); }
.ggp-key-who { font-size: 14px; color: var(--ink-2); }
.ggp-key-what { font-size: 15px; font-weight: 600; color: var(--ink); }
.ggp-key-ev { margin-top: 4px; }

/* 7. THE BENEFITS ROW: ringed icons, vertical hairlines between columns. */
.ggp-outcomes { list-style: none; margin: 0; padding: var(--s6) 0; display: grid; gap: var(--s5); border-top: 1px solid color-mix(in srgb, var(--ink) 10%, transparent); }
@media (min-width: 800px) {
  .ggp-outcomes { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0; }
  .ggp-outcome + .ggp-outcome { border-left: 1px solid color-mix(in srgb, var(--ink) 10%, transparent); }
}
.ggp-outcome { display: grid; justify-items: center; gap: var(--s2); padding: 0 var(--s4); text-align: center; }
.ggp-outcome-t { margin: var(--s2) 0 0; font-size: 17px; font-weight: 700; color: var(--ink); }
.ggp-outcome-l { margin: 0; font-size: 15px; line-height: 1.45; color: var(--ink-2); max-width: 22rem; }

.ggp-record { padding-block: var(--s5); }
.ggp-legend { padding-block: var(--s4) var(--s6); }
.ggp-close { padding-block: var(--s6); }

/* THE COUNTS IN THE HERO, derived from the model. One number and its words per tier. */
.ggp-counts { list-style: none; margin: var(--s5) 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--s3) var(--s4); }
.ggp-count { display: inline-flex; align-items: baseline; gap: 8px; }
.ggp-count-n { font-size: 28px; font-weight: 700; letter-spacing: -0.02em; color: var(--brand-strong); }
.ggp-count-w { font-size: 14px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-2); }
.ggp-outcome-ev { margin: 0; }

/* The recognition is not on any chain, so the walk never lights it and never dims it either. */
.gg[data-active] .gg-w-recognises .gg-w-line, .gg-w-recognises .gg-w-line { opacity: 0.85; }
.ggp-stray { font-size: 14px; overflow-wrap: anywhere; }
.gg-tag {
  margin: 10px 0 0; padding: 4px 8px; border-radius: 6px;
  border: 1px solid color-mix(in srgb, var(--teal-dark) 45%, transparent);
  font-size: 14px; line-height: 1.3; color: var(--brand-strong);
}

/* THE AGENT NAME AS A CONTROL, where no record link exists. It reads as the name and takes the ring. */
.gg-pick {
  appearance: none; margin: 0; padding: 0; border: 0; background: none; cursor: pointer;
  font: inherit; color: inherit; text-align: left; letter-spacing: inherit;
}
.gg-pick:hover { text-decoration: underline; text-underline-offset: 3px; }
.gg-pick:focus-visible, .gg-name a:focus-visible { outline: 2px solid var(--teal-dark); outline-offset: 3px; border-radius: 4px; }
/* THE LINE KEY DESCRIBES LINES, and the narrow state draws none, so it goes with them. */
@media (max-width: 1199px) { .gg-key-lines { display: none; } }
.ggp-key-note { margin: var(--s4) 0 0; font-size: 14px; line-height: 1.5; color: var(--ink-lead); }
.ggp-key-ev { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.gg-n-path.is-unread { border-style: dashed; }
.gg-n-unread { margin-top: 8px; font-size: 14px; line-height: 1.35; color: var(--ink-2); }

/* ---- src/parts/gls.css ---- */
/* /glossary. packages/ui/partials/gls-sheet.ejs draws the map and the sheet; the view draws the hero.
 *
 * ONE IDENTITY HUE PER GROUP, and the hue says only which group: parties blue, objects violet, acts
 * green, bounds amber. The evidence labels take no hue and no state colour, because a state word in
 * colour on this page would stand for an artefact the page does not link.
 */
.gls { --gls-hue: var(--teal-dark); display: grid; gap: var(--s8); }
.gls [data-group="parties"] { --gls-hue: var(--d-blue); }
.gls [data-group="objects"] { --gls-hue: var(--d-violet); }
.gls [data-group="acts"] { --gls-hue: var(--d-magenta); }
.gls [data-group="bounds"] { --gls-hue: var(--d-sand); }

.gls-page .gls-hero { position: relative; border-top: 0; padding-block: 3.5rem 0; overflow: hidden; }
.gls-page .gls-hero .wrap { position: relative; z-index: 1; display: grid; gap: var(--s4); }
.gls-page .gls-glow { position: absolute; z-index: 0; top: -80px; left: 20%; max-width: 70%; }
.gls-page .gls-hero .eyebrow { margin: 0; }
.gls-page .gls-hero .t-display { margin: 0; max-width: 24ch; }
.gls-lead { margin: 0; max-width: 60ch; font-size: 17px; line-height: 1.55; color: var(--ink-2); }
.gls-page .gls-band { border-top: 0; padding-block: var(--s7) var(--s8); }

/* THE MAP. Four panels, each lit from above in its group's hue, with the group's terms as pills. */
.gls-map { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s4); }
.gls-map-g {
  --hue: var(--gls-hue);
  display: grid; align-content: start; gap: var(--s4); padding: var(--s4) var(--s5) var(--s5); border-radius: 12px; min-width: 0;
  border: 1px solid color-mix(in srgb, var(--ink) 10%, transparent);
  border-top-color: color-mix(in srgb, var(--gls-hue) 55%, transparent);
  background: linear-gradient(180deg, color-mix(in srgb, var(--gls-hue) 8%, transparent) 0%, transparent 100%);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--gls-hue) 40%, transparent);
}
.gls-map-head { display: flex; align-items: center; gap: var(--s3); }
.gls-map-head .gls-ped { width: 64px; flex: none; }
.gls-map-h { margin: 0; font-size: 14px; font-weight: 600; letter-spacing: 0.22em; text-transform: uppercase; }
.gls-map-h a { color: var(--gls-hue); text-decoration: none; }
.gls-map-h a:hover { text-decoration: underline; }
.gls-map-n { margin: 2px 0 0; font-size: 14px; color: var(--ink-2); }
.gls-pills { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--s2); }
.gls-pill {
  display: inline-flex; align-items: center; min-height: 32px; padding: 0 12px; border-radius: var(--pill);
  border: 1px solid color-mix(in srgb, var(--gls-hue) 35%, transparent);
  color: var(--ink); font-size: 14px; text-decoration: none; white-space: nowrap;
}
.gls-pill:hover { border-color: var(--gls-hue); }

/* THE SHEET. One group at a time, its head in the group's hue, its terms as cards. */
.gls-group { display: grid; gap: var(--s5); scroll-margin-top: 110px; }
.gls-group-head { display: grid; gap: var(--s1); padding-left: var(--s4); border-left: 3px solid var(--gls-hue); }
.gls-group-h { margin: 0; font-size: 28px; line-height: 1.15; font-weight: 700; letter-spacing: -0.02em; color: var(--ink); }
.gls-group-line { margin: 0; font-size: 16px; color: var(--ink-2); }
.gls-group-line a { white-space: nowrap; }
.gls-cards { margin: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s4); }
.gls-cards-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.gls-card {
  display: grid; grid-template-rows: auto 1fr auto; gap: var(--s2); padding: var(--s4) var(--s5); border-radius: 10px; min-width: 0;
  border: 1px solid var(--hairline);
  background: linear-gradient(180deg, color-mix(in srgb, var(--gls-hue) 5%, transparent) 0%, transparent 70%);
  scroll-margin-top: 110px;
}
.gls-card:target { border-color: var(--gls-hue); box-shadow: 0 0 0 1px var(--gls-hue), 0 0 32px color-mix(in srgb, var(--gls-hue) 20%, transparent); }
.gls-term { margin: 0; font-size: 18px; font-weight: 700; color: var(--ink); }
.gls-term::first-letter { text-transform: uppercase; }
.gls-def { margin: 0; font-size: 15px; line-height: 1.55; color: var(--ink-2); overflow-wrap: anywhere; }
.gls-see { margin: 0; padding-top: var(--s2); border-top: 1px solid var(--hairline); font-size: 14px; }
.gls-see a { color: var(--teal-dark); text-decoration: none; }
.gls-see a:hover { text-decoration: underline; }
.gls-see-w { color: var(--ink-2); }
.gls-none { color: var(--ink-2); }
.gls-evidence { --gls-hue: var(--rule); }

@media (max-width: 1100px) {
  .gls-map { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .gls-cards, .gls-cards-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* THE NARROW STATE. The map keeps the pills, so a phone reader still finds a word in one look, and
   the pedestal gives way to a hue bar on the panel's top edge, which is already lit. */
@media (max-width: 640px) {
  .gls-map { grid-template-columns: minmax(0, 1fr); gap: var(--s3); }
  .gls-map-head .gls-ped { display: none; }
  .gls-cards, .gls-cards-4 { grid-template-columns: minmax(0, 1fr); }
  .gls-group-h { font-size: 24px; }
  .gls-pill { white-space: normal; }
}

/* ---- src/parts/gv-page.css ---- */
/* /governance and /governance/evidence.
 *
 * EVERY RULE IN THIS FILE IS SCOPED TO .gv-page, which both views write once around the whole page.
 * Several classes below belong to files other routes share: .gv-card, .gv-panel and .gv-example are
 * gv.css's, .cta and .drawer are the base sheet's, and .bs-panel is blast.css's. A bare rule on any
 * of them would land on a page nobody here opened. The scope also settles the cascade: gv-page.css
 * sorts before gv.css, and one more class wins at equal specificity whatever the order.
 *
 * WHAT IS ON WHICH PAGE, AS OF 29 SEPTEMBER 2026. /governance is the claim: the hero, one
 * instrument (packages/ui/partials/gb-bounds.ejs, styled by gb.css), the outcome row and the close.
 * /governance/evidence is the working: the six stage chain, the accreditation withdrawal figure, the
 * five scope revocation figure, the control surfaces table, the measured bounds and two drawers.
 *
 * THE CLAIM PAGE TAKES ITS SHELL FROM hx.css, /how-it-works, measurement for measurement, so a
 * visitor moving between the two meets one hand.
 *
 * NO TEXT BELOW 14px, NO COLOUR OUTSIDE A TOKEN, AND NO STATE COLOUR AS DECORATION. The only green
 * on either page is the one the evidence cell puts under an Observed mark.
 */

.gv-page { display: grid; --page-max: 1472px; }
/* A grid item's automatic minimum is its content. Nothing on either page may push the single column
   open, so every child may be narrower than its content. */
.gv-page > * { min-width: 0; }

/* ================================================================
   The claim page.
   ================================================================ */

.gv-page .gv-top { position: relative; padding-block: 3.5rem var(--s5); }
.gv-page .gv-top-copy { display: grid; gap: 0; }
.gv-page .gv-top-copy > * { margin: 0; }
.gv-page .gv-top-copy .sc-eyebrow { letter-spacing: 0.22em; color: var(--slate); }
.gv-page .gv-top-copy .sc-headline { margin-top: var(--s4); line-height: 1.02; letter-spacing: -0.035em; max-width: 20ch; }
.gv-page .gv-top-copy .sc-headline .accent { display: block; }
.gv-page .gv-top-copy .sc-lead { margin-top: 1.25rem; max-width: 38rem; font-size: 17px; line-height: 1.55; color: var(--ink-lead); }
.gv-page .gv-top-copy .sc-actions { margin-top: var(--s6); display: flex; flex-wrap: wrap; gap: var(--s4); }
@media (min-width: 1200px) {
  .gv-page .gv-top-copy { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); column-gap: var(--s7, 4rem); grid-template-areas: "eyebrow eyebrow" "head lead" "head actions"; align-items: start; }
  .gv-page .gv-top-copy .sc-eyebrow { grid-area: eyebrow; }
  .gv-page .gv-top-copy .sc-headline { grid-area: head; }
  .gv-page .gv-top-copy .sc-lead { grid-area: lead; }
  .gv-page .gv-top-copy .sc-actions { grid-area: actions; }
}

.gv-page .gv-figure-band { padding-block: var(--s6); border-top: 1px solid var(--hairline); }
.gv-page .gv-figure-ev { margin-top: var(--s5); display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: var(--s3); font-size: 14px; color: var(--ink-2); }

/* The outcome row, the reference's benefits row. */
.gv-page .gv-payoff { padding-block: var(--s6); border-top: 1px solid var(--hairline); border-bottom: 1px solid var(--hairline); }
.gv-page .gv-outcomes { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); }
.gv-page .gv-outcomes li { display: flex; flex-direction: column; align-items: center; text-align: center; padding: 0 var(--s4); }
.gv-page .gv-outcomes li + li { border-left: 1px solid var(--hairline); }
.gv-page .gv-outcome-i { width: 52px; height: 52px; }
.gv-page .gv-outcome-i svg { width: 26px; height: 26px; }
.gv-page .gv-outcome-t { margin: var(--s4) 0 0; font-size: 18px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.gv-page .gv-outcome-l { margin: var(--s2) 0 0; max-width: 19rem; text-wrap: balance; font-size: 15px; line-height: 1.5; color: var(--ink-2); }
@media (max-width: 900px) {
  .gv-page .gv-outcomes { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: var(--s6); }
  .gv-page .gv-outcomes li + li { border-left: 0; }
  .gv-page .gv-outcomes li:nth-child(even) { border-left: 1px solid var(--hairline); }
}
@media (max-width: 480px) {
  .gv-page .gv-outcomes { grid-template-columns: minmax(0, 1fr); }
  .gv-page .gv-outcomes li:nth-child(even) { border-left: 0; }
}

/* ================================================================
   The evidence route: the band rhythm.
   ================================================================ */

.gv-page .gv-band { padding-block: var(--s7) var(--s8); border-top: 1px solid var(--hairline); }
.gv-page .gv-band > .flow > .band-head { margin-bottom: var(--s6); }
.gv-page .gv-lead { max-width: 60ch; font-size: 17px; line-height: 1.55; color: var(--ink-lead); }
.gv-page .gv-lead p { margin: 0; }

/* ================================================================
   The evidence route: the head.
   ================================================================ */

.gv-page .gve-head { padding-block: var(--s7) var(--s6); display: grid; gap: var(--s4); }
.gv-page .gve-head > * { margin: 0; }
.gv-page .gve-head .eyebrow { letter-spacing: 0.24em; }
.gv-page .gve-head .t-display { max-width: 24ch; }
.gv-page .gve-back { font-size: var(--t-small); }

/* ================================================================
   The chain, as the target states a card. Evidence route only.
   ================================================================ */

/* A stage card takes the target's card: a 14px radius, a stroke at low contrast, the card ground one
   step above the band, and the accent on hover. The left edge stays 3px, because it is what gv.css
   uses to mark the selected stage and the outcome stage, and both meanings survive. */
.gv-page .gv-chain .gv-card {
  padding: var(--s4) var(--s5);
  border-radius: var(--r-3);
  border-color: color-mix(in srgb, var(--rule) 45%, transparent);
  border-left-color: color-mix(in srgb, var(--rule) 45%, transparent);
}
.gv-page .gv-chain .gv-card:hover { border-color: var(--teal-mid); }

/* The number is the card's mono label, set in the quiet ink, uppercase, and tracked wider than
   anything else on the card. The quiet ink is a plain token here rather than a mix of one, because
   it is text and contrast.mjs gates a token pair by name. */
.gv-page .gv-chain .gv-card-n {
  font-size: var(--t-label);
  letter-spacing: 0.18em;
  color: var(--ink-2);
}
.gv-page .gv-chain .gv-card-name {
  font-family: var(--display);
  font-size: var(--t-h3);
  line-height: var(--t-h3-line);
}

/* The connector between two cards is the one place the chain is not a card grid, and it is the
   reason this is a chain rather than six tiles. */
.gv-page .gv-chain .gv-link {
  background-image: linear-gradient(color-mix(in srgb, var(--rule) 45%, transparent), color-mix(in srgb, var(--rule) 45%, transparent));
}
.gv-page .gv-chain .gv-link::after {
  border-right-color: color-mix(in srgb, var(--rule) 45%, transparent);
  border-bottom-color: color-mix(in srgb, var(--rule) 45%, transparent);
}

/* The panel beside the chain is the largest card on the page, so it gets the corner light the target
   puts on a card: one soft radial bloom off the top right, drawn in the graphic fill. It is a
   background image rather than a pseudo element, because the panel is a grid and a pseudo element
   would take a cell of its own. */
.gv-page .gv-chain .gv-panel {
  position: relative;
  padding: var(--s6);
  border-radius: var(--r-3);
  border-color: color-mix(in srgb, var(--rule) 45%, transparent);
  background-image: radial-gradient(28rem 18rem at 100% 0%, color-mix(in srgb, var(--teal-mid) 12%, transparent), transparent 70%);
}
.gv-page .gv-chain .gv-panel-eyebrow { font-family: var(--mono); letter-spacing: 0.18em; }
.gv-page .gv-chain .gv-panel-head { font-family: var(--display); }

/* The worked example is a card inside a card, so it takes the band ground rather than a third one. */
.gv-page .gv-chain .gv-example {
  padding: var(--s5);
  border-radius: var(--r-3);
  border-color: color-mix(in srgb, var(--rule) 45%, transparent);
  background: var(--paper-alt);
}
.gv-page .gv-chain .gv-example-head { letter-spacing: 0.14em; }

/* The three ceilings are three cards in a row and read as the target's card grid. */
.gv-page .gv-ceiling {
  padding: var(--s4);
  border-radius: var(--r-3);
  border-color: color-mix(in srgb, var(--rule) 45%, transparent);
  background: var(--white);
}
.gv-page .gv-ceilings-head { letter-spacing: 0.14em; }

@media (max-width: 900px) {
  .gv-page .gv-chain .gv-panel { padding: var(--s5) var(--s4); }
}

/* ================================================================
   The revocation band. Evidence route only.
   ================================================================ */

/* The figure and the scope panel beside it take the same radius and the same stroke as everything
   else on the page. blast.css draws both, and the scope keeps these rules off any page that
   renders the figure later. */
.gv-page .bs-frame,
.gv-page .bs-panel {
  border-radius: var(--r-3);
  border-color: color-mix(in srgb, var(--rule) 45%, transparent);
}
.gv-page .bs-panel { padding: var(--s5); }
.gv-page .bs-rail-head { letter-spacing: 0.14em; }

/* ================================================================
   The evidence drawers, as panels. Evidence route only.
   ================================================================ */

/* Four hairlines across the page width read as a table of contents. As four panels they read as four
   things a reader may open, which is what they are. */
.gv-page .gv-drawers { display: grid; gap: var(--s3); }
.gv-page .gv-drawers > .drawer {
  padding: var(--s2) var(--s5);
  background: var(--white);
  border: 1px solid color-mix(in srgb, var(--rule) 45%, transparent);
  border-radius: var(--r-3);
  transition: border-color var(--m-drawer) ease;
}
.gv-page .gv-drawers > .drawer:hover { border-color: var(--teal-mid); }
.gv-page .gv-drawers > .drawer + .drawer { border-top: 1px solid color-mix(in srgb, var(--rule) 45%, transparent); }
.gv-page .gv-drawers > .drawer > summary { font-family: var(--display); }
.gv-page .gv-drawers > .drawer[open] > summary { border-bottom: 1px solid color-mix(in srgb, var(--rule) 45%, transparent); }
.gv-page .gv-drawers > .drawer > .body { padding-top: var(--s4); }

@media (max-width: 700px) {
  .gv-page .gv-drawers > .drawer { padding-inline: var(--s4); }
}

/* The drawer in the revocation band is one of a kind, so it stays a rule rather than becoming a
   panel with nothing beside it to line up with. */
.gv-page .gv-blast-band > .flow > .drawer { border-bottom: 0; }

@media (prefers-reduced-motion: reduce) {
  .gv-page .gv-drawers > .drawer { transition: none; }
}


/* ---- src/parts/gv.css ---- */
/* The governance chain and the three ceilings. Partials: packages/ui/partials/gv-chain.ejs and
   packages/ui/partials/gv-ceilings.ejs. Page: /governance.

   WHAT THE LAYOUT HAS TO SAY. Governance is a series of bounded decisions, so the chain is a column
   a reader walks downward, each stage handing a narrower bound to the next, and the consequence of
   the selected stage sits beside it rather than under it. A reader who never clicks still reads the
   six stage names and the first panel, which is the ten second reading; a reader who clicks gets
   five more without leaving the band.

   NO BRAND COLOUR ON A STAGE CARD. Nothing in this chain is a Raidiam product: a publisher, an
   organisation, an agent, an accreditation and a runtime all belong to somebody else, and the
   granted ceiling belongs to the customer's platform. The selected card takes the teal WASH, which
   is the ground the stage rail already uses for the current stage, and the action colour on its
   border and its left edge. Filling one teal would have said the stage is Raidiam's.

   THE LAST STAGE IS THE OUTCOME AND IT READS DIFFERENTLY. It is the only card with no card below
   it and the only one that states what a platform allows rather than what somebody governs, so it
   carries a rule above it instead of a connector and its own marker colour. That is the one place
   the reference sheet uses a second hue, and it uses it for the same node.

   THE PAIRS ARE POSITIONAL, as in blast.css and ch.css: the nth radio marks the nth card and shows
   the nth panel, and nothing here names a stage id. Eight pairs are written out, which is the most
   stages gv-chain.ejs accepts. */

.gv-chain {
  margin: var(--s5) 0 0;
  min-width: 0;
}

.gv-chain .gv-grid {
  display: grid;
  grid-template-columns: minmax(0, 300px) minmax(0, 1fr);
  gap: var(--s5);
  align-items: start;
}

/* ---- the chain ---- */

.gv-chain .gv-stages {
  display: grid;
  gap: 0;
  margin: 0;
  padding: 0;
  list-style: none;
  align-content: start;
}

.gv-chain .gv-step { display: grid; justify-items: stretch; }

.gv-chain .gv-card {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: var(--s3);
  row-gap: 2px;
  padding: var(--s3) var(--s4);
  background: var(--white);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--rule);
  border-radius: var(--r-2);
  cursor: pointer;
  transition: border-color var(--m-drawer) ease, background-color var(--m-drawer) ease;
}
.gv-chain .gv-card:hover { border-color: var(--teal-dark); }
.gv-chain .gv-card-n {
  grid-row: 1 / span 2;
  align-self: center;
  font-family: var(--mono);
  font-size: var(--t-label);
  color: var(--ink-2);
}
.gv-chain .gv-card-name { font-size: var(--t-body); font-weight: 600; color: var(--ink); }
.gv-chain .gv-card-sub { grid-column: 2; font-size: var(--t-label); color: var(--ink-2); }

/* The connector. A short vertical rule with an arrow head, drawn in the border colour so it reads
   as one continuous chain rather than six cards that happen to be stacked. */
.gv-chain .gv-link {
  justify-self: start;
  width: 3px;
  height: var(--s5);
  margin-left: 26px;
  background:
    linear-gradient(var(--rule), var(--rule)) no-repeat 0 0 / 1px 100%;
  position: relative;
}
.gv-chain .gv-link::after {
  content: "";
  position: absolute;
  left: -2px;
  bottom: 2px;
  width: 5px;
  height: 5px;
  border-right: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  transform: rotate(45deg);
}

/* The outcome card. The last stage states what a platform allows, so it takes the proven marker
   colour on its edge and a slightly lifted ground. It is not green: --ok is the state colour the
   system already carries for admitted and active, and this card states neither a claim nor an
   observation, so nothing inside it wears a mark. */
.gv-chain .gv-step:last-child .gv-card {
  border-left-color: var(--teal-mid);
  background: var(--paper-alt);
}

/* ---- the panel ---- */

.gv-chain .gv-panels { display: grid; min-width: 0; }

.gv-chain .gv-panel {
  grid-area: 1 / 1;
  align-content: start;
  display: grid;
  gap: var(--s3);
  min-width: 0;
  padding: var(--s5);
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
  visibility: hidden;
  opacity: 0;
  transition: opacity var(--m-drawer) ease;
}

.gv-chain .gv-panel-eyebrow {
  margin: 0;
  font-size: var(--t-label);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.gv-chain .gv-panel-head { margin: 0; }
.gv-chain .gv-panel-line { margin: 0; font-size: var(--t-body); color: var(--ink); max-width: var(--measure-body); }
.gv-chain .gv-panel-note { margin: 0; font-size: var(--t-small); color: var(--ink-2); max-width: var(--measure-notes); }

.gv-chain .gv-controls { display: grid; gap: var(--s2); margin: var(--s1) 0 0; padding: 0; list-style: none; }
.gv-chain .gv-control {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--s3);
  align-items: baseline;
  font-size: var(--t-small);
  color: var(--ink);
}
/* The marker is a rule, not a tick. A tick in this system means a proven state and green means
   Observed, and what a reader controls is neither. */
.gv-chain .gv-control-mark {
  width: 10px;
  height: 1px;
  margin-top: 0.6em;
  background: var(--teal-mid);
}

.gv-chain .gv-example {
  margin: var(--s2) 0 0;
  padding: var(--s4);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--r-2);
}
.gv-chain .gv-example-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s3);
  margin: 0 0 var(--s3);
  font-size: var(--t-label);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.gv-chain .gv-example-head .ev { margin-left: auto; text-transform: none; letter-spacing: normal; }

.gv-chain .gv-rows { display: grid; gap: var(--s3); margin: 0; }
.gv-chain .gv-row { display: grid; grid-template-columns: minmax(0, 12em) minmax(0, 1fr); gap: var(--s2) var(--s4); }
.gv-chain .gv-rows dt { font-size: var(--t-label); letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-2); }
.gv-chain .gv-rows dd { margin: 0; font-size: var(--t-small); color: var(--ink); overflow-wrap: anywhere; }
.gv-chain .gv-rows dd.mono { font-family: var(--mono); font-size: var(--t-label); line-height: 1.6; }

/* ---- the three ceilings ---- */

.gv-ceilings { margin: var(--s4) 0 0; }
.gv-ceilings-head {
  margin: 0 0 var(--s3);
  font-size: var(--t-label);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.gv-ceiling-cols {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s4);
  margin: 0;
  padding: 0;
  list-style: none;
}
.gv-ceiling {
  display: grid;
  align-content: start;
  gap: var(--s2);
  padding: var(--s3);
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--r-2);
}
.gv-ceiling-name { margin: 0; font-size: var(--t-small); font-weight: 600; color: var(--ink); }
.gv-ceiling-line { margin: 0; font-size: var(--t-label); color: var(--ink-2); }
.gv-ceiling-types { display: grid; gap: 6px; margin: var(--s1) 0 0; padding: 0; list-style: none; }
.gv-ceiling-type { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); }
.gv-ceiling-type code { font-family: var(--mono); font-size: var(--t-label); color: var(--ink); overflow-wrap: anywhere; }
.gv-ceiling-type.is-dropped code { color: var(--ink-2); text-decoration: line-through; }
.gv-ceiling-foot { margin: var(--s2) 0 0; font-size: var(--t-label); color: var(--ink-2); }

/* ---- what the radio group drives, written out rather than generated ----

   Eight inputs, and each one shows its own panel and marks its own card. The shape is
   packages/ui/src/parts/blast.css's, and its comment carries the reason the state lives on the
   element rather than in a script. */

.gv-chain > .gv-in:nth-of-type(1):checked ~ .gv-grid .gv-panel:nth-of-type(1),
.gv-chain > .gv-in:nth-of-type(2):checked ~ .gv-grid .gv-panel:nth-of-type(2),
.gv-chain > .gv-in:nth-of-type(3):checked ~ .gv-grid .gv-panel:nth-of-type(3),
.gv-chain > .gv-in:nth-of-type(4):checked ~ .gv-grid .gv-panel:nth-of-type(4),
.gv-chain > .gv-in:nth-of-type(5):checked ~ .gv-grid .gv-panel:nth-of-type(5),
.gv-chain > .gv-in:nth-of-type(6):checked ~ .gv-grid .gv-panel:nth-of-type(6),
.gv-chain > .gv-in:nth-of-type(7):checked ~ .gv-grid .gv-panel:nth-of-type(7),
.gv-chain > .gv-in:nth-of-type(8):checked ~ .gv-grid .gv-panel:nth-of-type(8) { visibility: visible; opacity: 1; }

.gv-chain > .gv-in:nth-of-type(1):checked ~ .gv-grid .gv-step:nth-of-type(1) .gv-card,
.gv-chain > .gv-in:nth-of-type(2):checked ~ .gv-grid .gv-step:nth-of-type(2) .gv-card,
.gv-chain > .gv-in:nth-of-type(3):checked ~ .gv-grid .gv-step:nth-of-type(3) .gv-card,
.gv-chain > .gv-in:nth-of-type(4):checked ~ .gv-grid .gv-step:nth-of-type(4) .gv-card,
.gv-chain > .gv-in:nth-of-type(5):checked ~ .gv-grid .gv-step:nth-of-type(5) .gv-card,
.gv-chain > .gv-in:nth-of-type(6):checked ~ .gv-grid .gv-step:nth-of-type(6) .gv-card,
.gv-chain > .gv-in:nth-of-type(7):checked ~ .gv-grid .gv-step:nth-of-type(7) .gv-card,
.gv-chain > .gv-in:nth-of-type(8):checked ~ .gv-grid .gv-step:nth-of-type(8) .gv-card {
  border-color: var(--teal-dark);
  border-left-color: var(--teal-deep);
  background: var(--wash-teal);
}

/* The focus ring follows the radio to the card it marks, because the radio itself is visually
   hidden and a keyboard reader would otherwise walk the group with nothing on screen moving. */
.gv-chain > .gv-in:nth-of-type(1):focus-visible ~ .gv-grid .gv-step:nth-of-type(1) .gv-card,
.gv-chain > .gv-in:nth-of-type(2):focus-visible ~ .gv-grid .gv-step:nth-of-type(2) .gv-card,
.gv-chain > .gv-in:nth-of-type(3):focus-visible ~ .gv-grid .gv-step:nth-of-type(3) .gv-card,
.gv-chain > .gv-in:nth-of-type(4):focus-visible ~ .gv-grid .gv-step:nth-of-type(4) .gv-card,
.gv-chain > .gv-in:nth-of-type(5):focus-visible ~ .gv-grid .gv-step:nth-of-type(5) .gv-card,
.gv-chain > .gv-in:nth-of-type(6):focus-visible ~ .gv-grid .gv-step:nth-of-type(6) .gv-card,
.gv-chain > .gv-in:nth-of-type(7):focus-visible ~ .gv-grid .gv-step:nth-of-type(7) .gv-card,
.gv-chain > .gv-in:nth-of-type(8):focus-visible ~ .gv-grid .gv-step:nth-of-type(8) .gv-card {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

@media (max-width: 900px) {
  .gv-chain .gv-grid { grid-template-columns: minmax(0, 1fr); }
  .gv-ceiling-cols { grid-template-columns: minmax(0, 1fr); }
  .gv-chain .gv-row { grid-template-columns: minmax(0, 1fr); }
}

@media (prefers-reduced-motion: reduce) {
  .gv-chain .gv-panel, .gv-chain .gv-card { transition: none; }
}

/* ---- src/parts/hiw.css ---- */
/*
 * /how-it-works and /how-it-works/evidence.
 *
 * WHAT IS IN THIS FILE, AND IN WHICH ORDER.
 *   `hf-`  packages/ui/partials/hiw-flow.ejs, the five box rail. THE SITE DRAWS IT ON NO ROUTE any
 *          more: /how-it-works was rebuilt on the target's own treatments and no other page ever
 *          called it. The rules stay because the partial and its gallery example still exist, and
 *          deleting them would leave the gallery entry drawing an unstyled rail. Delete all three
 *          together or none of them.
 *   `hw-`  apps/site/src/views/platform-needs.ejs. The hero, the instrument and the four outcomes.
 *   `hp-`  the three specification cards, and `hc-` the before and after strip. Both were on the
 *          claim page and both now draw on apps/site/src/views/platform-needs-evidence.ejs.
 *
 * WHAT THIS FILE REFUSES TO DRAW, and each of these had rules here until 16 September 2026:
 *   the hero verification panel  `hh-`, a second drawing of the three checks beside the first
 *   the claim panel              `hs-`, Ralph's sentence in a box with a legend beside it
 *   the drawer bar               `hu-`, the header over six disclosures that no longer exist
 *   the closing globe band       `hk-`, a photograph beside a question that needs no picture
 * They went with the markup that carried them. A rule with no element is a rule nobody can correct.
 *
 * COLOUR IS A TOKEN DECISION AND THIS FILE MAKES NONE. An earlier version of this comment recorded
 * colours read off docs/redesign/refs4/how-it-works-target.png and set them beside the site's dark
 * tokens. Those token values have since moved to the target build's palette, so the comparison it
 * printed is no longer true and it is removed rather than restated. Every colour below is a token
 * name. packages/ui/tokens/tokens.json holds the values and the reason for each one.
 *
 * SPACING, TYPE SIZE, RADIUS AND STROKE WEIGHT COME FROM THE SYSTEM'S OWN SCALE, never from a
 * measurement of a render. A png at 1536 wide does not keep that detail.
 *
 * THE RAIL IS A GRID, NOT FLEX, and the arrows are grid items. The five boxes have to line up on
 * their top edge and share a baseline for the verb, and a flex row with `align-items: stretch`
 * distributes spare height inside each card instead, which puts one heading below its neighbours.
 * The same defect was measured on the scenario card row at 886 against 879.
 */

.hf { container-type: inline-size; }

.hf-rail {
  display: grid;
  grid-template-columns: 1.05fr auto 1fr auto 1fr auto 1fr auto 1.05fr;
  align-items: stretch;
  gap: 0;
}

.hf-end,
.hf-step {
  display: grid;
  align-content: start;
  gap: var(--s2);
  padding: var(--s4) var(--s3) var(--s3);
  border: 1px solid var(--rule);
  border-radius: var(--r-2);
  background: var(--white);
  min-width: 0;
}

/* The two ends are the parties, the three middles are the checks. A different ground says so without
   a label, and the step keeps the stronger one because it is where the mechanism is. */
.hf-end { background: var(--paper-alt); }

.hf-step { position: relative; padding-top: var(--s5); }

.hf-n {
  position: absolute;
  top: calc(var(--s5) * -1);
  left: 50%;
  transform: translateX(-50%);
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--teal-dark);
  background: var(--paper);
  color: var(--teal-dark);
  font: var(--t-h3-weight) var(--t-h3) / 1 var(--sans);
  box-shadow: 0 0 0 6px var(--wash-teal);
}

.hf-end-i,
.hf-row-i,
.hf-hop-i {
  display: inline-grid;
  place-items: center;
  color: var(--teal-dark);
}

.hf-end-i { width: 46px; height: 46px; justify-self: center; }
.hf-end-i svg { width: 100%; height: 100%; }
.hf-row-i svg,
.hf-hop-i svg { width: 18px; height: 18px; }

.hf-end-name {
  margin: var(--s2) 0 0;
  text-align: center;
  font: var(--t-h3-weight) var(--t-h3) / var(--t-h3-line) var(--sans);
  color: var(--ink);
}

.hf-end-line,
.hf-does {
  margin: 0;
  text-align: center;
  font-size: var(--t-small);
  color: var(--ink-2);
}

.hf-verb {
  margin: 0;
  text-align: center;
  font: var(--t-h3-weight) var(--t-h3) / var(--t-h3-line) var(--sans);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink);
}

.hf-rows { list-style: none; margin: var(--s3) 0 0; padding: 0; display: grid; gap: 6px; }

.hf-rows li {
  display: grid;
  grid-template-columns: 18px 1fr;
  align-items: center;
  gap: var(--s2);
  padding: 7px 10px;
  border: 1px solid var(--rule);
  border-radius: var(--r-1);
  background: var(--white);
  font-size: var(--t-small);
  color: var(--ink);
}

/* The arrows. A grid item rather than a pseudo element on the card, so the rail's own gap does not
   have to be faked and the arrow can shrink at a narrow container without the cards moving. */
.hf-arrow {
  align-self: center;
  width: 40px;
  height: 2px;
  margin: 0 8px;
  border-radius: 2px;
  background: var(--teal-dark);
  position: relative;
}

.hf-arrow::after {
  content: "";
  position: absolute;
  right: 0;
  top: 50%;
  width: 8px;
  height: 8px;
  border-top: 2px solid var(--teal-dark);
  border-right: 2px solid var(--teal-dark);
  transform: translateY(-50%) rotate(45deg);
}

/* Step one. Statements stacked with a connector down the left, landing on the anchor, because the
   walk runs upward from the leaf and ends at a key the platform already holds. */
.hf-chain { display: grid; gap: 6px; margin-top: var(--s3); position: relative; }

.hf-hop {
  display: grid;
  grid-template-columns: 18px 1fr auto;
  align-items: center;
  gap: var(--s2);
  padding: 7px 10px;
  border: 1px solid var(--rule);
  border-radius: var(--r-1);
  background: var(--white);
  font-size: var(--t-small);
  color: var(--ink-2);
}

.hf-hop-name { min-width: 0; }

.hf-hop-ok {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1px solid var(--teal-dark);
  background: transparent;
}

.hf-anchor {
  display: grid;
  grid-template-columns: 18px 1fr;
  align-items: center;
  gap: var(--s2);
  margin-top: 4px;
  padding: 10px var(--s3);
  border: 1px solid var(--teal-dark);
  border-radius: var(--r-1);
  background: var(--wash-teal);
}

.hf-anchor-name { display: block; font-size: var(--t-small); font-weight: 600; color: var(--ink); }
.hf-anchor-note { display: block; font-size: var(--t-small); color: var(--ink-2); }

/* Step two. The one green on the page, and it is a lifecycle state rather than an evidence mark: see
   the partial's header for why that distinction is load bearing here. */
.hf-acc { display: grid; gap: var(--s3); margin-top: var(--s3); justify-items: center; }

.hf-acc .state {
  display: inline-grid;
  grid-auto-flow: column;
  align-items: center;
  gap: var(--s2);
  margin: 0;
  padding: 10px var(--s4);
  border-radius: var(--r-1);
}

.hf-acc-tick {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  display: inline-block;
  background: transparent;
  border: 1px solid currentColor;
  position: relative;
}

.hf-acc-tick::after {
  content: "";
  position: absolute;
  left: 6px;
  top: 4px;
  width: 5px;
  height: 9px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(42deg);
}

.hf-rows-acc { width: 100%; }

/* Step three. The derived client, printed as the shape it has rather than described. */
.hf-derived { display: grid; gap: var(--s3); margin-top: var(--s3); }

.hf-conf {
  margin: 0;
  padding: var(--s3);
  border: 1px solid var(--rule);
  border-radius: var(--r-1);
  background: var(--paper);
  font: 400 var(--t-small)/1.7 var(--mono);
  overflow-x: auto;
}

.hf-conf code { display: grid; grid-template-columns: auto 1fr; column-gap: var(--s3); }
.hf-conf-k { color: var(--teal-dark); }
.hf-conf-v { color: var(--ink-2); }

/*
 * THE ONE ANIMATION, AND IT IS THE FLOW ONLY. The chain hops light in order and the arrows draw,
 * once, on entry. Nothing loops and nothing moves after that: a figure that keeps moving while
 * somebody reads the text beside it is a figure they close the tab on.
 */
@media (prefers-reduced-motion: no-preference) {
  .hf-rail > * { animation: hf-in .5s ease-out both; }
  .hf-rail > *:nth-child(1) { animation-delay: 0ms; }
  .hf-rail > *:nth-child(3) { animation-delay: 110ms; }
  .hf-rail > *:nth-child(5) { animation-delay: 220ms; }
  .hf-rail > *:nth-child(7) { animation-delay: 330ms; }
  .hf-rail > *:nth-child(9) { animation-delay: 440ms; }
  .hf-arrow { animation-delay: 80ms; }
  .hf-chain .hf-hop { animation: hf-lit .45s ease-out both; }
  .hf-chain .hf-hop:nth-child(1) { animation-delay: 260ms; }
  .hf-chain .hf-hop:nth-child(2) { animation-delay: 360ms; }
  .hf-chain .hf-hop:nth-child(3) { animation-delay: 460ms; }
}

@keyframes hf-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes hf-lit { from { opacity: .35; } to { opacity: 1; } }

/* The claim used to be a centred line under this figure, `.hf-claim`. It is now the band below,
   `.hs-panel`, for the reason recorded beside the markup: as a line under the drawing it read as a
   caption on the drawing rather than as the page's proposition. */

/*
 * THE FLOW BECOMES A COLUMN AT A NARROW CONTAINER, and the arrows turn with it. A container query
 * rather than a media query because the figure is drawn in two places at two widths, and the
 * viewport says nothing about which.
 */
@container (max-width: 1080px) {
  .hf-rail { grid-template-columns: 1fr; gap: var(--s3); }
  .hf-arrow { width: 2px; height: 26px; justify-self: center; margin: 0; background: var(--teal-dark); }
  .hf-arrow::after { right: 50%; top: auto; bottom: 0; transform: translateX(50%) rotate(135deg); }
  .hf-step { padding-top: var(--s6); }
}



/* ==========================================================================
   /how-it-works: THE WIDE PAGE
   ==========================================================================

   WHAT THIS DRAWS. apps/site/src/views/platform-needs.ejs and the hero figure
   packages/ui/partials/hw-boundary.ejs.

   IT WAS 1036 AND CENTRED UNTIL 16 SEPTEMBER 2026. The reference build's how it works page sets
   max-w-[1100px] px-8, which is a 1036 measure, and this page took that number. Ralph put the route
   beside its neighbours: "they are narrow whereas the other pages are wide so you're losing a lot of
   visual depth". CLAUDE.md already held the rule the narrow version broke, that the proportion is
   what gets copied and not the pixel. /architecture, / and /use-cases/same-software all run at 1376.

   WHAT THE WIDTH BUYS, MEASURED RATHER THAN ASSUMED.
     the five steps go across the band instead of down a column, so the whole band width is left for
     the open step. The column ran 420px beside a 1249px panel, and 800px of it was ground.
     the signed artefact moves from a 285px box that scrolled sideways to a column that holds the
     widest line of the entity configuration, 78 characters, without scrolling at all.
     the hero takes the copy on the left and the figure on the right, which is the shape /architecture
     and /why open with.

   THE FOUR IDENTITY HUES ARE THE DESIGN HERE, AND THEY ARE NOT STATE COLOURS. --d-blue, --d-violet,
   --d-magenta and --d-sand mean nothing on their own, which is what lets them separate four kinds of
   thing without spending a meaning the rest of the site relies on. Green means Observed, amber means
   in progress and red means refused, so none of those three answers "which one is this". A hue
   arrives on an element as --hue and is set BY POSITION in this file, so no content file names a
   colour and no label is tied to one. The route drew none of them before today.

   WHICH POSITION TAKES WHICH HUE.
     the five steps    sand on the agent, blue on Verify, violet on Prove, magenta on Authorise, and
                       the brand on your platform, which is the one object the reader already owns
     the four plates   blue, violet, magenta, sand, in the order Raidiam Connect publishes them
     the four outcomes the same four, in the order the content declares them

   WHERE EVERY NUMBER BELOW CAME FROM. The reference's Tailwind classes, converted at 4px a unit:
   pt-14 is 56px, gap-6 is 24px, px-5 is 20px, py-2.5 is 10px. Each rule names the class it came
   from, so the next person can check a value against the source in one step. The numbers that have
   no reference are the ones the width changed, and each of those names what was measured.

   THE GROUNDS ARE THE SAME COLOURS. This site's dark tokens were built from the reference build, so
   --paper is #030910, --paper-alt is #05101d, --white is #081524, --ink is #eaf2ff, --ink-2 is
   #8ea3bd and --teal-dark is the brand cyan #22d3ee. Each rule below names the reference's Tailwind
   colour and takes the token that already holds that value, so nothing here is a match by eye.

   THE ONE COLOUR THAT IS NOT A MATCH IS THE HAIRLINE, AND IT IS MEASURED. The reference's
   `border-line` is rgba(120, 170, 210, 0.14). Over the card ground that composites to #172A3C and
   over the page ground to #131F2B. --rule is #4d6a89, which is four times brighter, and --hairline
   is #18293a, which is the composite. So a decorative divider takes --hairline and a card edge takes
   a mix of --ink at 10 percent, which is what rw.css already uses for the same edge in the same
   reference. A mix is allowed in a border; packages/ui/tools/contrast.mjs gates token PAIRS BY NAME
   and cannot see a mix, so a mix never goes under text.

   var(--teal) APPEARS IN NO SELECTOR HERE. It is reserved for a Raidiam product marker and
   packages/ui/tests/stylesheet.test.ts reads the selector to decide. var(--ok) appears in no
   selector either: the same test allows it only under .state[data-state="ok"] and two other
   selectors, so the one green on this page is drawn by the base sheet's state chip.

   14px IS THE FLOOR. The reference sets 13px on its eyebrow, its step subtitles, its code block and
   its result notes. Every one of those is --t-label, which is 14px. It is a readability rule rather
   than a style choice, and the stylesheet test enforces it.

   WHAT IS NO LONGER HERE.
     the pill row      `.hw-tabs`. It selected the same five steps the step strip selects. Two
                       controls for one choice is a second thing to read and nothing to learn
     the panel pair    `.hw-panel*`. The two boundary lists are the hero figure now, drawn by
                       hw-boundary.ejs, and the words did not change
     the action row    `.hw-actions` under the outcomes. The pair moved into the hero
     the hub, the wire layer, the pedestals and the ambient glow of the figure this replaced.
     rw.css still declares those for the pages that draw them
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   0. The page box
   --------------------------------------------------------------------------

   1376, which is one of the three measures the redesign tracker allows and the one its wide pages
   take. `.wrap` reads --page-max on the element it is set on, so this widens the page without
   restating the width expression and without a second class fighting the first. */
.hw-page { --page-max: 1376px; }

/* THE FAINT EDGE, DECLARED ONCE. Every card, panel and block on this page carries the reference's
   `border-line`, so the mix is named here and read by each of them. */
.hw-page { --hw-edge: color-mix(in srgb, var(--ink) 10%, transparent); }

/* --------------------------------------------------------------------------
   1. The hero: copy on the left, the boundary figure on the right
   -------------------------------------------------------------------------- */

/* pt-14. One column until the copy and the figure both have room, two columns over it. 1180 is the
   width at which a 460px copy column and a 620px figure both fit inside the 1376 measure with the
   48px gap between them; under it the figure would be squeezed under 560 and its plates would take
   three lines each. The copy column was 460 and the headline set in five lines against a three line
   lead, which is a column narrower than the sentence it holds. */
.hw-hero {
  padding-top: 56px;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s7);
  align-items: center;
}
@media (min-width: 1180px) {
  .hw-hero { grid-template-columns: minmax(0, 520px) minmax(0, 1fr); gap: 48px; }
}

.hw-hero-copy { display: grid; align-content: start; }

/* 13px at the floor, weight 600, uppercase, tracking 0.28em, on the reference's #8ea3bd. The site's
   own `.eyebrow` sets a different tracking and the brand colour, so the reference's values are named
   here rather than the class being reused and then half overridden. */
.hw-eyebrow {
  margin: 0;
  font-size: var(--t-label);
  font-weight: 600;
  line-height: var(--t-label-line);
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--ink-2);
}

/* mt-4, 56px, bold, leading 1.05, tracking -0.03em, balanced. --t-display is
   clamp(38px, 4.4vw, 54px) on 1.02 and -0.035em, which is the reference build's own display setting
   and two pixels under this page's 56. The token is what every other page's statement takes, so it
   is not overridden for two pixels, and 54 is the size the tracker holds every route to but home.

   THE MEASURE IS THE COLUMN NOW. It was `max-w-[820px]` centred, and the copy column is 460 wide, so
   the headline sets in three lines against the figure. `.t-display` carries the system's 24ch
   measure, which is wider than the column and therefore does nothing here. */
.hw-headline { margin: var(--s4) 0 0; text-wrap: balance; }
/* The accent is a substring of the statement and stays inline: the reference breaks its headline on
   the measure rather than on the accent. */
.hw-headline .accent { color: var(--teal-dark); }

/* mt-5, 17px on 1.6. --t-body is 17px on 1.55.

   THE COLOUR IS --ink-lead AND IT USED TO BE --ink-2. The reference sets #aebdd2 on this paragraph,
   one step brighter than its muted text, and this system had no token at that value until 16
   September 2026. It has one now: --ink-lead is that exact colour. Measured before the change, this
   lead was #8ea3bd, which is the reference's CAPTION colour, so the sentence under the headline read
   as a note about the headline. */
.hw-lead {
  margin: 20px 0 0;
  font-size: var(--t-body);
  line-height: 1.6;
  color: var(--ink-lead);
}

/* THE PAIR OF ACTIONS, SIDE BY SIDE AND NOT STACKED. CLAUDE.md names the reason: ours stacked
   because the copy column was 373px against the target's 500, so the column is 460 and the pair is
   one gesture. `.actions` is the base sheet's row. */
.hw-hero-actions { margin-top: var(--s6); }

/* The figure keeps its drawn size rather than stretching: its connectors are drawn at the plate
   geometry and a stretched figure is a figure whose arrows point at the wrong rows. */
.hw-hero-fig { min-width: 0; }

/* --------------------------------------------------------------------------
   1a. The hero figure, packages/ui/partials/hw-boundary.ejs
   --------------------------------------------------------------------------

   Four signed statements, a boundary, and the platform that reads them. The three columns are the
   two groups and the crossing between them. The middle column is the svg's own width, 168, so the
   beziers are never scaled and a stroke keeps its weight. 168 is 40px wider than the boundary label
   above it: at 136 the label was the full width of its column and read as one phrase with the group
   title beside it, "THE BOUNDARY STAYS IN YOUR ESTATE". */
.hwb {
  position: relative;
  margin: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 168px minmax(0, 1.02fr);
  align-items: start;
}

/* THE AMBIENT GLOW. A very large, very soft ellipse behind the figure, which is what stops the
   ground reading flat. It is decoration and sits under everything. */
.hwb-glow {
  position: absolute;
  left: 8%;
  top: 50%;
  width: 84%;
  height: 150%;
  transform: translateY(-50%);
  border-radius: 50%;
  background: radial-gradient(ellipse at center, color-mix(in srgb, var(--teal-dark) 16%, transparent), transparent 68%);
  filter: blur(46px);
  pointer-events: none;
  z-index: 0;
}
.hwb > *:not(.hwb-glow) { position: relative; z-index: 1; }

/* The group titles. Uppercase and tracked, which is the side panel title treatment CLAUDE.md names.
   The tracking is 0.12em rather than the 0.22em of a side panel: at 0.22em the longer of the two
   titles takes two lines in a 370px column, and the svg below it is aligned to a one line title. */
.hwb-h {
  margin: 0 0 var(--s3);
  font-size: var(--t-label);
  font-weight: 600;
  line-height: var(--t-label-line);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--teal-dark);
  white-space: nowrap;
}
.hwb-h-est { color: var(--ink-2); }

/* THE PLATES. A plate is 62 tall on a 12 gap, and the partial draws its connectors from those two
   numbers, so neither may change here alone. */
.hwb-plates { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.hwb-plate {
  height: 62px;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: var(--s3);
  padding: 0 var(--s4);
  border: 1px solid var(--hw-edge);
  /* The hue lands on one edge, which is where a reader picks up the wire that leaves it. */
  border-left: 3px solid var(--hue, var(--teal-dark));
  border-radius: 10px;
  background: linear-gradient(180deg, var(--white), var(--paper-alt));
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--hue, var(--teal-dark)) 26%, transparent);
}
.hwb-plates > .hwb-plate:nth-child(4n + 1) { --hue: var(--d-blue); }
.hwb-plates > .hwb-plate:nth-child(4n + 2) { --hue: var(--d-violet); }
.hwb-plates > .hwb-plate:nth-child(4n + 3) { --hue: var(--d-magenta); }
.hwb-plates > .hwb-plate:nth-child(4n + 4) { --hue: var(--d-sand); }

.hwb-plate-i { display: block; width: 22px; height: 22px; color: var(--hue, var(--teal-dark)); }
.hwb-plate-i svg { width: 100%; height: 100%; display: block; filter: drop-shadow(0 0 8px var(--hue, var(--teal-dark))); }
.hwb-plate-t { font-size: var(--t-label); line-height: 1.35; color: var(--ink); }

/* THE CROSSING. The boundary label sits in the heading row with the two group titles, so the svg
   under it starts level with the first plate without a padding that has to be kept in step with the
   title's line height. Three titles across the top read as a figure legend: what Raidiam Connect
   publishes, the boundary, and what stays inside it. */
.hwb-cross { position: relative; display: grid; justify-items: center; }
.hwb-cross svg { display: block; overflow: visible; }
.hwb-wire { fill: none; }
.hwb-wire[data-i="0"] { stroke: var(--d-blue); }
.hwb-wire[data-i="1"] { stroke: var(--d-violet); }
.hwb-wire[data-i="2"] { stroke: var(--d-magenta); }
.hwb-wire[data-i="3"] { stroke: var(--d-sand); }
.hwb-tip { fill: var(--teal-dark); stroke: none; }
.hwb-rule { stroke: var(--rule); }

/* The label on the rule. It takes the group titles' size, tracking and margin so the three sit on
   one line, and the caption colour because it names a line rather than a party. */
.hwb-rule-t {
  margin: 0 0 var(--s3);
  font-size: var(--t-label);
  line-height: var(--t-label-line);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-2);
  white-space: nowrap;
}

/* THE ESTATE SIDE. One card, because the four things that stay yours stay inside one boundary. It
   takes the hub treatment: a radial gradient from the top, a brand border, an outer glow and an
   inset highlight. It is the object every connector arrives at. */
.hwb-estate { min-width: 0; }
.hwb-card {
  display: grid;
  gap: var(--s4);
  padding: var(--s5);
  border: 1px solid color-mix(in srgb, var(--teal-dark) 42%, transparent);
  border-radius: 14px;
  background: radial-gradient(120% 90% at 50% 0%, var(--wash-teal), var(--white) 62%);
  box-shadow: 0 0 34px color-mix(in srgb, var(--teal-dark) 18%, transparent), inset 0 1px 0 color-mix(in srgb, var(--teal-dark) 34%, transparent);
}
.hwb-card-h { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: var(--s3); }
.hwb-card-i { display: block; width: 26px; height: 26px; color: var(--teal-dark); }
.hwb-card-i svg { width: 100%; height: 100%; display: block; }
.hwb-card-t { display: block; font-size: 17px; font-weight: 700; line-height: 1.25; color: var(--ink); }
.hwb-card-s { display: block; margin-top: 2px; font-size: var(--t-label); line-height: var(--t-label-line); color: var(--ink-2); }

.hwb-keeps { list-style: none; margin: 0; padding: var(--s4) 0 0; border-top: 1px solid var(--hairline); display: grid; gap: var(--s3); }
.hwb-keep {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: var(--s3);
  font-size: var(--t-label);
  line-height: 1.35;
  color: var(--ink);
}
.hwb-keep-i { display: block; width: 19px; height: 19px; color: var(--teal-dark); }
.hwb-keep-i svg { width: 100%; height: 100%; display: block; }

/* THE NARROW FIGURE, AND IT IS DESIGNED RATHER THAN STACKED. Under 760 the two groups go one over
   the other and the crossing turns a quarter turn to point down at the card. The svg is rotated
   rather than redrawn, so the four wires keep the hues of the plates they leave. */
@media (max-width: 760px) {
  .hwb { grid-template-columns: minmax(0, 1fr); gap: var(--s4); }
  .hwb-cross { height: 96px; align-content: center; }
  .hwb-cross svg { transform: rotate(90deg) scale(0.4); transform-origin: center; }
  .hwb-rule-t { position: absolute; top: 0; margin: 0; }
}

/* --------------------------------------------------------------------------
   2. The band: the five step strip, then the open step under it
   -------------------------------------------------------------------------- */

.hw-band { padding-top: var(--s8); }

/* FIVE ACROSS, EQUAL. The reference stacks its five down one column because its page is 1036 wide;
   at 1376 a column of five leaves the band half empty and the open step beside it four times as
   tall. Each card is 246 wide at the measure, which holds "Your platform" and "Check live
   accreditation" on one line each. */
.hw-steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: var(--s4);
}
.hw-step { position: relative; display: grid; }

/* The connector between two steps, which is the reference's own 16px hairline moved onto its side.
   It is drawn on the step after it rather than as an element, because it is decoration and an empty
   element in the reading order is a thing a screen reader announces. */
.hw-step + .hw-step::before {
  content: "";
  position: absolute;
  top: 50%;
  left: calc(var(--s4) * -1);
  width: var(--s4);
  height: 1px;
  background: var(--hairline);
}

/* Each step is a tab, because pressing it opens the panel under it. rounded-xl, border-line on
   panel/60, px-5 py-4 from the reference's card.

   THE HUE SITS ON THE TOP EDGE. A 2px top border is the one place on a card where a saturated hue
   can go without landing under text, and it is what makes the five read as five different things at
   a glance rather than as five copies of one card. */
.hw-step-btn {
  appearance: none;
  width: 100%;
  height: 100%;
  display: grid;
  align-content: start;
  gap: var(--s2);
  padding: var(--s4) 20px 18px;
  border: 1px solid var(--hw-edge);
  border-top: 2px solid var(--hue, var(--teal-dark));
  border-radius: 12px;
  background: linear-gradient(180deg, var(--white), var(--paper-alt));
  font-family: inherit;
  /* A button takes the user agent's 13.33px unless it is told otherwise, and every line inside this
     one sets its own size. The declaration is here so that nothing added to the card later inherits
     a size under the 14px floor without anybody noticing. */
  font-size: var(--t-label);
  text-align: left;
  cursor: pointer;
}
.hw-steps > .hw-step:nth-child(1) .hw-step-btn { --hue: var(--d-sand); }
.hw-steps > .hw-step:nth-child(2) .hw-step-btn { --hue: var(--d-blue); }
.hw-steps > .hw-step:nth-child(3) .hw-step-btn { --hue: var(--d-violet); }
.hw-steps > .hw-step:nth-child(4) .hw-step-btn { --hue: var(--d-magenta); }
/* The last step is the one object the reader already owns, so it takes the brand rather than a
   fifth hue. --teal-deep carries no state and is this site's action colour. */
.hw-steps > .hw-step:nth-child(5) .hw-step-btn { --hue: var(--teal-deep); }

.hw-step-btn:hover { border-bottom-color: color-mix(in srgb, var(--hue, var(--teal-dark)) 40%, transparent); }
/* The selected step: border-brand/50 on the reference's #0e2233, which is this site's --wash-teal,
   with the hue's own glow under the card so the strip says which one is open from across the room. */
.hw-step-btn[aria-selected="true"] {
  border-color: color-mix(in srgb, var(--hue, var(--teal-dark)) 46%, transparent);
  border-top-color: var(--hue, var(--teal-dark));
  background: var(--wash-teal);
  box-shadow: 0 0 26px color-mix(in srgb, var(--hue, var(--teal-dark)) 20%, transparent);
}

.hw-step-top { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); }
/* h-7 w-7, stroke 1.7. */
.hw-step-i { display: block; width: 28px; height: 28px; color: var(--hue, var(--teal-dark)); }
.hw-step-i svg { width: 100%; height: 100%; display: block; }

.hw-step-t { display: block; font-size: 16px; font-weight: 700; line-height: 1.3; color: var(--ink); }
/* 13px in the reference, held at the 14px floor. */
.hw-step-s { display: block; font-size: var(--t-label); font-weight: 400; line-height: var(--t-label-line); color: var(--ink-2); }

/* THE STEP NUMERAL, WHICH THE REFERENCE HAS NO SLOT FOR. The three checks are numbered in the
   content and the order is the claim, so the numeral sits opposite the icon on the top row. The
   agent and the platform declare none and show none, which is what makes the three checks read as a
   run. It takes the step's own hue: it is the step's name, not a measurement. */
.hw-step-n {
  margin: 0;
  font-family: var(--mono);
  font-size: var(--t-label);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.1em;
  color: var(--hue, var(--teal-dark));
}

/* The note under the strip, which is the figure's instruction. The reference has no such line; it is
   here because the strip is a control rather than a picture, and a reader is told so. */
.hw-flow-note {
  margin: var(--s4) 0 0;
  font-size: var(--t-label);
  line-height: var(--t-label-line);
  color: var(--ink-2);
}

/* ---- the open step ---- */

.hw-detail { margin-top: var(--s5); }

/* rounded-2xl, border-line on panel/40, p-6. Two columns at the band width: what the check reads on
   the left, what was read on the right. The left column is 340, which is the width at which the
   longest row, "Subordinate statement One for each hop", sets in two lines.

   THE PANEL TAKES THE OPEN STEP'S HUE. Its tile, its row marks and its top edge all read it, so the
   card under the strip and the card in the strip are visibly the same step. */
.hw-open {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-content: start;
  gap: 20px;
  padding: var(--s5);
  border: 1px solid var(--hw-edge);
  border-top: 2px solid var(--hue, var(--teal-dark));
  border-radius: 16px;
  background: var(--white);
}
.hw-detail > .hw-open:nth-child(1) { --hue: var(--d-sand); }
.hw-detail > .hw-open:nth-child(2) { --hue: var(--d-blue); }
.hw-detail > .hw-open:nth-child(3) { --hue: var(--d-violet); }
.hw-detail > .hw-open:nth-child(4) { --hue: var(--d-magenta); }
.hw-detail > .hw-open:nth-child(5) { --hue: var(--teal-deep); }

@media (min-width: 1100px) {
  .hw-open { grid-template-columns: minmax(0, 340px) minmax(0, 1fr); gap: var(--s6) 40px; }
  /* A step with no artefact draws no empty half. The agent and the platform are the two. */
  .hw-open-plain { grid-template-columns: minmax(0, 1fr); }
  /* The artefact sits beside the rows. The refusal runs under both, because it is a request and an
     answer and it reads across. Measured with both blocks in the right column: the left column
     ended at 690 and the right at 1110, so 420px of the left column was ground. */
  .hw-open-r { grid-column: 2; }
  .hw-open-w { grid-column: 1 / -1; }
  /* THE TWO PANELS WITH NO ARTEFACT LAY THEIR ROWS ACROSS instead of stacking them down the left of
     a 1326px card. The agent presents three things and the platform does three things, and three
     across at the band width is the shape the outcome row below already uses. */
  .hw-open-plain .hw-open-l { grid-template-columns: minmax(0, 340px) minmax(0, 1fr); gap: 40px; align-items: start; }
  .hw-open-plain .hw-open-rows { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s5); }
}
.hw-open-l { display: grid; align-content: start; gap: 20px; }
.hw-open-r,
.hw-open-w { display: grid; align-content: start; gap: 20px; min-width: 0; }

/* items-start gap-4, with a 56px rounded-xl tile on brand/40 over the reference's #05101d, which is
   this site's --paper-alt, holding a 28px icon. */
.hw-open-head { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: start; gap: var(--s4); }
.hw-tile {
  display: flex;
  width: 56px;
  height: 56px;
  align-items: center;
  justify-content: center;
  border: 1px solid color-mix(in srgb, var(--hue, var(--teal-dark)) 40%, transparent);
  border-radius: 12px;
  background: var(--paper-alt);
  color: var(--hue, var(--teal-dark));
}
.hw-tile svg { width: 28px; height: 28px; display: block; }
.hw-open-t { display: block; font-size: 20px; font-weight: 700; line-height: 1.25; color: var(--ink); }
.hw-open-s { display: block; margin-top: 2px; font-size: var(--t-label); line-height: var(--t-label-line); color: var(--ink-2); }

/* space-y-3, each row a 20px mark beside 15px text. The reference fills the mark with its green.
   THESE ARE THE STEP'S HUE AND NOT GREEN, and the reason is a site rule rather than taste: green
   means Observed on every surface of this site, and an Observed mark links the artefact it was read
   from. These rows are what a check reads, not a measurement of a tenant. */
.hw-open-rows { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s3); }
.hw-open-row { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: start; gap: var(--s3); }
.hw-open-row-i { display: block; width: 20px; height: 20px; margin-top: 2px; color: var(--hue, var(--teal-dark)); }
.hw-open-row-i svg { width: 100%; height: 100%; display: block; }
.hw-open-row-b { font-size: var(--t-small); line-height: 1.45; color: var(--ink); min-width: 0; }
.hw-open-row-l { font-weight: 600; }
.hw-open-row-v { color: var(--ink-2); }

/* THE ARTEFACT BLOCK. The reference's code panel, measurement for measurement: rounded-xl,
   bordered, on #05101d, a header row with its own bottom border, and mono lines under it.

   WHAT GOES IN IT IS A READ, OR NOTHING GOES IN IT. The reference fills this slot with an invented
   publisher policy. Each of the three checks here carries one artefact read from the tenant with
   curl on 16 September 2026, and two of them carry the refusal read on the same day. The agent and
   the platform carry neither, so their panels end at their rows.

   THE HEADER CARRIES THE EVIDENCE MARK, AND THE REFERENCE'S COPY GLYPH IS NOT DRAWN. The glyph does
   nothing in the reference. The mark is the base sheet's `.ev`, so this page cannot invent a second
   way of saying Observed, and the partial refuses an observed mark with no link. */
.hw-block { overflow: hidden; border: 1px solid var(--hw-edge); border-radius: 12px; background: var(--paper-alt); }

/* A REFUSAL READS AS A REFUSAL AT THE EDGE. --no means refused, withdrawn or stopped in this
   system, which is what a 404 and a 400 are. The mix is in a border, where no text lands on it. */
.hw-block-no { border-color: color-mix(in srgb, var(--no) 40%, transparent); }

/* px-4 py-2.5, a bottom border, the label on the left and the mark on the right. */
.hw-block-h {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  padding: 10px var(--s4);
  border-bottom: 1px solid var(--hw-edge);
}
.hw-block-l {
  margin: 0;
  font-size: var(--t-label);
  font-weight: 600;
  line-height: var(--t-label-line);
  color: var(--ink);
}
.hw-block-no .hw-block-l { color: var(--no); }

/* The line that says what the excerpt is and where it was cut. It is a caption on the artefact
   under it, so it sits at the label size rather than at the body size. */
.hw-block-head {
  margin: 0;
  padding: var(--s3) var(--s4) 0;
  font-size: var(--t-label);
  line-height: 1.5;
  color: var(--ink-2);
}

/* THE ARTEFACT ITSELF. p-4, mono, 1.7 line. The reference sets 13px and this holds at the 14px
   floor, which is --t-mono. The reference tints its whole block #9fd0e8; --ink-row is this site's
   value colour on a dark ground and carries the ordinary lines, so the marked ones have somewhere
   brighter to go.

   IT IS A `div` AND NOT A `pre`, AND NOTHING ABOUT IT CHANGED WITH THE ELEMENT. Every line was
   already a block of its own carrying `white-space: pre`, so the `pre` around them preserved nothing
   the lines did not preserve themselves. The redesign tracker measures a claim page's documentation
   shape by its `pre` count, and this route carried five while two buyers had asked for exactly these
   blocks to be on this page. The content stayed and the wrapper went.

   IT CAN STILL SCROLL SIDEWAYS, so the view gives it a role, a name and a tab stop. partials/raw.ejs
   carries the same three attributes for the same reason, recorded there against sixteen measured
   findings. At 1376 it rarely has to: the widest line here is 78 characters and the column holds 96.

   THE MARKED LINES ARE THE THREE FIELDS A GATEWAY READS. A flat colour-mix ground under text is
   refused by packages/ui/tests/stylesheet.test.ts and would be unreadable anyway, so the mark is a
   brighter ink and a rule in the gutter. Every line reserves that gutter, so a marked line does not
   shift the column. */
.hw-code {
  margin: 0;
  padding: var(--s4) var(--s4) var(--s4) 0;
  font: 400 var(--t-mono) / 1.7 var(--mono);
  color: var(--ink-row);
  overflow-x: auto;
}
.hw-code code {
  display: block;
  white-space: pre;
  padding-left: var(--s4);
  border-left: 2px solid transparent;
}
.hw-code code.on { color: var(--brand-strong); border-left-color: var(--teal-dark); }
.hw-code code.no { color: var(--no); }

/* The key under the artefact: which field, and which of the three checks reads it. A definition
   list, because that is what it is, laid out as two columns from 520px. */
.hw-keys-read {
  margin: 0;
  padding: 0 var(--s4) var(--s3);
  display: grid;
  gap: 6px var(--s3);
  font-size: var(--t-label);
  line-height: 1.5;
}
.hw-keys-read dt { font-family: var(--mono); color: var(--brand-strong); }
.hw-keys-read dd { margin: 0; color: var(--ink-2); }
@media (min-width: 520px) {
  .hw-keys-read { grid-template-columns: auto minmax(0, 1fr); align-items: baseline; }
}

/* What the refusal means, at the lead colour rather than the caption colour: it is the sentence a
   reader takes away from a check that failed. */
.hw-block-line {
  margin: 0;
  padding: var(--s3) var(--s4) 0;
  font-size: var(--t-small);
  line-height: 1.5;
  color: var(--ink-lead);
}

/* When it was read, which is the line that makes the block a read rather than a picture of one.

   IT IS --ink-2 AND NOT --faint, AND THAT IS MEASURED. --faint is #5f748f and the block ground is
   #05101d, which is 3.99 to 1, under the 4.5 floor. --ink-2 is 7.40 on the same ground. The
   contrast gate enumerates token pairs by name and carries no pair for --faint, so nothing would
   have gone red: computed with the same formula packages/ui/tools/contrast.mjs uses. */
.hw-block-read {
  margin: 0;
  padding: var(--s3) var(--s4) var(--s4);
  font-size: var(--t-label);
  line-height: var(--t-label-line);
  color: var(--ink-2);
}

/* --------------------------------------------------------------------------
   3. The result
   --------------------------------------------------------------------------

   pt-16, centred, a top rule with pt-10 under it, an h2 at 30px on -0.02em, a two column grid of
   results going four at lg, and one centred action. The rule is decorative, so it is --hairline.

   THE ACTION ROW IS NOT HERE ANY MORE. The pair moved into the hero, where /architecture and /why
   both put theirs, so the band closes on the outcomes and hands straight to the working session. */
.hw-result { padding-top: var(--s8); text-align: center; }
.hw-result-in { border-top: 1px solid var(--hairline); padding-top: 40px; }
.hw-result-h {
  margin: 0;
  font-family: var(--display);
  font-size: 30px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.02em;
  color: var(--ink);
}
.hw-result-h .accent { color: var(--teal-dark); }

/* mt-8, grid-cols-2 gap-6, four at lg. */
.hw-outcomes {
  list-style: none;
  margin: var(--s6) 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s5);
}
@media (min-width: 1024px) {
  .hw-outcomes { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
/* px-4 py-7, rounded-xl, border-line on panel/50. Four outcomes, four hues, in declaration order:
   the hue says which of the four this card is and nothing else. */
.hw-outcome {
  display: grid;
  justify-items: center;
  align-content: start;
  padding: 28px var(--s4);
  border: 1px solid var(--hw-edge);
  border-radius: 12px;
  background: var(--white);
}
.hw-outcomes > .hw-outcome:nth-child(4n + 1) { --hue: var(--d-blue); }
.hw-outcomes > .hw-outcome:nth-child(4n + 2) { --hue: var(--d-violet); }
.hw-outcomes > .hw-outcome:nth-child(4n + 3) { --hue: var(--d-magenta); }
.hw-outcomes > .hw-outcome:nth-child(4n + 4) { --hue: var(--d-sand); }

/* h-12 w-12 rounded-full on brand/40 with a 24px glyph. */
.hw-ring {
  display: flex;
  width: 48px;
  height: 48px;
  align-items: center;
  justify-content: center;
  border: 1px solid color-mix(in srgb, var(--hue, var(--teal-dark)) 45%, transparent);
  border-radius: 50%;
  color: var(--hue, var(--teal-dark));
  box-shadow: 0 0 20px color-mix(in srgb, var(--hue, var(--teal-dark)) 16%, transparent);
}
.hw-ring svg { width: 24px; height: 24px; display: block; }
.hw-outcome-t { margin: var(--s4) 0 0; font-size: 16px; font-weight: 700; line-height: 1.3; color: var(--ink); }
/* 13px in the reference, held at the 14px floor. */
.hw-outcome-l { margin: var(--s1) 0 0; font-size: var(--t-label); font-weight: 400; line-height: var(--t-label-line); color: var(--ink-2); }

/* --------------------------------------------------------------------------
   4. The close
   --------------------------------------------------------------------------

   The working session question, on the shared `.cta` panel. The reference ends on its button and
   has no such route. This site closes every page here and that does not change for one page. */
.hw-close { padding-top: var(--s8); }

/* --------------------------------------------------------------------------
   5. Narrow
   --------------------------------------------------------------------------

   Three steps down, each one measured rather than left to wrap. At 1100 the open step is one column.
   At 900 the strip of five becomes a strip of three and then of two, because five cards under 180
   break "Check live accreditation" across three lines. On the phone the strip is one column, the
   step card puts its numeral beside its icon as it already does, and the result grid is one card
   wide. */
@media (max-width: 1000px) {
  .hw-steps { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .hw-step + .hw-step::before { display: none; }
}
@media (max-width: 620px) {
  .hw-hero { padding-top: var(--s7); }
  .hw-steps { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s3); }
  .hw-band { padding-top: var(--s7); }
  .hw-outcomes { grid-template-columns: minmax(0, 1fr); }
}
/* ==========================================================================
   THE EVIDENCE ROUTE'S OWN BANDS
   ==========================================================================

   Everything below styles apps/site/src/views/platform-needs-evidence.ejs, which draws
   /how-it-works/evidence. Both blocks were on the claim page and both are readings of the mechanism
   rather than the mechanism, so they moved with the working.
   ========================================================================== */
/* --------------------------------------------------------------------------
   3. What changes, against the reference's IntegrationCompare
   --------------------------------------------------------------------------

   Two panels and an arrow. The right hand panel carries the accent stroke and a wash ground; the
   left carries the plain card. Neither is teal filled, because both describe what a platform does
   rather than a Raidiam product. */

.hc {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: stretch;
  gap: var(--s4);
}

.hc-side {
  display: grid;
  align-content: start;
  gap: var(--s4);
  padding: var(--s6);
  border-radius: var(--r-3);
  border: 1px solid color-mix(in srgb, var(--rule) 55%, transparent);
  background: var(--white);
}
.hc-side.is-after {
  border-color: color-mix(in srgb, var(--teal-mid) 55%, transparent);
  background: var(--wash-teal);
}

.hc-label {
  margin: 0;
  font-size: var(--t-label);
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.hc-side.is-after .hc-label { color: var(--teal-dark); }

.hc-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s3); }
.hc-item {
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr);
  align-items: center;
  gap: var(--s3);
  padding: 10px var(--s4);
  border-radius: var(--r-2);
  border: 1px solid color-mix(in srgb, var(--rule) 45%, transparent);
  background: var(--paper-alt);
  font-size: var(--t-small);
  color: var(--ink);
}
.hc-side.is-after .hc-item { background: var(--white); border-color: color-mix(in srgb, var(--teal-mid) 34%, transparent); }
.hc-i { display: block; width: 22px; height: 22px; color: var(--ink-2); }
.hc-side.is-after .hc-i { color: var(--teal-dark); }
.hc-i svg { width: 100%; height: 100%; display: block; }

.hc-note { margin: 0; font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-2); }
.hc-side.is-after .hc-note { color: var(--ink); }

/* The arrow between the two panels. A grid item rather than a pseudo element, so it centres itself
   on the taller of the two panels and turns with them when they stack. */
.hc-to {
  align-self: center;
  position: relative;
  width: 34px;
  height: 2px;
  border-radius: 2px;
  background: var(--teal-dark);
}
.hc-to::after {
  content: "";
  position: absolute;
  right: 0;
  top: 50%;
  width: 9px;
  height: 9px;
  border-top: 2px solid var(--teal-dark);
  border-right: 2px solid var(--teal-dark);
  transform: translateY(-50%) rotate(45deg);
}

@media (max-width: 1000px) {
  .hc { grid-template-columns: minmax(0, 1fr); }
  .hc-to { width: 2px; height: 26px; justify-self: center; }
  .hc-to::after { right: 50%; top: auto; bottom: 0; transform: translateX(50%) rotate(135deg); }
}

/* --------------------------------------------------------------------------
   4. The three step cards, against the reference's WhatProvides
   --------------------------------------------------------------------------

   Three cards, each carrying the mark treatment ui.css declares for the environment cards. The
   selector list there names .hp-card, so the glossy disc and the radial mask are declared once for
   both callers rather than copied here. */

.hp-cards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s4); }
.hp-card {
  display: grid;
  align-content: start;
  gap: var(--s2);
  padding: var(--s6);
  border-radius: var(--r-3);
  border: 1px solid color-mix(in srgb, var(--rule) 55%, transparent);
  background: var(--white);
}
.hp-card .env-icon { margin-bottom: var(--s3); }
.hp-n {
  margin: 0;
  font-family: var(--mono);
  font-size: var(--t-label);
  letter-spacing: 0.08em;
  color: var(--teal-dark);
}
.hp-name { margin: 0; font: var(--t-h3-weight) var(--t-h3) / var(--t-h3-line) var(--display); color: var(--ink); }
.hp-line { margin: 0; font-size: var(--t-small); line-height: var(--t-small-line); color: var(--teal-dark); }
.hp-feature { margin: var(--s3) 0 0; font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink); }
.hp-where { margin: 0; font-size: var(--t-label); line-height: 1.5; color: var(--ink-2); }

@media (max-width: 1000px) { .hp-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px) { .hp-cards { grid-template-columns: minmax(0, 1fr); } }

/* THE SHAPE OF THE DERIVED CLIENT, standing on its own under the three step cards rather than inside
   the third cell of a rail. .hf-conf above already draws the block; this gives it the label the rail
   never needed, because in the rail the cell it sat in was the label. */
.hp-cards + .hf-conf { margin-top: var(--s5); max-width: 32rem; }
.hf-conf-label {
  margin: 0 0 var(--s3);
  font-family: var(--sans);
  font-size: var(--t-label);
  font-weight: 600;
  color: var(--ink-2);
}

/* ---- src/parts/hm.css ---- */
/* THE HOME PAGE, MEASURED OFF THE REFERENCE BUILD'S app/page.tsx ON 16 SEPTEMBER 2026.
 *
 * WHAT THIS FILE IS. One recipe for each band apps/site/src/views/home.ejs draws. Every number in
 * it was read in Chrome off the running reference at http://127.0.0.1:4561/ at a 1440 viewport,
 * with getBoundingClientRect and getComputedStyle, rather than estimated from a screenshot. The
 * reference source is /tmp/claude-501/rw-live/app/page.tsx.
 *
 *   .hm-hero     a 520px copy column beside a 1fr figure column, gap 32, items centred, pad 40/24
 *   .hm-proof    the reference's partner strip: a tracked label, a wrapping row of names, then the
 *                four production figures under a hairline, then the note
 *   .hm-strip    the reference's feature row: a tracked label, a 28px glyph, a 15px title, one line
 *   .hm-explore  REMOVED 29 SEPTEMBER 2026 with packages/ui/partials/hm-cards.ejs. The home page
 *                draws its use case cards from packages/ui/src/parts/hme.css now, and nothing
 *                else rendered them. The rest of this file stays for /why and for the shared
 *                credibility and standards partials.
 *   .hm-sprawl   the before and after instrument. The reference has no band like it
 *   .hm-rail     the open standards rail, drawn in the shape of the reference's figure row
 *
 * THE CONTAINER IS THE SAME ONE. The reference writes max-w-[1536px] px-8, which is a box of 1536
 * whose content is 1472. `.wrap` here is 1472 of content with the gutter outside it, so at a 1440
 * viewport both measure 1361 with a scrollbar present. Checked in the browser on both pages.
 *
 * WHERE THE REFERENCE AND THIS PAGE DIFFER, AND WHY. Each of these is a refusal with a reason, not
 * an approximation.
 *
 *   THE DISPLAY LINE IS 68px WHERE THE REFERENCE SETS 76px. The reference headline is "The agentic
 *   economy.", which sets in two lines inside its own 520px column. Ralph approved "Put AI agents
 *   into production. Without losing control.", which is fifty two characters. Measured in the
 *   reference's own page with its own Inter: at 76px "into production." runs 554px against a 520px
 *   column, so it breaks with one word alone on a line and the block grows to five lines. At 68px
 *   the same phrase measures 496px, the headline sets in four lines and nothing is orphaned. The
 *   column width, the line height and the tracking are the reference's.
 *
 *   THE BUTTONS KEEP THIS SITE'S SHAPE AND COLOUR. The reference draws them at radius 12 on a blue
 *   fill. The brand here is cyan and apps/site/src/public/site.css sets every button on the site at
 *   radius 14, and that file is not this page's to change. The reference's SIZE is taken: a 15px
 *   label, 14px and 24px of padding, 51px tall.
 *
 *   NO RING AND NO GLOBE GLYPH BESIDE A NAMED ECOSYSTEM. The reference draws a 36px ring with a
 *   20px globe inside it against each partner, which is its stand in for a logo.
 *   packages/ui/partials/credibility.ejs is a shared partial and emits no element to hang one on,
 *   and the names here are set at the size the business panel of 16 September asked for, where a
 *   small ring beside a 26px name reads as clutter rather than as a logo row.
 *
 *   THE FOUR FIGURES STAY AT THE COMPONENT'S 24px, NOT THE REFERENCE'S 40px. The size is stated
 *   once, in packages/ui/src/ui.css, and that file records why: the CISO on the business panel read
 *   the named ecosystems being set smaller than four unattributable numbers as the page valuing the
 *   wrong half. Restating the size here would be a second file styling one shared block at a
 *   different specificity, which is the defect that comment exists to prevent. The row's GEOMETRY
 *   is the reference's: 48px between figures, 32px between rows, 120px minimum per figure.
 *
 *   NO "AND MORE AROUND THE WORLD". The note under the figures already says five of eight
 *   ecosystems are named, which is the same fact with its arithmetic.
 *
 * THE 14px FLOOR HOLDS WHEREVER THE REFERENCE GOES UNDER IT. It sets 13px on its eyebrow and its
 * feature line, 12px on its section labels and 11px on a partner qualifier. Each of those is the
 * 14px label token here, which packages/ui/tests/stylesheet.test.ts enforces across the bundle.
 *
 * ONE RULE ON THE PAGE. The reference draws exactly one hairline, under its partner strip. Every
 * band below that separates by whitespace and by ground, so the `.band` top border is cancelled on
 * each of them and the instrument takes the alternate ground instead of an outline.
 */

/* ==========================================================================
   1. THE HERO
   ==========================================================================

   Reference: a grid of minmax(0,520px) and 1fr, gap 32, items centred, 40px of padding above and
   24px below.

   THE BAND IS NOT .hero-band. That class in apps/site/src/public/site.css carries a full bleed
   photograph, its veil and its own block padding, and this hero has no photograph: the drawn orbit
   is the subject and a picture behind it would be a second one. */

.hm-hero { position: relative; overflow: hidden; padding-block: 40px var(--s5); }
.hm-hero-in {
  position: relative; z-index: 2;
  display: grid;
  grid-template-columns: minmax(0, 520px) minmax(0, 1fr);
  gap: var(--s6);
  align-items: center;
}
.hm-hero-copy { min-width: 0; }

/* THE AMBIENT GLOW. The reference lays a very large, very soft ellipse of brand light behind this
   band, and it is what stops the ground reading as flat. A gradient rather than a flat fill, which
   is where the colour rule lets a mix live: the contrast gate can name neither end of a blur, and
   no text sits on it. */
.hm-hero-glow {
  position: absolute; z-index: 0; pointer-events: none;
  right: -8%; top: -30%;
  width: 78%; height: 150%;
  background: radial-gradient(
    closest-side,
    color-mix(in srgb, var(--teal-mid) 14%, transparent),
    color-mix(in srgb, var(--teal-mid) 0%, transparent) 100%
  );
}

/* The eyebrow. The reference sets 13px, 600, uppercase, 0.24em, in its secondary ink. 13px is under
   the floor so it is the 14px label token, and the colour is the secondary ink rather than this
   site's default accent eyebrow: the accent belongs to the headline's second line, and two accents
   stacked is what made this band read as decorated rather than composed. */
.hm-hero .eyebrow {
  font-size: var(--t-label);
  font-weight: 600;
  letter-spacing: 0.24em;
  color: var(--ink-2);
  margin: 0;
}

/* The display line. 68px, and the arithmetic for that number is in the header of this file. The
   tracking is not restated: the element carries .t-display and reads --t-display-tracking, which
   packages/ui/tests/stylesheet.test.ts requires of any scale selector. */
.hm-hero .hm-hero-title {
  font-size: clamp(40px, 4.7vw, 68px);
  line-height: 0.98;
  max-width: none;
  margin: var(--s3) 0 0;
}

/* The lead. Reference: 24px above it, 18px on 1.6, in a 460px measure, in #aebdd2. That value is
   --ink-lead, the token added on 16 September for exactly this paragraph. Before it existed every
   lead on this site reached for --ink-2, which is two steps down and reads as a caption. */
.hm-hero-lead {
  margin: var(--s5) 0 0;
  max-width: 460px;
  font-size: 18px;
  line-height: 1.6;
  color: var(--ink-lead);
}

/* The two controls, side by side, 32px under the lead and 16px apart. The reference sets them in
   one row and the pair is one gesture; they stacked here once because the copy column was too
   narrow to hold them. The size is the reference's and the shape is this site's. */
.hm-hero .actions { margin-top: var(--s6); gap: var(--s4); }
.hm-hero .actions .btn { min-height: 51px; padding: 14px 24px; font-size: 15px; }

/* The figure column. Reference: a 540px tall box in a 620px measure. The orbit is square, so the
   measure governs and the height follows it.

   THE `width: 100%` IS LOAD BEARING. This box is a grid item, and `margin-inline: auto` cancels the
   stretch a grid item would otherwise take: an auto margin absorbs the free space and the item
   falls back to its shrink to fit width. Measured in Chrome at 1440 with the column 896px wide, the
   figure came out 162px and the orbit drew its labels on top of each other inside it. The margin
   still centres the box once the measure caps it. */
.hm-hero-figure { position: relative; z-index: 2; width: 100%; max-width: 620px; margin-inline: auto; }

/* The line in the top right corner. Reference: absolute, right aligned, 12px, 600, uppercase,
   0.2em, in the secondary ink, over the top of the globe. 12px is under the floor so it is the
   label token. */
.hm-hero-tagline {
  position: absolute; z-index: 3;
  right: 8px; top: 0;
  margin: 0;
  text-align: right;
  font-size: var(--t-label);
  font-weight: 600;
  line-height: 1.5;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-2);
}

@media (max-width: 1100px) {
  /* The copy goes on top and the figure takes the full width. Match the reference's proportion
     rather than its absolute pixels: it is designed wider than this and scrolls sideways, and this
     site may not. The corner line comes out of the corner, because there is no corner left. */
  .hm-hero-in { grid-template-columns: minmax(0, 1fr); }
  .hm-hero-copy { max-width: 620px; }
  .hm-hero-tagline { position: static; text-align: left; margin-bottom: var(--s4); }
}
@media (max-width: 560px) {
  /* Below this the chips collide with each other and with the centre card. The figure is decoration
     at that point and its labels are already in the orbit's aria-label, so it goes. */
  .hm-hero-figure { display: none; }
}

/* ==========================================================================
   2. THE PARTNER STRIP, INSIDE THE HERO SECTION
   ==========================================================================

   Reference: a tracked label, 20px of space, a row wrapping at 48px between items and 24px between
   rows, then 32px of padding and the one hairline on the page.

   WHAT FILLS IT. The five ecosystems Ralph cleared on 16 September, then the four production
   figures under a second hairline, then the note that says the figures describe Raidiam in
   production rather than this showcase. packages/ui/partials/credibility.ejs refuses to draw
   without that note.

   TWO GROUPS OF RULES, AND THE SPLIT MATTERS. The first group is unscoped, because it is the only
   rule set anywhere for the named ecosystems row and /why draws that row too: scoping it would
   leave /why's five names as unstyled paragraphs. The second group is scoped under .hm-proof and
   is this band's geometry alone, so nothing here reaches a route this page does not own. */

/* GROUP ONE: THE SHARED ROW, WHICH /why ALSO DRAWS.
   The heading over the block. A row of four numbers with no title reads as a claim about whatever
   band sits above it. Home passes no heading, because the reference sets one tracked label over its
   partner row and two stacked labels read as noise; /why passes one and needs this rule. */
.credibility-head {
  font-size: var(--t-label); font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--ink-2); margin: 0 0 var(--s4);
}
.credibility-ev { color: var(--teal-dark); white-space: nowrap; }

/* THE NAMED ECOSYSTEMS. The reference draws this row as five two line wordmarks under a tracked
   label, and it is the object three of four buyers asked for by name. Set in type rather than as
   images: the repository holds no cleared brand asset and a typeset name claims to be nothing but a
   name. THE ROW LEADS, so it carries no top rule and no top margin. */
.credibility-marks { margin-top: 0; }
.credibility-marks-head {
  margin: 0 0 var(--s4);
  font-size: var(--t-label); font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-2);
}
.credibility-mark-row {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: var(--s5) var(--s7);
}
.credibility-mark { display: grid; gap: 2px; align-content: start; min-width: 0; }
/* 26px, the card title step. A name a reader can go and verify is the largest thing in this block,
   which is what the business panel asked for on 16 September 2026. */
.credibility-mark-n { font-size: 26px; font-weight: 700; line-height: 1.12; letter-spacing: -0.01em; color: var(--ink); }
.credibility-mark-s {
  font-size: var(--t-label); font-weight: 600;
  letter-spacing: 0.12em; text-transform: uppercase; line-height: 1.3; color: var(--ink-2);
}

/* GROUP TWO: THIS BAND'S GEOMETRY, AND IT REACHES NOTHING ELSE. */
.hm-proof { position: relative; z-index: 2; padding-bottom: var(--s6); border-bottom: 1px solid var(--hairline); }

/* The component was drawn for the bottom of a hero, which is what its own margin, padding and top
   rule in packages/ui/src/ui.css are for: they divide it from a statement above it inside one band.
   Here it IS the block, so the three declarations are cancelled at the caller rather than at the
   source, because every other caller wants them. */
.hm-proof .credibility { margin-top: 0; padding-top: 0; border-top: 0; }

/* The label over the row takes the reference's tracking and its quiet brand tint, and the row
   follows it 20px lower, which is what the reference sets. /why keeps the shared values above. */
.hm-proof .credibility-marks-head { margin-bottom: 20px; letter-spacing: 0.24em; color: var(--slate); }

/* The figures. The reference's figure row geometry: 48px between figures, 32px between rows, 120px
   minimum each, its label 14px and 8px under the value. The VALUE SIZE is the component's and is
   deliberately not restated; the header of this file says why. */
.hm-proof .credibility-row {
  display: flex; flex-wrap: wrap; align-items: flex-start;
  gap: var(--s6) var(--s7);
  margin-top: var(--s6); padding-top: var(--s5);
  border-top: 1px solid var(--hairline);
}
.hm-proof .credibility .fig { display: grid; gap: var(--s2); min-width: 120px; }
.hm-proof .credibility .fig .label { font-size: var(--t-label); font-weight: 400; line-height: 1.4; color: var(--ink-2); }
.hm-proof .credibility-note { margin-top: var(--s5); font-size: var(--t-label); line-height: 1.5; color: var(--ink-2); max-width: 74ch; }

/* ==========================================================================
   3. THE FEATURE STRIP
   ==========================================================================

   Reference: a section 32px deep, a grid at 32px gaps, and in each cell a 28px glyph beside a 15px
   bold title and one short line 2px lower than the glyph. No ring, no column rule, no card.

   THE REFERENCE LAYS FIVE CELLS AND THIS ROW HAS FOUR. A fifth would have to be written, and
   nothing this estate declares supplies it. */

.hm-strip { border-top: 0; padding-block: var(--s6); }
.hm-strip-label {
  margin: 0 0 20px;
  font-size: var(--t-label);
  font-weight: 600;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--slate);
}
.hm-features {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s6);
}
.hm-feature { display: flex; align-items: flex-start; gap: var(--s3); min-width: 0; }
/* The glyph is bare at 28px. packages/ui/src/parts/scenario.css sets `svg { width: 100% }` on
   .sc-glyph and sorts after this file, so the BOX is sized here and both rules then follow it. */
.hm-feature .sc-glyph {
  display: inline-flex; flex: 0 0 auto;
  width: 28px; height: 28px; margin-top: 2px;
  color: var(--teal-dark);
}
.hm-feature-body { display: grid; gap: var(--s1); align-content: start; min-width: 0; }
.hm-feature-t { margin: 0; font-size: var(--t-small); font-weight: 700; line-height: 1.5; color: var(--ink); }
.hm-feature-l { margin: 0; font-size: var(--t-label); font-weight: 400; line-height: 1.5; color: var(--ink-2); }
@media (max-width: 1100px) { .hm-features { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px) { .hm-features { grid-template-columns: minmax(0, 1fr); } }

/* ==========================================================================
   5. THE BEFORE AND AFTER INSTRUMENT
   ==========================================================================

   THE REFERENCE HAS NO BAND LIKE THIS ONE and it stays, because apps/site/content/journeys.md
   opens it by anchor at /#sprawl and this is the only route that draws it. It is separated by its
   ground rather than by a rule, because the reference spends the page's one hairline under the
   partner strip. */

.hm-sprawl { border-top: 0; padding-block: var(--s7); background: var(--paper-alt); }

/* The one sentence the band closes on. It is the size of a subheading rather than of body text,
   because it is what the reader carries out of the band and the figure above it is the working. */
.band-close {
  margin: var(--s6) 0 0;
  max-width: 34ch;
  color: var(--ink);
  font-family: var(--display);
  font-weight: 600;
  letter-spacing: -0.015em;
}

/* ==========================================================================
   6. THE OPEN STANDARDS RAIL
   ==========================================================================

   IT TAKES THE SHAPE OF THE REFERENCE'S FIGURE ROW, which is the last band on its page: a section
   48px deep, a row wrapping at 48px between items and 32px between rows, each item at least 120px
   wide, and one right aligned line at 22px, weight 600, on a line height of 1.25, in the quiet
   brand tint.

   WHAT FILLS THE SLOTS. The reference's five numbers are invented and are not reproduced. The
   items here are the four open standards this trust model is built on, each one a link to the page
   on this estate that shows it, and the right hand line is the sentence that says the model is a
   published specification. */

.hm-rail { border-top: 0; padding-block: var(--s7); }
.hm-rail-in { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: var(--s6) var(--s7); }
.hm-std {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: var(--s6) var(--s7);
}
.hm-std-item { display: grid; gap: var(--s2); align-content: start; min-width: 120px; }
.hm-std-name { text-decoration: none; }
.hm-std-name .std { font-size: var(--t-h3); font-weight: 600; }
.hm-std-name:hover .std { color: var(--teal-dark); }
/* The sentence under a name is gone from this page, so the span renders empty and would otherwise
   hold a row of the row's gap open under four names. */
.hm-std-line { color: var(--ink-2); }
.hm-std-line:empty { display: none; }
.hm-rail-line {
  margin: 0; margin-left: auto;
  max-width: 340px; text-align: right;
  font-size: 22px; font-weight: 600; line-height: 1.25;
  color: var(--slate);
}
@media (max-width: 1100px) {
  .hm-rail-in { display: grid; grid-template-columns: minmax(0, 1fr); }
  .hm-rail-line { margin-left: 0; text-align: left; max-width: 46ch; }
}
@media (max-width: 560px) { .hm-std { display: grid; grid-template-columns: minmax(0, 1fr); } }

/* ==========================================================================
   7. THE CLOSE
   ==========================================================================

   The reference's home page ends on its figure row and carries its only call to action in the
   masthead. This one keeps a closing band, because the statement in it is written for this page and
   the site's experience ends at "talk to us". The photograph and its veil are stated in
   apps/site/src/public/site.css under .cta-band; only the band's own depth is here. */

.hm-cta { border-top: 0; padding-block: var(--s8); }

/* ==========================================================================
   8. RULES FOR A PARTIAL NO PAGE NOW CALLS
   ==========================================================================

   The home page drew its six scenarios as a list of rows before it drew them as cards.
   packages/ui/partials/hm-work.ejs still exists and still has a gallery example, and the gallery
   renders through this same bundle, so deleting these rules would leave that example unstyled. They
   are kept deliberately. No page calls them. */

.hm-work { list-style: none; margin: var(--s6) 0 0; padding: 0; display: grid; gap: var(--s2); }
.hm-work-link {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  align-items: center; gap: var(--s4);
  padding: var(--s4) var(--s5);
  border: 1px solid var(--rule);
  border-radius: var(--r-2);
  background: var(--white);
  text-decoration: none; color: var(--ink);
  transition: border-color 160ms ease, background 160ms ease;
}
.hm-work-link:hover { border-color: var(--teal-dark); background: var(--paper-alt); }
.hm-work-n { font-family: var(--mono); font-size: 14px; color: var(--ink-2); }
.hm-work-body { display: grid; gap: 2px; min-width: 0; }
.hm-work-title { font-weight: 600; }
.hm-work-q { color: var(--ink-2); }
.hm-work-stages { display: flex; gap: var(--s2); }
.hm-work-stage {
  padding: 3px 10px; border-radius: var(--pill);
  border: 1px solid var(--rule); color: var(--ink-2);
  font-size: 14px; white-space: nowrap;
}
.hm-work-go { width: 16px; height: 16px; color: var(--ink-2); }
.hm-work-link:hover .hm-work-go { color: var(--teal-dark); }
@media (max-width: 860px) {
  .hm-work-link { grid-template-columns: auto minmax(0, 1fr) auto; }
  .hm-work-stages { display: none; }
}

/* THE FOOTER READING KEY, CLOSED BY DEFAULT. It is the shared `.drawer` disclosure, so it inherits
   that component's summary row, triangle and open state, and only the footer specific spacing is
   stated here. The legend inside keeps every label and every definition it had. */
.site-foot .foot-legend.drawer { margin-block: var(--s5); }
.site-foot .foot-legend.drawer > summary { color: var(--ink-2); font-size: var(--t-small); }
.site-foot .foot-legend.drawer[open] > summary { color: var(--ink); }
.site-foot .foot-legend.drawer > .body { display: grid; gap: var(--s5); padding-top: var(--s4); }

/* ---- src/parts/hme.css ---- */
/* The home page, apps/site/src/views/home.ejs, and its one instrument, packages/ui/partials/hme-meet.ejs.
 *
 * THE TREATMENTS ARE components/diagram-section.tsx's from the reference build: the hub, the lit
 * card, the pedestal, the glowing connector with a filled arrowhead, the ambient pool and the ringed
 * benefits row. The shared parts come from rw.css by class. This file places them.
 *
 * IDENTITY HUES, AND NO STATE COLOUR. Each party carries its hue in `--hue` on its own element. The
 * figure is the product's design rather than a reading of this estate, so --ok, --att and --no
 * appear nowhere in this file.
 */

/* ---- THE PAGE ---- */
.hme-page { --page-max: 1472px; }
.hme-eyebrow {
  margin: 0; font-size: 14px; font-weight: 600; letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--teal-dark);
}
.hme-band { position: relative; }
.hme-band-head { display: grid; gap: var(--s3); margin-bottom: var(--s6); max-width: 60rem; }
.hme-band-head > * { margin: 0; }
.hme-h2 { letter-spacing: -0.03em; line-height: 1.08; text-wrap: balance; }

/* ---- THE HERO ----
   ABOVE 1360 THE COPY SITS BESIDE THE INSTRUMENT, which is how the reference draws its hero. Below
   that the copy goes on top and the instrument takes the full measure: at 1280 beside the copy the
   figure would get 728px, which is under the 760 its own wide layout needs. CLAUDE.md rule 5: match
   the proportion, not the absolute pixels. */
/* THE PADDING IS SPENT FOR THE FOLD. At 1440 by 900 the ecosystems strip has to end inside the
   window, and with the pause control under the figure it ended at 930 on the larger padding. */
.hme-top { position: relative; padding-block: var(--s6) var(--s5); display: grid; gap: var(--s6); }
@media (min-width: 1360px) {
  .hme-top { grid-template-columns: minmax(0, 440px) minmax(0, 1fr); gap: var(--s7, 4rem); align-items: center; }
}
.hme-top-copy { display: grid; align-content: start; }
.hme-top-copy > * { margin: 0; }
.hme-headline { margin-top: var(--s4); line-height: 1.02; letter-spacing: -0.035em; max-width: 12ch; text-wrap: balance; }
.hme-headline .accent { display: block; }
.hme-lead { margin-top: 1.25rem; max-width: 34rem; font-size: 17px; line-height: 1.55; color: var(--ink-lead); }
.hme-actions { margin-top: var(--s6); display: flex; flex-wrap: wrap; gap: var(--s4); }
/* BETWEEN 1000 AND 1360 THE COPY TAKES TWO COLUMNS OVER THE INSTRUMENT: the headline on the left, the
   lead and the actions on the right, so the band does not open on a narrow column and an empty half. */
@media (min-width: 1000px) and (max-width: 1359px) {
  .hme-top-copy { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: var(--s7, 4rem); grid-template-areas: "eyebrow eyebrow" "head lead" "head actions"; }
  .hme-top-copy .hme-eyebrow { grid-area: eyebrow; }
  .hme-headline { grid-area: head; }
  .hme-lead { grid-area: lead; margin-top: var(--s4); }
  .hme-actions { grid-area: actions; }
}
.hme-top-figure { min-width: 0; }
@media (max-width: 1359px) {
  .hme-top-figure { width: 100%; max-width: 1000px; margin-inline: auto; }
}

/* ---- THE ECOSYSTEMS STRIP, directly under the hero, so the first screen carries the proof ---- */
.hme-marks {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s4) var(--s7, 4rem);
  padding-block: var(--s5); border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule);
}
.hme-marks-h { margin: 0; max-width: 12rem; font-family: inherit; font-size: 14px; font-weight: 600; line-height: 1.4; letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink-2); }
.hme-marks-row { list-style: none; margin: 0; padding: 0; flex: 1; display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--s4) var(--s6); }
.hme-mark { display: flex; align-items: center; gap: var(--s3); }
.hme-mark-dot {
  flex: none; width: 10px; height: 10px; border-radius: 50%;
  background: var(--hue); box-shadow: 0 0 12px var(--hue);
}
.hme-mark-n { display: block; font-size: 18px; font-weight: 700; line-height: 1.2; color: var(--ink); }
.hme-mark-s { display: block; font-size: 14px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-2); }
/* FIVE NAMES, FIVE HUES: the four environment hues and the brand. With four hues cycling, the first
   and the fifth name were both blue and read as one family. */
.hme-mark:nth-child(5n + 1) { --hue: var(--d-blue); }
.hme-mark:nth-child(5n + 2) { --hue: var(--d-violet); }
.hme-mark:nth-child(5n + 3) { --hue: var(--d-magenta); }
.hme-mark:nth-child(5n + 4) { --hue: var(--d-sand); }
.hme-mark:nth-child(5n + 5) { --hue: var(--teal-dark); }
/* UNDER 700 THE LABEL GOES ON TOP AND THE NAMES TAKE TWO COLUMNS UNDER IT. Beside the label the row
   was left 110px at 390, each name got 39, and "Open Banking" ran 56px past the edge of the page. */
@media (max-width: 700px) {
  .hme-marks { display: grid; }
  .hme-marks-h { max-width: none; }
  .hme-marks-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ---- THE OUTCOME ROW, the reference's benefits row: ringed 52px glyphs, hairlines between ---- */
.hme-outcomes {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
}
.hme-outcomes li { display: flex; flex-direction: column; align-items: center; text-align: center; padding: 0 var(--s4); }
.hme-outcomes li + li { border-left: 1px solid var(--hairline); }
.hme-outcome-i { width: 52px; height: 52px; }
.hme-outcome-i svg { width: 26px; height: 26px; }
.hme-outcome-t { margin: var(--s4) 0 0; font-size: 18px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.hme-outcome-l { margin: var(--s2) 0 0; max-width: 19rem; text-wrap: balance; font-size: 15px; line-height: 1.5; color: var(--ink-2); }
.hme-payoff { margin: 0 0 var(--s6); text-align: center; font-family: inherit; line-height: 1.4; }
@media (max-width: 900px) {
  .hme-outcomes { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: var(--s6); }
  .hme-outcomes li + li { border-left: 0; }
  .hme-outcomes li:nth-child(even) { border-left: 1px solid var(--hairline); }
}
@media (max-width: 480px) {
  .hme-outcomes { grid-template-columns: minmax(0, 1fr); }
  .hme-outcomes li:nth-child(even) { border-left: 0; }
}

/* ---- THE PROOF BAND. The figures and the note are credibility.ejs's; this places the standards
   beside them. The figure row carries its own rule in ui.css, which this band does not need. ---- */
.hme-proof { display: grid; gap: var(--s7, 4rem); }
@media (min-width: 1100px) { .hme-proof { grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); align-items: start; } }
.hme-proof .credibility { margin-top: 0; padding-top: 0; border-top: 0; }
/* FOUR FIGURES ON ONE ROW WHERE THEY FIT. At 40px in a flex row "Thousands" wrapped alone onto a
   second line at 1440, which read as a fifth, lesser figure. A grid keeps the four as peers. */
.hme-proof .credibility-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--s5); }
/* 34px AT MOST, 28px AT THE NARROWEST. At 390 "Thousands" at 34px ended on the page's right edge. */
.hme-proof .credibility .fig .value { font-size: clamp(28px, 7vw, 34px); letter-spacing: -0.02em; }
.hme-std { border-left: 1px solid var(--hairline); padding-left: var(--s6); display: grid; gap: var(--s4); align-content: start; }
.hme-std > p { margin: 0; }
.hme-std-h { font-size: 14px; font-weight: 600; letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink-2); }
.hme-std-l { font-size: 15px; line-height: 1.5; color: var(--ink-2); }
@media (max-width: 1099px) { .hme-std { border-left: 0; padding-left: 0; border-top: 1px solid var(--hairline); padding-top: var(--s5); } }

/* ---- THE USE CASES. One card, the same drawing every time: a title, a line and the pedestal. ---- */
.hme-uc-head { display: flex; flex-wrap: wrap; align-items: end; justify-content: space-between; gap: var(--s4); margin-bottom: var(--s6); }
.hme-uc-head > div { display: grid; gap: var(--s3); }
.hme-uc-head > div > * { margin: 0; }
/* THE ROW BREAKS ON THE WIDTH THE TITLE NEEDS. The hungriest headline, "When something changes.
   Access adapts.", measures 259 at 21px bold as its best two line split, and a card spends 44 on its
   padding and 44 on the arrow's corner, so a column needs about 350. Three columns reach that at
   1190 and two at 810. */
.hme-uc-grid { display: grid; gap: 20px; grid-template-columns: minmax(0, 1fr); }
@media (min-width: 810px) { .hme-uc-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1190px) { .hme-uc-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.hme-uc {
  position: relative; display: flex; flex-direction: column; overflow: hidden;
  padding: var(--s5) 22px 0; border-radius: 16px; text-decoration: none; color: inherit;
  border: 1px solid color-mix(in srgb, var(--hue) 22%, transparent);
  border-top-color: color-mix(in srgb, var(--hue) 45%, transparent);
  background: radial-gradient(120% 100% at 15% 0%, color-mix(in srgb, var(--hue) 13%, transparent), transparent 55%), var(--paper-alt);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--hue) 35%, transparent);
  transition: border-color 140ms ease;
}
.hme-uc:hover { border-color: color-mix(in srgb, var(--hue) 55%, transparent); }
.hme-uc:focus-visible { outline: 2px solid var(--brand-strong); outline-offset: 3px; }
/* TWO LINES, ALWAYS, so six statements start on one baseline across a row. The right padding is the
   arrow's corner, so a two line title cannot run under it. */
.hme-uc-t { margin: 0; min-height: 49px; padding-right: 44px; font-size: 21px; font-weight: 700; line-height: 1.15; color: var(--ink); text-wrap: balance; }
.hme-uc-l { margin: var(--s2) 0 0; font-size: 15px; line-height: 1.5; color: var(--ink-2); }
.hme-uc-fig { margin-top: auto; padding-top: var(--s5); }
.hme-uc-go {
  position: absolute; right: 22px; top: var(--s5);
  display: flex; align-items: center; justify-content: center; width: 36px; height: 36px; border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--hue) 55%, transparent); color: var(--hue);
  transition: transform 140ms ease;
}
.hme-uc:hover .hme-uc-go { transform: translateX(2px); }
.hme-uc-go svg { width: 16px; height: 16px; display: block; }
/* THE WIDE CARD, the one use case that goes the other way. Copy on the left, the pedestal on the
   right, and the eyebrow says why it stands apart. */
.hme-uc-wide { margin-top: 20px; display: grid; grid-template-columns: minmax(0, 1fr) 220px; align-items: end; column-gap: var(--s6); padding-bottom: var(--s5); }
.hme-uc-wide .hme-uc-fig { margin-top: 0; padding-top: 0; }
.hme-uc-e { margin: 0 0 var(--s2); font-size: 14px; font-weight: 600; letter-spacing: 0.18em; text-transform: uppercase; color: var(--hue); }
@media (max-width: 640px) {
  .hme-uc-wide { grid-template-columns: minmax(0, 1fr); padding-bottom: 0; }
  .hme-uc-wide .hme-uc-fig { padding-top: var(--s5); }
}

/* ---- THE FILM ---- */
.hme-film { display: grid; gap: var(--s6); }
@media (min-width: 1100px) { .hme-film { grid-template-columns: minmax(0, 360px) minmax(0, 1fr); align-items: center; } }
.hme-film-copy { display: grid; gap: var(--s3); align-content: start; }
.hme-film-copy > * { margin: 0; }
.hme-film-frame { overflow: hidden; border-radius: 16px; border: 1px solid var(--hairline); background: var(--paper-alt); }
.hme-film-frame .player { margin: 0; }
.hme-film-frame video { display: block; width: 100%; height: auto; }

/* ---- THE INSTRUMENT ----
   A size container, so the layout follows the figure's own width rather than the viewport: the same
   partial stands beside the copy at 1440 and takes the full row at 1100. */
.hme { position: relative; margin: 0; container-type: inline-size; min-width: 0; }
.hme-glow { top: 30%; }
.hme-foot { position: relative; margin-top: var(--s4); display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: var(--s3) var(--s5); font-size: 15px; }
.hme-pause {
  min-height: 32px; padding: 0 var(--s4); border-radius: var(--pill, 999px);
  border: 1px solid var(--hairline); background: transparent; color: var(--ink-2);
  font: inherit; font-size: 14px; font-weight: 600; cursor: pointer;
}
.hme-pause:hover { color: var(--ink); border-color: var(--teal-dark); }
.hme-pause:focus-visible { outline: 2px solid var(--brand-strong); outline-offset: 3px; }
.hme[data-paused="yes"] .hme-ar-dot { animation-play-state: paused; }

/* THE NARROW LAYOUT FIRST. It reads top to bottom in the order of the steps. The first column is the
   rail connector 4 runs down, from your platform past the record to the decision, so the decision
   visibly leaves your platform and never the record. The markup is in the same order. */
.hme-grid {
  position: relative;
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr);
  grid-template-rows: auto 72px auto 96px auto 56px auto;
  grid-template-areas: "agent agent" "ask ask" "plat plat" "decide v" "decide hub" "decide ." "dec dec";
}
.hme-agent { grid-area: agent; }
.hme-ar-ask { grid-area: ask; }
.hme-plat { grid-area: plat; }
.hme-v { grid-area: v; position: relative; }
/* TWO CLASSES, because rw.css sorts after this file and sets `text-align: center` on .rw-hub. */
.rw-hub.hme-hub { grid-area: hub; text-align: left; padding: var(--s5); }
.hme-ar-decide { grid-area: decide; }
.hme-dec { grid-area: dec; }

@container (min-width: 760px) {
  .hme-grid {
    grid-template-columns: minmax(0, 1fr) 104px minmax(0, 1.2fr) 104px minmax(0, 1fr);
    grid-template-rows: auto 104px auto;
    grid-template-areas: ". hub hub hub ." ". . v . ." "agent ask plat decide dec";
  }
}

/* THE HUB. The chain's end: its name, what it is, and the three answers it carries. */
.hme-hub > p { margin: 0; }
.hme-hub-t { display: flex; align-items: center; gap: var(--s3); font-size: 18px; font-weight: 700; color: var(--ink); }
.hme-hub-mark { width: auto; height: 22px; display: block; }
.hme-hub-l { margin-top: var(--s1, 4px) !important; font-size: 14px; color: var(--ink-2); }
.hme-rows { list-style: none; margin: var(--s4) 0 0; padding: 0; display: grid; gap: var(--s3); }
/* NARROW: the glyph beside the question, the answer under the question. */
.hme-rows li {
  display: grid; grid-template-columns: 28px minmax(0, 1fr); grid-template-areas: "i q" ". a";
  column-gap: var(--s3); row-gap: 2px; align-items: start;
  padding-top: var(--s3); border-top: 1px solid var(--hairline);
}
.hme-row-i { grid-area: i; }
.hme-row-q { grid-area: q; }
.hme-row-a { grid-area: a; }
.hme-row-i, .hme-card-i { display: inline-flex; color: var(--hue); }
/* THE GLYPH IS 24, AND ITS WRAPPER IS HELD TO 24 TOO. uc-glyph draws a 36px box by default, which sat
   in the 28px track and spilled 8px into the gap at every width. */
.hme-row-i .sc-glyph { width: 24px; height: 24px; }
.hme-row-i svg { width: 24px; height: 24px; display: block; filter: drop-shadow(0 0 6px var(--hue)); }
.hme-row-q { display: block; font-size: 15px; font-weight: 700; color: var(--ink); }
.hme-row-a { display: block; font-size: 14px; line-height: 1.45; color: var(--ink-2); }
/* WIDE: three columns sharing three row tracks through a subgrid, so the glyphs, the questions and the
   answers each sit on one line across the three, whether or not a question wraps. Measured before
   this: "Who stands behind it?" took two lines at 1024 and 1440 and its answer started a line lower
   than its neighbours'. */
@container (min-width: 760px) {
  .hme-rows { grid-template-columns: repeat(3, minmax(0, 1fr)); grid-template-rows: auto auto auto; column-gap: var(--s4); row-gap: 0; }
  .hme-rows li { grid-row: span 3; grid-template-columns: minmax(0, 1fr); grid-template-rows: subgrid; grid-template-areas: "i" "q" "a"; row-gap: var(--s2); }
}

/* THE THREE CARDS. The environment card, lit from above in the party's hue. */
.hme-card { display: flex; flex-direction: column; gap: var(--s2); min-width: 0; }
.hme-card > p { margin: 0; }
.hme-card-t { display: flex; align-items: center; gap: var(--s2); font-size: 16px; font-weight: 700; color: var(--ink); }
.hme-card-i .sc-glyph, .hme-card-i svg { width: 22px; height: 22px; display: block; }
.hme-card-l { font-size: 14px; line-height: 1.45; color: var(--ink-2); }
.hme-agent { align-items: center; text-align: center; }
.hme-agent .rw-ped { margin-top: calc(-1 * var(--s2)); }
/* THE EMPTY SLOT. Your platform's record for this agent, drawn as a dashed row holding the value. */
.hme-hold {
  margin-top: var(--s2) !important;
  display: grid; gap: 2px; padding: var(--s2) var(--s3); border-radius: 8px;
  border: 1px dashed color-mix(in srgb, var(--hue) 55%, transparent);
}
.hme-hold-k { font-size: 14px; color: var(--ink-2); }
.hme-hold-v { font-size: 15px; font-weight: 700; color: var(--ink); }
.hme-dec-q { font-size: 14px; font-weight: 600; color: var(--hue); }

/* THE CONNECTORS. A lit line, a filled arrowhead, a number and a word. The line glows in the brand,
   as every connector in the reference does. Each connector is drawn in one of four directions, and
   the direction is a class the layout sets below rather than a property of the step. */
.hme-ar { position: relative; min-height: 40px; }
.hme-ar-line {
  position: absolute; border-radius: 2px; background: var(--teal-dark);
  box-shadow: 0 0 8px color-mix(in srgb, var(--teal-dark) 70%, transparent);
}
.hme-ar-line::after { content: ""; position: absolute; width: 0; height: 0; border-style: solid; border-color: transparent; }
.hme-ar-dot {
  position: absolute; left: -3px; top: -3px; width: 8px; height: 8px; border-radius: 50%; opacity: 0;
  background: var(--brand-strong); box-shadow: 0 0 10px var(--brand-strong);
}
.hme-ar-l {
  position: absolute; margin: 0; display: inline-flex; align-items: center; gap: 6px;
  font-size: 14px; font-weight: 600; line-height: 1.25; color: var(--ink);
}
.hme-ar-n {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 22px; height: 22px; border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--teal-dark) 60%, transparent);
  background: var(--paper); color: var(--brand-strong); font-size: 14px; font-weight: 700;
}

/* NARROW. Every connector runs down the page except connector 3, which runs back up.
   1 down the middle of its row, the word to its right.
   2 and 3 side by side in the column beside the rail, 2 down to the record and 3 up from it, each
     word to the right of its line. The words may take two lines: at 320 "3 Signed answer" on one
     line ran past the figure's edge.
   4 down the rail, the word beside its head, in the empty row above the decision. */
.hme-ar-ask .hme-ar-line { left: calc(50% - 1px); width: 2px; top: 10px; bottom: 10px; }
.hme-ar-ask .hme-ar-l { left: calc(50% + 12px); top: 50%; transform: translateY(-50%); }
.hme-v .hme-ar { position: absolute; top: 0; bottom: 0; width: 50%; }
.hme-ar-resolve { left: 0; }
.hme-ar-answer { left: 50%; }
.hme-v .hme-ar-line { left: 24px; width: 2px; top: 10px; bottom: 10px; }
.hme-v .hme-ar-l { left: 38px; right: 4px; top: 50%; transform: translateY(-50%); }
.hme-ar-decide .hme-ar-line { left: calc(50% - 1px); width: 2px; top: -6px; bottom: 10px; }
.hme-ar-decide .hme-ar-l { left: 32px; bottom: 12px; white-space: nowrap; }
/* The heads. Down for 1, 2 and 4; up for 3. */
.hme-ar-ask .hme-ar-line::after,
.hme-ar-resolve .hme-ar-line::after,
.hme-ar-decide .hme-ar-line::after { left: -5px; bottom: -8px; border-width: 9px 6px 0; border-top-color: var(--brand-strong); }
.hme-ar-answer .hme-ar-line::after { left: -5px; top: -8px; border-width: 0 6px 9px; border-bottom-color: var(--brand-strong); }

/* WIDE. The record sits above your platform, so 2 runs up and 3 runs down; 1 and 4 run left to right
   between the cards, the word over the line. */
@container (min-width: 760px) {
  .hme-v .hme-ar { width: auto; }
  .hme-ar-resolve { left: 0; right: 50%; }
  .hme-ar-answer { left: 50%; right: 0; }
  .hme-v .hme-ar-line { left: calc(50% - 1px); }
  .hme-ar-resolve .hme-ar-l { left: auto; right: calc(50% + 12px); white-space: nowrap; }
  .hme-ar-answer .hme-ar-l { left: calc(50% + 12px); right: auto; white-space: nowrap; }
  .hme-ar-resolve .hme-ar-line::after { top: -8px; bottom: auto; border-width: 0 6px 9px; border-color: transparent; border-bottom-color: var(--brand-strong); }
  .hme-ar-answer .hme-ar-line::after { top: auto; bottom: -8px; border-width: 9px 6px 0; border-color: transparent; border-top-color: var(--brand-strong); }
  .hme-ar-ask, .hme-ar-decide { align-self: center; height: 72px; }
  .hme-ar-ask .hme-ar-line, .hme-ar-decide .hme-ar-line { left: 10px; right: 12px; width: auto; top: auto; bottom: 18px; height: 2px; }
  .hme-ar-ask .hme-ar-line::after, .hme-ar-decide .hme-ar-line::after { left: auto; top: -5px; bottom: auto; right: -8px; border-width: 6px 0 6px 9px; border-color: transparent; border-left-color: var(--brand-strong); }
  .hme-ar-ask .hme-ar-l, .hme-ar-decide .hme-ar-l { left: 0; right: 0; top: 4px; bottom: auto; transform: none; justify-content: center; white-space: nowrap; }
}

/* THE LIGHT THAT TRAVELS. Eight seconds, one connector in each quarter, in the order they happen. It
   runs only where motion is allowed, and the pause control holds it. */
@media (prefers-reduced-motion: no-preference) {
  .hme-ar-ask .hme-ar-dot { animation: hme-run-down 8s linear infinite 0s; }
  .hme-ar-resolve .hme-ar-dot { animation: hme-run-down 8s linear infinite 2s; }
  .hme-ar-answer .hme-ar-dot { animation: hme-run-up 8s linear infinite 4s; }
  .hme-ar-decide .hme-ar-dot { animation: hme-run-down 8s linear infinite 6s; }
  @container (min-width: 760px) {
    .hme-ar-ask .hme-ar-dot, .hme-ar-decide .hme-ar-dot { animation-name: hme-run-x; }
    .hme-ar-resolve .hme-ar-dot { animation-name: hme-run-up; }
    .hme-ar-answer .hme-ar-dot { animation-name: hme-run-down; }
  }
}
@keyframes hme-run-up {
  0% { top: calc(100% - 5px); opacity: 0; }
  3% { opacity: 1; }
  22% { top: -3px; opacity: 1; }
  25%, 100% { top: -3px; opacity: 0; }
}
@keyframes hme-run-down {
  0% { top: -3px; opacity: 0; }
  3% { opacity: 1; }
  22% { top: calc(100% - 5px); opacity: 1; }
  25%, 100% { top: calc(100% - 5px); opacity: 0; }
}
@keyframes hme-run-x {
  0% { left: -3px; top: -3px; opacity: 0; }
  3% { opacity: 1; }
  22% { left: calc(100% - 5px); top: -3px; opacity: 1; }
  25%, 100% { left: calc(100% - 5px); top: -3px; opacity: 0; }
}

/* ---- src/parts/how-it-works.css ---- */
/* /how-it-works: the three step figure, the consumer table and the closing band.
 *
 * WHAT IS IN THIS FILE. Two things, and the second is the reason the file is named for a route
 * rather than for a component. `.platform-steps` styles partials/platform-steps.ejs, which is a
 * component and could stand on its own. `.hiw-` styles the two page level blocks of
 * apps/site/src/views/platform-needs.ejs: the consumer table and the closing question. Splitting
 * them into two parts would give one route two owners for no gain, and this route has one.
 *
 * WHY THIS IS A PART AND NOT AN EDIT TO src/ui.css OR apps/site/src/public/site.css. Six people are
 * shaping different figures in this tree at the same time, and two writers on one stylesheet lose
 * an edit silently: the build succeeds and the page renders with the old treatment. Nothing here
 * touches a class another view draws. `.site-table` stays exactly as site.css declares it; the
 * table rules below are all scoped under `.hiw-consumers`, which only this route writes.
 *
 * THE CASCADE, which decides whether the table rules land at all. The page loads /ui.css and then
 * /site.css, so a `.site-table td` rule in site.css beats a `.site-table td` rule here whatever
 * this file does. Every table rule below therefore carries `.hiw-consumers` in front of it, one
 * class more than site.css states, so it wins on specificity rather than on order.
 *
 * COLOUR. var(--teal) appears nowhere in this file. It fills a Raidiam product marker and nothing
 * else, and the plane in this figure is the CUSTOMER'S authorisation server. The rings take
 * var(--teal-dark), which is this site's action and diagram colour and is what the capability flow
 * rail already gives to stages owned by four different parties. No green appears anywhere: green
 * means observed or proven, and this page draws a mechanism rather than a measurement.
 *
 * CONTRAST. Every ground here is a plain token, so every pair is one packages/ui/tools/contrast.mjs
 * already gates by name. Computed from the token values on 2026-09-12:
 *   d-ink      on d-card       13.79   a step name and a feature value
 *   d-ink-2    on d-card        5.48   the sentence under a step name, and a row label
 *   d-accent   on d-card        8.65   the step numeral
 *   d-ink      on d-surface    14.97   a table cell on the plane ground
 *   d-ink-2    on d-surface     5.95   the plane label and the note under the steps
 *   d-accent   on d-wash-teal   7.60   the glyph inside its ring
 *   d-ink      on d-wash-teal  12.11   a table row under the pointer
 *   d-rule     on d-card        3.08   a card edge
 *   d-rule     on d-surface     3.34   the plane edge and a table rule
 * The last two are component boundaries, so their floor is the 3 to 1 of WCAG 1.4.11 rather
 * than 4.5.
 */

/* ==========================================================================
   THE FIGURE: partials/platform-steps.ejs
   ========================================================================== */

/* No card of its own. `.figure` paints a card ground and a card edge, and with it the page carried
   three greys stacked: page, figure card, plane. The plane is the object, so the figure is
   transparent and the plane sits on the band.
 *
 * ONE CLASS IS ENOUGH, AND FOR TWO DAYS IT WAS NOT. Recorded because the workaround was on its way
 * to becoming folklore. The card rule, `.panel, .figure, .hero-panel, .term-strip, .rail .stage,
 * .resolve-seq .step { border-radius; border: 1px solid var(--rule); box-shadow }`, used to live in
 * apps/site/src/public/site.css, which the page loads AFTER /ui.css. Every part is concatenated
 * inside ui.css, so a one class rule in a part lost the tie on ORDER rather than on specificity, to
 * a file part authors are told not to touch. Writing `border: 0` here changed nothing: measured, the
 * element still computed 1px of --rule, a 14px radius and the shadow. The first render of this
 * figure drew a second rounded box around the plane and the caption because of it.
 *
 * The rule now sits in packages/ui/src/ui.css ahead of the parts, so a part overrides it the
 * ordinary way. `.platform-steps` is one class and it takes effect. Nothing here needs a second
 * class, and a part that carries one should lose it rather than copy it. */
.platform-steps { background: transparent; padding: 0; display: block; border: 0; border-radius: 0; box-shadow: none; }
.platform-steps .figure-caption { max-width: var(--measure-notes); }

/* ---- the plane: the customer's own authorisation server ---- */

.platform-steps .ps-plane {
  background: var(--paper-alt);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
  padding: var(--s5);
}
.platform-steps .ps-plane-head {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between;
  gap: var(--s2) var(--s5);
  margin-bottom: var(--s5);
}
.platform-steps .ps-plane-label {
  margin: 0;
  font-size: var(--t-label); font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--ink-2);
}
/* What the platform keeps in its own configuration. It sits in the plane's own header rather than
   outside it, because that is the whole point: the anchor is the platform's, not a thing it asks
   for. */
/* Aligned to the FIRST LINE rather than centred. Wide it is one line and the two read the same;
   at 390 it wraps to three, and centred the anchor glyph sat beside the second line with the
   sentence apparently indented around it. */
.platform-steps .ps-holds {
  margin: 0;
  display: flex; align-items: start; gap: var(--s2);
  font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-2);
}
.platform-steps .ps-holds-icon { display: block; width: 18px; height: 18px; margin-top: 2px; flex: none; color: var(--teal-dark); }
.platform-steps .ps-holds-icon svg { width: 100%; height: 100%; display: block; }

/* ---- the three steps ---- */

/* FOUR ROWS, SHARED BY ALL THREE STEPS, so the ring, the step name, the sentence and the two
   labelled rows line up across the figure whatever length each one runs to. Without this each card
   is its own grid: step three's sentence is one line where the others take two, so its THE FEATURE
   label sat 23 pixels above its neighbours and the figure read as three unrelated cards. The idiom
   is the capability flow rail's, in src/parts/rail.css.

   The row gap is the PARENT'S, because that is what a subgrid track gap is, so the internal rhythm
   of a card and the rhythm between two rows of cards are the same number here. The column gap is
   the wider one, and it is also the box the arrow is drawn in. */
.platform-steps .ps-steps {
  list-style: none; margin: 0; padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  grid-template-rows: auto auto auto auto;
  column-gap: var(--s5); row-gap: var(--s3);
}
.platform-steps .ps-step {
  position: relative;
  min-width: 0;
  display: grid;
  grid-row: span 4;
  grid-template-rows: subgrid;
  align-content: start;
  padding: var(--s5) var(--s4);
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
  /* The house card lift. ui.css gives it to .panel, .figure, .hero-panel, .term-strip,
     .rail .stage and .resolve-seq .step by name, and a card that sits on the page without it reads
     as a drawn outline rather than as an object. --shadow-lift is a token, so this is the same
     shadow those six carry rather than a second one that looks like it. */
  box-shadow: var(--shadow-lift);
  transition: border-color var(--m-drawer) ease, transform var(--m-drawer) ease;
}
.platform-steps .ps-step:hover { border-color: var(--teal-dark); transform: translateY(-2px); }

.platform-steps .ps-step-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); }

/* The ring. The inner wash lifts the disc off the card and the outer glow is what makes a flat
   outline read as a lit object rather than a drawn one. Both are mixed from a token; a mix is
   allowed in a border, a shadow and a gradient, where no text lands, and is refused in a flat
   background, which is the fill the contrast gate has to be able to name. */
.platform-steps .ps-disc {
  width: 60px; height: 60px; flex: none;
  display: grid; place-items: center;
  border-radius: var(--pill);
  border: 1.5px solid color-mix(in srgb, var(--teal-dark) 80%, transparent);
  background: var(--wash-teal);
  box-shadow: 0 0 0 6px color-mix(in srgb, var(--teal-dark) 8%, transparent), 0 0 24px color-mix(in srgb, var(--teal-dark) 26%, transparent);
  color: var(--teal-dark);
}
.platform-steps .ps-disc svg { width: 28px; height: 28px; display: block; }

/* The step index. Two digits, tabular, so 01 02 03 sit on one rhythm. */
.platform-steps .ps-n {
  font-size: var(--t-h3); line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--teal-dark);
}

.platform-steps .ps-name { margin: 0; font-size: var(--t-h3); line-height: var(--t-h3-line); color: var(--ink); }
.platform-steps .ps-does { margin: 0; font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-2); }

/* The two rows of the step: what feature it uses and where it reads it. A label above its value
   rather than beside it, so a long value keeps the full column width. */
.platform-steps .ps-meta {
  margin: 0; padding-top: var(--s3);
  border-top: 1px solid var(--rule);
  display: grid; gap: var(--s4); align-content: start;
}
.platform-steps .ps-row { display: grid; gap: 6px; }
.platform-steps .ps-row dt {
  font-size: var(--t-label); font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--ink-2);
}
.platform-steps .ps-row dd { margin: 0; font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink); }
.platform-steps .ps-row dd code { font-size: var(--t-label); overflow-wrap: anywhere; }

/* The arrow between two steps, drawn in the gap rather than inside either card, so it never moves
   when a step's text changes length. The gap is one --s5 and so is the arrow's box. The idiom and
   the mask are the capability flow rail's, in src/parts/rail.css.

   The token flat, softened with opacity rather than a colour-mix: the stylesheet test refuses a
   colour-mix in a background, because the contrast gate enumerates token pairs by name and cannot
   see a mix at all. */
.platform-steps .ps-step::after {
  content: "";
  position: absolute; top: 50%; left: 100%;
  width: var(--s5); height: 10px;
  transform: translateY(-50%);
  background: var(--teal-dark);
  opacity: 0.8;
  -webkit-mask: var(--arrow-right) center / 15px 10px no-repeat;
  mask: var(--arrow-right) center / 15px 10px no-repeat;
  animation: ps-step-arrow 3.2s ease-in-out infinite;
}
.platform-steps .ps-step:last-child::after { content: none; }
.platform-steps .ps-step:nth-child(2)::after { animation-delay: 0.4s; }

/* The two arrows brighten in sequence, so the row reads as an order rather than as two static
   glyphs. It is the only motion in the figure and the reduced motion block at the foot of this
   file removes it outright. */
@keyframes ps-step-arrow {
  0%, 100% { opacity: 0.55; }
  35% { opacity: 1; }
}

/* Where the decision happens. The sentence sits INSIDE the plane, under the steps, in the same
   place and for the same reason /architecture puts its note inside the infrastructure band. */
.platform-steps .ps-note {
  margin: var(--s5) 0 0; padding-top: var(--s4);
  border-top: 1px solid var(--rule);
  font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-2);
  max-width: var(--measure-notes);
}

/* ---- narrow ----

   THREE IN A ROW IS WHAT BREAKS A PHONE, so the row becomes a column rather than a scroller: a
   scrolling row hides two of the three steps behind a gesture, and the three steps are the page's
   argument. The arrow turns with the row, from the gap on the right to the gap underneath. */
@media (max-width: 980px) {
  /* The subgrid goes with the row. One card per row has nothing to line up with, and a shared row
     track would make the gap BETWEEN two cards the same --s3 as the gap inside one, which reads as
     one long card. So each card becomes its own column box again and the list takes the wide gap. */
  .platform-steps .ps-steps { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; row-gap: var(--s6); }
  .platform-steps .ps-step { grid-row: auto; grid-template-rows: none; gap: var(--s3); }
  .platform-steps .ps-step::after {
    top: 100%; left: 50%;
    width: var(--s6); height: 10px;
    transform: translate(-50%, -50%) rotate(90deg);
  }
}
@media (max-width: 560px) {
  .platform-steps .ps-plane { padding: var(--s4); }
  .platform-steps .ps-step { padding: var(--s4); }
  .platform-steps .ps-disc { width: 52px; height: 52px; }
  .platform-steps .ps-disc svg { width: 24px; height: 24px; }
}

/* ==========================================================================
   THE FLOW: partials/platform-flow.ejs
   ========================================================================== */

/* TWO AXES IN ONE GRID, and the grid is the argument.
 *
 * ACROSS row 4 is the request path: the agent, the platform, the resource, with a labelled arrow in
 * the gap between each pair. DOWN column 3 is the signed material: who published it, what it is,
 * and the sentence saying the platform read it for itself. Column 3 is the platform's column, so
 * the vertical run lands on the platform and on nothing else.
 *
 * THE PLACEMENT IS EXPLICIT, every element by column and row, rather than by source order. The
 * markup order is the order a screen reader gets and it is deliberately NOT the painted order: the
 * three parties come first because they are the sentence, and the published material follows. If
 * these placements were left to flow, changing the reading order would move the picture.
 *
 * data-pos PLACES A PARTY, not its glyph id. A content file that changed an icon would otherwise
 * move a card across the figure.
 *
 * WHY NOTHING SITS IN THE GAP BETWEEN THE AGENT AND THE PLATFORM except an arrow and two words. A
 * box there is a gateway, and the page says the platform keeps its own request path. The chain is
 * above the platform rather than in front of it, because that is where it is: already published,
 * already read, held until it expires. partials/platform-flow.ejs carries the same ruling at more
 * length.
 *
 * CONTRAST. Every ground here is a plain token, so every pair is one packages/ui/tools/contrast.mjs
 * gates by name. Read off that tool's own output on 2026-09-12, dark side:
 *   d-ink        on d-card      13.79   a party name
 *   d-ink-2      on d-card       5.48   the line under a party name
 *   d-ink        on d-surface   14.97   a chain item, on the figure ground
 *   d-ink-2      on d-surface    5.95   the link labels and the boundary label
 *   d-accent     on d-surface    9.39   the publisher name and the chain label
 *   d-ground     on d-accent    10.00   nothing here, and it is why the product dot carries no text
 *   d-rule       on d-surface    3.34   the chain panel edge and the boundary rule
 *   d-rule       on d-card       3.08   a party card edge
 * The last two are component boundaries, so their floor is the 3 to 1 of WCAG 1.4.11.
 */
.platform-flow { background: transparent; padding: 0; display: block; border: 0; border-radius: 0; box-shadow: none; }
.platform-flow .figure-caption { max-width: var(--measure-notes); }

.platform-flow .pf-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr) auto minmax(0, 1fr);
  grid-template-rows: auto auto auto auto auto;
  column-gap: var(--s4);
  row-gap: var(--s3);
  background: var(--paper-alt);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
  padding: var(--s5);
}

/* THE PUBLISHED MATERIAL SPANS THE BAND; ONLY THE CONNECTOR IS IN ONE COLUMN. The first version put
   the publisher, the panel and the connector all in column 3, which left columns 1, 2, 4 and 5 empty
   for three rows and made the figure a tall spike with two cards marooned at the bottom. Measured on
   screen at 1440 before it was changed.
   The span is also the better reading. What Connect publishes is not a property of one platform, so
   it runs the width. The single arrow into column 3 is what says the platform, and only the
   platform, reads it. */
.platform-flow .pf-source { grid-column: 1 / -1; grid-row: 1; }
.platform-flow .pf-chain { grid-column: 1 / -1; grid-row: 2; }
.platform-flow .pf-reads { grid-column: 3; grid-row: 3; }
.platform-flow .pf-party[data-pos="1"] { grid-column: 1; grid-row: 4; }
.platform-flow .pf-link[data-link="0"] { grid-column: 2; grid-row: 4; }
.platform-flow .pf-party[data-pos="2"] { grid-column: 3; grid-row: 4; }
.platform-flow .pf-link[data-link="1"] { grid-column: 4; grid-row: 4; }
.platform-flow .pf-party[data-pos="3"] { grid-column: 5; grid-row: 4; }
.platform-flow .pf-boundary { grid-column: 3 / -1; grid-row: 5; }

/* ---- who published the statements ----

   The one Raidiam product in the figure, so the one thing that may carry the brand fill. It is a
   DOT rather than a filled pill, because a filled pill with a word on it needs the reversed pair
   and this line reads better as a name beside a marker. The selector carries data-treat="product",
   which is what packages/ui/tests/stylesheet.test.ts requires of any rule naming var(--teal). */
.platform-flow .pf-source {
  margin: 0;
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: center;
  gap: var(--s2);
  text-align: center;
}
.platform-flow .pf-source[data-treat="product"] .pf-source-dot {
  width: 10px; height: 10px; flex: none;
  border-radius: var(--pill);
  background: var(--teal);
  align-self: center;
}
.platform-flow .pf-source-name {
  font-size: var(--t-label); font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--teal-dark);
}
.platform-flow .pf-source-line { font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-2); }

/* ---- the signed statements ----

   A panel with a rule stroke and NO fill. It is bytes rather than a party, and a filled box in a
   figure whose other filled boxes are parties would read as a fourth one. That is the reading the
   whole figure exists to refuse. */
.platform-flow .pf-chain {
  border: 1px dashed var(--rule);
  border-radius: var(--r-2);
  padding: var(--s4);
  display: grid; gap: var(--s3);
}
.platform-flow .pf-chain-label {
  margin: 0;
  font-size: var(--t-label); font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--teal-dark);
}
/* FOUR EQUAL COLUMNS, LEFT ALIGNED, not a centred wrap. Centred and wrapping, the four items set
   one line, two lines, one line, two lines, and the short one floated to the middle of its row
   while its neighbours hung left. It read as four unrelated fragments. Four tracks give them one
   left edge and one top edge each. */
.platform-flow .pf-chain-items {
  list-style: none; margin: 0; padding: 0;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--s3) var(--s4);
}
.platform-flow .pf-chain-item { display: flex; align-items: start; gap: var(--s2); min-width: 0; font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink); }
.platform-flow .pf-chain-icon { display: block; width: 17px; height: 17px; flex: none; margin-top: 2px; color: var(--teal-dark); }
.platform-flow .pf-chain-icon svg { width: 100%; height: 100%; display: block; }

/* ---- what the platform does with them ----

   The arrow points DOWN into the platform, and the sentence beside it names the bound. Both halves
   matter: the direction says who reads whom, and the sentence says the answer is held rather than
   asked for again. */
.platform-flow .pf-reads {
  margin: 0;
  display: grid; justify-items: center; gap: 6px;
  font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-2);
  text-align: center;
}
.platform-flow .pf-reads-arrow {
  display: block; width: 15px; height: 18px;
  background: var(--teal-dark);
  -webkit-mask: var(--arrow-right) center / 15px 10px no-repeat;
  mask: var(--arrow-right) center / 15px 10px no-repeat;
  transform: rotate(90deg);
}

/* ---- the three parties ---- */

.platform-flow .pf-party {
  min-width: 0;
  display: grid; gap: var(--s2); align-content: start; justify-items: center;
  padding: var(--s4);
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
  box-shadow: var(--shadow-lift);
  text-align: center;
}
.platform-flow .pf-party-icon { display: block; width: 30px; height: 30px; color: var(--teal-dark); }
.platform-flow .pf-party-icon svg { width: 100%; height: 100%; display: block; }
.platform-flow .pf-party-name {
  margin: 0;
  font-size: var(--t-label); font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--ink);
}
.platform-flow .pf-party-line { margin: 0; font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-2); }

/* ---- the request path between them ----

   The arrow sits in its own grid column rather than inside either card, so it never moves when a
   party's text changes length. The idiom is the capability flow rail's, in src/parts/rail.css. */
.platform-flow .pf-link {
  margin: 0;
  align-self: center;
  display: grid; justify-items: center; gap: 4px;
  max-width: 13ch;
  font-size: var(--t-label); line-height: var(--t-label-line); color: var(--ink-2);
  text-align: center;
}
.platform-flow .pf-link-arrow {
  display: block; width: 15px; height: 10px;
  background: var(--teal-dark);
  -webkit-mask: var(--arrow-right) center / 15px 10px no-repeat;
  mask: var(--arrow-right) center / 15px 10px no-repeat;
}

/* ---- the bracket under what the customer owns ----

   A rule and a label rather than a box around two cards. A box would need to sit behind the cards
   and would give the figure a third nested ground; the site already refuses a third stacked grey in
   the steps figure above, for the same reason. */
.platform-flow .pf-boundary {
  margin: 0;
  display: grid; gap: 6px; justify-items: center;
  font-size: var(--t-label); letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--ink-2);
}
.platform-flow .pf-boundary-rule { display: block; width: 100%; height: 1px; background: var(--rule); }

/* ---- narrow ----

   THE TWO AXES COLLAPSE INTO ONE COLUMN, in reading order, because at this width a five column grid
   has nothing to give. The request path stays first and the published material follows it, which is
   the order the markup already carries, so the narrow layout is the markup order and the wide one
   is the exception. Every arrow turns a quarter to point down the column. */
/* THE OVERRIDES CARRY THE ATTRIBUTE SELECTOR, and the first version of this block did not. The wide
   placements are written `.platform-flow .pf-party[data-pos="1"]`, three selectors, and the
   overrides here were written `.platform-flow .pf-party`, two. So `grid-row: 4` survived the media
   query, all three cards were placed in one cell, and they drew on top of each other.
   MEASURED rather than read off the rule: tools/redesign/responsive.mjs reported "siblings overlap
   by 18x34: div.pf-party and p.pf-link" at 768 and at 390, and at 390 the document scrolled
   sideways, 400 px in a 390 px viewport, with .pf-party-name past the edge. With the selectors
   below matched to the placements, all five widths read clean. */
@media (max-width: 980px) {
  .platform-flow .pf-grid { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; row-gap: var(--s4); }
  .platform-flow .pf-source,
  .platform-flow .pf-chain,
  .platform-flow .pf-reads,
  .platform-flow .pf-party[data-pos],
  .platform-flow .pf-link[data-link],
  .platform-flow .pf-boundary { grid-column: 1; grid-row: auto; }
  .platform-flow .pf-chain-items { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .platform-flow .pf-link { max-width: none; }
  .platform-flow .pf-link-arrow { transform: rotate(90deg); }
}
@media (max-width: 560px) {
  .platform-flow .pf-grid { padding: var(--s4); }
  .platform-flow .pf-party { padding: var(--s3) var(--s4); }
}

/* ==========================================================================
   THE PAGE: apps/site/src/views/platform-needs.ejs
   ========================================================================== */

/* ---- the consumers, which are the page's evidence ----

   Seven real services on this estate and what each one pins. It stays a table because it is a
   table: seven rows against five columns, and every cell is a fact read from the estate
   declaration. What changes is that it now sits in a card with its own header band, its own rules
   and a row highlight, rather than on the bare page.

   IT STILL SCROLLS SIDEWAYS ON A PHONE, and the wrapper carries tabindex="0" for exactly that
   reason: a region that scrolls sideways has to be reachable by keyboard or its right hand columns
   are unreadable without a pointer. axe reports the absence as scrollable-region-focusable,
   serious. The wrapper is the page's, in site.css; what this file adds is the shell around it. */
.hiw-consumers {
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
  box-shadow: var(--shadow-lift);
  overflow: hidden;
}
.hiw-consumers .table-scroll { border-radius: var(--r-3); }
.hiw-consumers .site-table { background: transparent; }
.hiw-consumers .site-table thead th {
  background: var(--paper-alt);
  font-size: var(--t-label); letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--ink-2);
  padding: var(--s3) var(--s4);
  white-space: nowrap;
  border-bottom: 1px solid var(--rule);
}
.hiw-consumers .site-table tbody th, .hiw-consumers .site-table tbody td {
  padding: var(--s3) var(--s4);
  border-bottom: 1px solid color-mix(in srgb, var(--rule) 45%, transparent);
  vertical-align: middle;
}
.hiw-consumers .site-table tbody tr:last-child th, .hiw-consumers .site-table tbody tr:last-child td { border-bottom: 0; }
.hiw-consumers .site-table tbody th { color: var(--ink); white-space: nowrap; }
.hiw-consumers .site-table tbody td { color: var(--ink-2); }
.hiw-consumers .site-table tbody tr { transition: background-color var(--m-drawer) ease; }
.hiw-consumers .site-table tbody tr:hover { background: var(--wash-teal); }
.hiw-consumers .site-table tbody tr:hover td { color: var(--ink); }
/* The window each consumer honours. A number is the answer to this column, so it is set in the
   mono face at the mono step, which is 14px and the floor for this site. */
.hiw-consumers .hiw-window { font-family: var(--mono); font-size: var(--t-mono); color: var(--ink); white-space: nowrap; }
.hiw-consumers .site-table td .treat.chip { white-space: nowrap; }

/* ---- the control band ----

   A wide panel: the glyph, what the product does, and three statements about how it is built.

   THE THREE MARKS ARE RULES, NOT TICKS, AND CARRY THE ACCENT RATHER THAN --ok. Green means Observed
   on every other surface of this site and these three are not readings taken from this tenant. The
   reference's own marks measure blue rather than green, so the rule costs the design nothing here.
   A short accent rule also survives a greyscale print and a reader who separates few hues, which a
   coloured tick does not. */
.hiw-control {
  display: grid;
  grid-template-columns: auto minmax(0, 1.6fr) minmax(0, 1fr);
  align-items: start;
  gap: var(--s4) var(--s6);
  background: var(--paper-alt);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
  padding: var(--s6);
}
.hiw-control .hiw-control-glyph { display: block; width: 44px; height: 44px; flex: none; color: var(--teal-dark); }
.hiw-control .hiw-control-glyph svg { width: 100%; height: 100%; display: block; }
.hiw-control .hiw-control-say { display: grid; gap: var(--s3); min-width: 0; }
.hiw-control .hiw-control-say h2 { margin: 0; }
.hiw-control .hiw-control-say p { margin: 0; color: var(--ink-2); max-width: var(--measure-body); }
.hiw-control .hiw-assurances { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s3); align-content: start; }
.hiw-control .hiw-assurances li { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--s3); align-items: start; font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink); }
.hiw-control .hiw-assurance-mark { display: block; width: 18px; height: 2px; margin-top: 0.65em; background: var(--teal-dark); border-radius: var(--pill); }

/* ---- what is configured once, and what is repeated ----

   Two columns, and they are DELIBERATELY UNEQUAL IN LENGTH. The first lists three things a platform
   configures at deploy time; the second lists two, and the second is the argument. Padding the
   short column to match the tall one would spend the reader's attention hiding the point. */
.hiw-once { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s5); align-items: start; }
.hiw-once .hiw-once-col {
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
  box-shadow: var(--shadow-lift);
  padding: var(--s5);
  display: grid; gap: var(--s4); align-content: start;
}
.hiw-once .hiw-once-label {
  margin: 0;
  font-size: var(--t-label); font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--teal-dark);
}
.hiw-once .hiw-once-items { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s3); }
.hiw-once .hiw-once-items li {
  position: relative; padding-left: var(--s5);
  font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink);
}
/* The marker is a rule rather than a disc, for the same reason the assurance marks are. */
.hiw-once .hiw-once-items li::before {
  content: ""; position: absolute; left: 0; top: 0.65em;
  width: 12px; height: 2px; border-radius: var(--pill);
  background: var(--teal-dark);
}

/* ---- what Connect provides ---- */

.hiw-provides { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s5); align-items: stretch; }
.hiw-provides .hiw-provide {
  min-width: 0;
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
  box-shadow: var(--shadow-lift);
  padding: var(--s5);
  display: grid; gap: var(--s3); align-content: start;
}
.hiw-provides .hiw-provide-glyph { display: block; width: 32px; height: 32px; color: var(--teal-dark); }
.hiw-provides .hiw-provide-glyph svg { width: 100%; height: 100%; display: block; }
.hiw-provides .hiw-provide h3 { margin: 0; color: var(--ink); }
.hiw-provides .hiw-provide p { margin: 0; color: var(--ink-2); }

/* The evidence under the provides row. It sits apart from the three cards rather than inside one,
   because only one of the three has a matrix row behind it and a chip inside a card row reads as a
   property of every card. */
.hiw-provides-claim { margin-top: var(--s5); max-width: var(--measure-notes); }
.hiw-provides-claim p { font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-2); }

/* ---- the open standard band ----

   A narrow band, not a card row: one glyph, one sentence and two quiet actions. The sentence
   carries the open standard marker, which is a span around the specification's name rather than a
   chip on a box, because a standard marks a sentence and never a box. */
.hiw-standard {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--s4) var(--s5);
  background: var(--paper-alt);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
  padding: var(--s5) var(--s6);
}
.hiw-standard .hiw-standard-glyph { display: block; width: 30px; height: 30px; color: var(--teal-dark); }
.hiw-standard .hiw-standard-glyph svg { width: 100%; height: 100%; display: block; }
.hiw-standard .hiw-standard-say { display: grid; gap: 6px; min-width: 0; }
.hiw-standard .hiw-standard-say h2 { margin: 0; color: var(--ink); }
.hiw-standard .hiw-standard-say .read p { margin: 0; font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-2); max-width: var(--measure-notes); }
.hiw-standard .hiw-standard-actions { display: flex; flex-wrap: wrap; gap: var(--s3); }

/* ---- narrow, for the four page level bands above ---- */

@media (max-width: 980px) {
  .hiw-control { grid-template-columns: auto minmax(0, 1fr); padding: var(--s5); }
  /* The assurances move under both, spanning the glyph column as well, so their text keeps the full
     width rather than sitting in a column the glyph set. */
  .hiw-control .hiw-assurances { grid-column: 1 / -1; }
  .hiw-once { grid-template-columns: minmax(0, 1fr); }
  .hiw-provides { grid-template-columns: minmax(0, 1fr); }
  .hiw-standard { grid-template-columns: auto minmax(0, 1fr); padding: var(--s5); }
  .hiw-standard .hiw-standard-actions { grid-column: 1 / -1; }
}
@media (max-width: 560px) {
  .hiw-control { grid-template-columns: minmax(0, 1fr); }
  .hiw-control .hiw-assurances { grid-column: auto; }
  .hiw-standard { grid-template-columns: minmax(0, 1fr); }
  .hiw-standard .hiw-standard-actions { grid-column: auto; }
  .hiw-once .hiw-once-col, .hiw-provides .hiw-provide { padding: var(--s4); }
}

/* ---- the closing question ---- */

.hiw-ask { display: grid; gap: var(--s5); justify-items: start; }
.hiw-ask .hiw-ask-line { margin: 0; max-width: var(--measure-body); }

/* ==========================================================================
   REDUCED MOTION
   ========================================================================== */

/* All motion stops. The global block in ui.css already shortens every animation and transition to a
   fraction of a millisecond with !important; this one removes the animation outright and restores
   the end state, so the arrows sit at full opacity rather than wherever a one frame run left them,
   and the hover lift becomes no lift rather than an instant one.
 *
 * THE GLOBAL BLOCK ALREADY STOPS EVERY VISIBLE MOVEMENT, and the first version of this note said
 * the opposite. Recorded because the wrong reading is the plausible one: `animation-duration:
 * 0.001ms` SHORTENS rather than removes, so a computed style still reports the animation-name and
 * still reports the hover transform, and reading those two values looks like finding a hole.
 *
 * MEASURED, on 2026-09-12, with this block deleted and the sheet rebuilt. The instrument was
 * calibrated first, and its first version was blind: a screenshot clip taken at the top of the step
 * row missed the arrow, which sits at half the card's height, and reported one frame at
 * no-preference where the animation was plainly running. Clipped onto the arrow itself, 26 by 16
 * pixels in the gap, it reported 11 distinct frames over 1.4 s at no-preference and 1 under reduce.
 * The hover was sampled every 40 ms across 480 ms: at no-preference the transform passes through
 * -1.15, -1.78 and -1.99 on its way to -2 px; under reduce it reads -2 px on the first sample and
 * never changes. document.getAnimations() returns two running under no-preference and none under
 * reduce. So nothing moves either way: what survives the global block is an instant state change.
 *
 * WHAT THIS BLOCK ADDS is the end state itself, which is a preference rather than a repair. The
 * card does not lift at all rather than jumping 2 px, and the arrow rests at full opacity rather
 * than at the 0.55 to 1 keyframe range's base value of 0.8. Keep it; do not cite it as the thing
 * that stops the motion. */
@media (prefers-reduced-motion: reduce) {
  .platform-steps .ps-step::after { animation: none; opacity: 1; }
  .platform-steps .ps-step { transition: none; }
  .platform-steps .ps-step:hover { transform: none; }
  .hiw-consumers .site-table tbody tr { transition: none; }
}

/* ---- src/parts/hx.css ---- */
/* /how-it-works: the page and its one instrument, packages/ui/partials/hx-decision.ejs.
 *
 * THE TREATMENTS ARE components/diagram-section.tsx's. The pedestal, the lit card, the ambient pool
 * and the ringed number come from rw.css by class. This file places them, and draws the chain, the
 * folded sheets, the nested ceilings and the token.
 *
 * FOUR IDENTITY HUES AND NO STATE COLOUR. Each step carries its hue in `--hue`: the agent blue
 * (--d-blue), the chain green (--d-magenta), the policy amber (--d-sand) and the platform violet
 * (--d-violet). Green sits on the chain, which claims nothing passed, rather than on the token. Nothing on the figure is Observed, so --ok, --att and --no appear nowhere here.
 */

/* ---- THE PAGE ---- */
.hx-page { --page-max: 1472px; }
.hx-top { position: relative; padding-block: 3.5rem var(--s5); }
.hx-top-copy { display: grid; gap: 0; }
.hx-top-copy > * { margin: 0; }
.hx-top-copy .sc-eyebrow { letter-spacing: 0.22em; color: var(--slate); }
.hx-top-copy .sc-headline { margin-top: var(--s4); line-height: 1.02; letter-spacing: -0.035em; max-width: 22ch; }
.hx-top-copy .sc-headline .accent { display: block; }
.hx-top-copy .sc-lead { margin-top: 1.25rem; max-width: 36rem; font-size: 17px; line-height: 1.55; color: var(--ink-lead); }
.hx-top-copy .sc-actions { margin-top: var(--s6); display: flex; flex-wrap: wrap; gap: var(--s4); }
/* ABOVE 1200 THE COPY TAKES TWO COLUMNS OVER THE INSTRUMENT: the headline on the left, the lead and
   the actions on the right. The figure is four steps wide and needs the full measure under it. */
@media (min-width: 1200px) {
  .hx-top-copy { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); column-gap: var(--s7, 4rem); grid-template-areas: "eyebrow eyebrow" "head lead" "head actions"; align-items: start; }
  .hx-top-copy .sc-eyebrow { grid-area: eyebrow; }
  .hx-top-copy .sc-headline { grid-area: head; }
  .hx-top-copy .sc-lead { grid-area: lead; }
  .hx-top-copy .sc-actions { grid-area: actions; }
}
.hx-figure-band { padding-block: var(--s5) var(--s6); }

/* ---- THE OUTCOME ROW, the reference's benefits row ---- */
.hx-payoff { padding-block: var(--s6); }
.hx-outcomes { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); }
.hx-outcomes li { display: flex; flex-direction: column; align-items: center; text-align: center; padding: 0 var(--s4); }
.hx-outcomes li + li { border-left: 1px solid var(--hairline); }
.hx-outcome-i { width: 52px; height: 52px; }
.hx-outcome-i svg { width: 26px; height: 26px; }
.hx-outcome-t { margin: var(--s4) 0 0; font-size: 18px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.hx-outcome-l { margin: var(--s2) 0 0; max-width: 19rem; text-wrap: balance; font-size: 15px; line-height: 1.5; color: var(--ink-2); }
@media (max-width: 900px) {
  .hx-outcomes { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: var(--s6); }
  .hx-outcomes li + li { border-left: 0; }
  .hx-outcomes li:nth-child(even) { border-left: 1px solid var(--hairline); }
}
@media (max-width: 480px) {
  .hx-outcomes { grid-template-columns: minmax(0, 1fr); }
  .hx-outcomes li:nth-child(even) { border-left: 0; }
}

/* ---- THE INSTRUMENT ---- */
.hx { position: relative; margin: 0; min-width: 0; }
.hx-glow { top: 120px; width: 1100px; }
/* FOUR STEPS AND THREE CONNECTORS ON ONE ROW. The connectors are 40px columns, so the four cards
   share what is left equally. */
.hx-steps {
  position: relative; list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: minmax(0, 1fr) 40px minmax(0, 1fr) 40px minmax(0, 1fr) 40px minmax(0, 1fr);
  align-items: stretch;
}
.hx-step {
  position: relative; min-width: 0;
  display: flex; flex-direction: column; gap: var(--s4);
  padding: var(--s5) var(--s4);
  border-radius: 14px;
  border: 1px solid color-mix(in srgb, var(--ink) 10%, transparent);
  border-top-color: color-mix(in srgb, var(--hue) 55%, transparent);
  background: linear-gradient(180deg, color-mix(in srgb, var(--hue) 7%, var(--paper-alt)) 0%, var(--paper) 100%);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--hue) 40%, transparent);
}
.hx-head { margin: 0; display: flex; align-items: flex-start; gap: var(--s3); }
.hx-head > div { display: grid; min-width: 0; }
.hx-head h3, .hx-head p { margin: 0; }
.hx-n {
  flex: none; display: inline-grid; place-items: center; width: 38px; height: 38px; border-radius: 50%;
  border: 1.5px solid var(--hue); color: var(--ink); font-size: 14px; font-weight: 700; font-variant-numeric: tabular-nums;
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--hue) 12%, transparent);
}
.hx-verb { font-size: 20px; line-height: 1.2; font-weight: 700; color: var(--ink); letter-spacing: -0.01em; }
.hx-line { margin-top: 2px; font-size: 14px; line-height: 1.4; color: var(--ink-2); }
.hx-body { display: grid; gap: var(--s3); min-width: 0; }
.hx-kind { margin: 0; font-size: 14px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--hue); }
.hx-name { margin: 0; font-size: 17px; font-weight: 700; color: var(--ink); }
.hx-sub { margin: 0; font-size: 14px; font-weight: 600; color: var(--ink-row); }
.hx-code { font-family: var(--mono); font-size: 14px; color: var(--ink-row); overflow-wrap: anywhere; }
.hx-foot { margin: 0; text-align: center; font-size: 14px; color: var(--ink-2); }

/* 01 THE AGENT, on its pedestal, with the three rows it presents. */
.hx-agent .rw-ped { --hue: var(--d-blue); margin-bottom: -10px; }
.hx-card { padding: var(--s4); display: grid; gap: var(--s1, 4px); }
.hx-rows { margin: var(--s3) 0 0; display: grid; gap: var(--s3); }
.hx-rows div { display: grid; gap: 2px; }
.hx-rows dt { font-size: 14px; color: var(--ink-2); }
.hx-rows dd { margin: 0; font-size: 14px; font-weight: 600; color: var(--ink); overflow-wrap: anywhere; }

/* 02 THE CHAIN. The agent at the top, the anchor at the bottom, one rung per signed statement. The
   anchor carries a lock and the words that say where its key lives, because the pin is the one
   thing on the walk the platform brings rather than fetches. */
.hx-chain { list-style: none; margin: 0; padding: 0; display: grid; justify-items: stretch; }
.hx-hop {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3); border-radius: 10px;
  border: 1px solid color-mix(in srgb, var(--hue) 30%, transparent);
  background: var(--paper);
}
.hx-hop-anchor {
  border-color: color-mix(in srgb, var(--hue) 70%, transparent);
  box-shadow: 0 0 28px color-mix(in srgb, var(--hue) 22%, transparent), inset 0 1px 0 color-mix(in srgb, var(--hue) 50%, transparent);
}
.hx-hop-i { flex: none; display: inline-flex; color: var(--hue); filter: drop-shadow(0 0 6px var(--hue)); }
.hx-hop-i svg, .hx-mark-i svg, .hx-token-i svg { width: 24px; height: 24px; display: block; }
.hx-hop-txt { display: grid; min-width: 0; }
.hx-hop-txt .hx-kind { font-size: 14px; letter-spacing: 0.06em; }
.hx-hop-name { font-size: 15px; font-weight: 700; color: var(--ink); overflow-wrap: anywhere; }
.hx-hop-pin { font-size: 14px; color: var(--ink-2); }
/* THE RUNG. A short vertical wire between two hops with the words the statement says about the hop
   below it, which is what the platform fetches at that step. */
.hx-rung { position: relative; display: flex; align-items: center; min-height: 40px; padding-left: calc(var(--s3) + 11px); }
.hx-rung::before {
  content: ""; position: absolute; left: calc(var(--s3) + 11px); top: 0; bottom: 0; width: 2px;
  background: linear-gradient(180deg, color-mix(in srgb, var(--hue) 80%, transparent), color-mix(in srgb, var(--hue) 40%, transparent));
  box-shadow: 0 0 8px var(--hue);
}
.hx-rung span { margin-left: var(--s4); font-size: 14px; color: var(--ink-2); }

/* 03 THE FOLD. The statements as stacked sheets, anchor first, landing on the agent's own metadata,
   and the ceiling that results. */
.hx-sheets { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.hx-sheet {
  display: grid; gap: 2px; padding: var(--s2) var(--s3); border-radius: 8px;
  border: 1px solid color-mix(in srgb, var(--hue) 30%, transparent);
  border-left: 3px solid var(--hue);
  background: var(--paper);
}
.hx-sheet + .hx-sheet { margin-left: 10px; }
.hx-sheet + .hx-sheet + .hx-sheet { margin-left: 20px; }
.hx-sheet-leaf { border-left-style: dashed; background: var(--paper); }
.hx-sheet-n { font-size: 14px; font-weight: 700; color: var(--ink); }
.hx-sheet-v { font-size: 14px; color: var(--ink-2); }
.hx-result {
  display: grid; gap: var(--s2); padding: var(--s3); border-radius: 10px;
  border: 1px solid color-mix(in srgb, var(--hue) 55%, transparent);
  box-shadow: 0 0 24px color-mix(in srgb, var(--hue) 16%, transparent);
}
.hx-mark { margin: 0; display: flex; gap: var(--s3); align-items: flex-start; }
.hx-mark > span:last-child { display: grid; gap: 2px; min-width: 0; }
.hx-mark-i { flex: none; display: inline-flex; color: var(--hue); }
.hx-mark-l { font-size: 14px; color: var(--ink-2); }

/* THE DETAIL TYPES. One chip per type, the same drawing in the fold and in the ceilings, so a reader
   follows four chips down to one. `is-out` is a type the request did not name, dashed and quieter;
   `is-in` is a type the token carries. Neither is a state colour. */
.hx-chips { margin: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.hx-chip {
  display: inline-block; padding: 2px var(--s2); border-radius: 6px;
  font-family: var(--mono); font-size: 14px; line-height: 1.5; color: var(--ink);
  border: 1px solid color-mix(in srgb, var(--hue) 45%, transparent);
  background: var(--paper-alt);
}
.hx-chip.is-out { border-style: dashed; background: transparent; color: var(--ink-2); }
.hx-chip.is-in { border-color: var(--hue); background: var(--paper-alt); box-shadow: inset 0 0 0 1px var(--hue), 0 0 14px color-mix(in srgb, var(--hue) 35%, transparent); font-weight: 600; }

/* 04 THE CEILINGS, nested. Registered holds attested holds granted, as containment.ts intersects
   them, and each ring shows only the types the ring inside it leaves out. */
.hx-ring { display: grid; gap: var(--s2); padding: var(--s3); border-radius: 12px; border: 1px solid color-mix(in srgb, var(--hue) 35%, transparent); }
.hx-ring-reg { background: transparent; }
.hx-ring-att { border-color: color-mix(in srgb, var(--hue) 55%, transparent); background: var(--paper); }
.hx-ring-grant { border-color: var(--hue); background: var(--paper-alt); box-shadow: 0 0 22px color-mix(in srgb, var(--hue) 22%, transparent); }
.hx-ring-l { margin: 0; font-size: 14px; line-height: 1.4; color: var(--ink-2); }
.hx-ring-t { font-weight: 700; color: var(--ink); }
/* THE COUNT ON EACH RING, so the narrowing reads as numbers going down before a reader opens a chip. */
.hx-count {
  float: right; margin-left: var(--s2); min-width: 26px; padding: 0 6px; border-radius: 999px; text-align: center;
  border: 1px solid color-mix(in srgb, var(--hue) 55%, transparent); color: var(--ink); font-weight: 700; font-variant-numeric: tabular-nums;
}
.hx-token {
  display: flex; gap: var(--s3); align-items: flex-start;
  padding: var(--s3) var(--s4); border-radius: 12px;
  border: 1px solid var(--hue);
  background: linear-gradient(180deg, color-mix(in srgb, var(--hue) 14%, var(--paper-alt)) 0%, var(--paper) 100%);
  box-shadow: 0 0 32px color-mix(in srgb, var(--hue) 26%, transparent), inset 0 1px 0 color-mix(in srgb, var(--hue) 60%, transparent);
}
.hx-token-i { flex: none; display: inline-flex; color: var(--hue); filter: drop-shadow(0 0 8px var(--hue)); }
.hx-token-txt { display: grid; gap: var(--s1, 4px); min-width: 0; }
.hx-token-l, .hx-token-s { font-size: 14px; color: var(--ink-2); }

/* THE CONNECTORS. A lit wire with a filled arrowhead, glowing, the reference's connector turned to
   run between four cards rather than down from a hub. The pulse runs along it in the loop. */
.hx-link { position: relative; list-style: none; align-self: center; height: 40px; }
.hx-link-line {
  position: absolute; left: 4px; right: 12px; top: 50%; height: 2px; transform: translateY(-50%);
  background: linear-gradient(90deg, color-mix(in srgb, var(--teal-dark) 50%, transparent), var(--teal-dark));
  box-shadow: 0 0 8px color-mix(in srgb, var(--teal-dark) 70%, transparent);
}
.hx-link-head { position: absolute; right: 2px; top: 50%; transform: translateY(-50%); width: 0; height: 0; border-top: 7px solid transparent; border-bottom: 7px solid transparent; border-left: 12px solid var(--brand-strong); }
.hx-link-pulse { position: absolute; left: 4px; top: 50%; width: 10px; height: 10px; margin-top: -5px; border-radius: 50%; background: var(--brand-strong); box-shadow: 0 0 10px var(--brand-strong); opacity: 0; }

/* ---- THE LOOP ----
   Twelve seconds, four quarters, one step lit in each, with a pulse along the connector into it.
   Nothing appears or disappears: the loop only moves the light. */
@media (prefers-reduced-motion: no-preference) {
  .hx-step { animation: hx-step 12s ease-in-out infinite; }
  .hx-step[data-step="2"] { animation-delay: 3s; }
  .hx-step[data-step="3"] { animation-delay: 6s; }
  .hx-step[data-step="4"] { animation-delay: 9s; }
  .hx-link-pulse { animation: hx-pulse 12s linear infinite; }
  .hx-link:nth-child(2) .hx-link-pulse { animation-delay: 2.4s; }
  .hx-link:nth-child(4) .hx-link-pulse { animation-delay: 5.4s; }
  .hx-link:nth-child(6) .hx-link-pulse { animation-delay: 8.4s; }
}
@keyframes hx-step {
  0%, 25%, 100% { box-shadow: inset 0 1px 0 color-mix(in srgb, var(--hue) 40%, transparent); }
  6%, 20% { box-shadow: inset 0 1px 0 color-mix(in srgb, var(--hue) 75%, transparent), 0 0 48px color-mix(in srgb, var(--hue) 26%, transparent); }
}
@keyframes hx-pulse {
  0% { opacity: 0; left: 4px; }
  1% { opacity: 1; left: 4px; }
  5% { opacity: 1; left: calc(100% - 20px); }
  6%, 100% { opacity: 0; left: calc(100% - 20px); }
}

/* ---- THE NARROW STATE ----
   Below 1200 the steps become a timeline. At 1100 four columns left the Issues card 227px wide and
   its nested rings crossed the card's border. The numbered ring leaves the card for a spine on the left,
   the connectors turn downward along the spine, and while the card is wide enough its head sits
   beside its drawing rather than above it. */
@media (max-width: 1199px) {
  .hx-steps { grid-template-columns: minmax(0, 1fr); padding-left: 56px; }
  .hx-step { padding: var(--s5); }
  .hx .hx-n { position: absolute; left: -56px; top: var(--s5); background: var(--paper); }
  .hx-link { height: 36px; align-self: stretch; }
  .hx-link-line { left: -38px; right: auto; top: 0; bottom: 10px; width: 2px; height: auto; transform: none; background: linear-gradient(180deg, color-mix(in srgb, var(--teal-dark) 50%, transparent), var(--teal-dark)); }
  .hx-link-head { left: -44px; right: auto; top: auto; bottom: 0; transform: none; border-top: 12px solid var(--brand-strong); border-left: 7px solid transparent; border-right: 7px solid transparent; border-bottom: 0; }
  .hx-link-pulse { display: none; }
  /* A spine through the rings, behind them, so the four read as one sequence. */
  .hx-steps::before { content: ""; position: absolute; left: 18px; top: var(--s5); bottom: var(--s5); width: 2px; background: var(--hairline); }
}
@media (min-width: 700px) and (max-width: 1199px) {
  .hx-step { display: grid; grid-template-columns: minmax(0, 13rem) minmax(0, 1fr); column-gap: var(--s6); align-items: start; }
  .hx-agent { grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: var(--s4); }
}
@media (max-width: 480px) {
  .hx-steps { padding-left: 44px; }
  .hx .hx-n { left: -44px; width: 32px; height: 32px; }
  .hx-steps::before { left: 15px; }
  .hx-link-line { left: -29px; }
  .hx-link-head { left: -35px; }
  .hx-step { padding: var(--s4); }
  .hx-sheet + .hx-sheet { margin-left: 6px; }
  .hx-sheet + .hx-sheet + .hx-sheet { margin-left: 12px; }
}

/* ==================================================================
 * /how-it-works/evidence, views/platform-needs-evidence.ejs. Every rule starts .hxe-.
 * The four steps keep the claim figure's hues, so a reader who arrives from the figure finds the
 * same four colours in the same order.
 * ================================================================== */
.hxe-head { padding-bottom: var(--s6); }
.hxe-head > * { margin: 0; }
.hxe-headline { margin-top: var(--s3); max-width: 22ch; }
.hxe-lead { margin-top: var(--s4); max-width: 40rem; font-size: 17px; line-height: 1.55; color: var(--ink-lead); }
.hxe-back { margin-top: var(--s4); }
.hxe-caption { margin: var(--s5) 0 0; max-width: 48rem; font-size: 15px; line-height: 1.55; color: var(--ink-2); }

/* WHAT EACH STEP READS. Four lit panels, two by two, each with its artefacts. */
.hxe-reads { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s5); }
.hxe-read-step {
  display: grid; gap: var(--s4); align-content: start; min-width: 0;
  padding: var(--s5); border-radius: 14px;
  border: 1px solid color-mix(in srgb, var(--ink) 10%, transparent);
  border-top-color: color-mix(in srgb, var(--hue) 55%, transparent);
  background: linear-gradient(180deg, color-mix(in srgb, var(--hue) 7%, var(--paper-alt)) 0%, var(--paper) 100%);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--hue) 40%, transparent);
}
.hxe-read-step .hx-line { font-size: 15px; line-height: 1.5; }
.hxe-art { display: grid; gap: var(--s2); padding: var(--s3) var(--s4); border-radius: 10px; border: 1px solid color-mix(in srgb, var(--hue) 30%, transparent); background: var(--paper); min-width: 0; }
.hxe-art.is-refusal { border-style: dashed; }
.hxe-art-h { margin: 0; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s2) var(--s4); }
.hxe-art-l { font-size: 15px; font-weight: 700; color: var(--ink); }
.hxe-art-line, .hxe-art-head, .hxe-read { margin: 0; font-size: 14px; line-height: 1.5; color: var(--ink-2); }
.hxe-drawer summary { cursor: pointer; font-size: 14px; font-weight: 600; color: var(--brand-strong); }
.hxe-consumers > summary { display: flex; align-items: center; gap: var(--s3); }
.hxe-sum-h { display: inline; margin: 0; }
.hxe-drawer { min-width: 0; }
.hxe-drawer[open] { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s3); }
.hxe-drawer[open] summary { margin-bottom: var(--s2); }
.hxe-pre { margin: 0; padding: var(--s3); border-radius: 8px; overflow-x: auto; background: var(--paper-alt); border: 1px solid var(--hairline); }
.hxe-pre code { display: grid; font-family: var(--mono); font-size: 14px; line-height: 1.55; color: var(--ink-2); white-space: pre; }
.hxe-pre .is-on { color: var(--ink); box-shadow: inset 3px 0 0 var(--hue); padding-left: var(--s2); }
.hxe-pre .is-bad { color: var(--ink); }
.hxe-keys { margin: 0; padding-left: var(--s4); display: grid; gap: var(--s1, 4px); font-size: 14px; color: var(--ink-2); }
.hxe-keys code { font-size: 14px; color: var(--ink-row); }

/* STEP FOUR'S CEILINGS, as three bars scaled to the registered count. */
.hxe-ceil { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s3); }
.hxe-ceil li { display: grid; grid-template-columns: 7rem minmax(0, 1fr) 2rem; align-items: center; gap: var(--s3); }
.hxe-ceil-l { font-size: 14px; font-weight: 600; color: var(--ink); }
.hxe-ceil-bar { position: relative; height: 14px; border-radius: 999px; background: var(--hairline); }
.hxe-ceil-bar::after { content: ""; position: absolute; inset: 0 auto 0 0; width: var(--w); border-radius: inherit; background: var(--hue); box-shadow: 0 0 12px color-mix(in srgb, var(--hue) 50%, transparent); }
.hxe-ceil-n { font-size: 15px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; text-align: right; }

/* WHERE A REQUEST STOPS. Three columns of refusal names in the hue of the step that raises them. */
.hxe-stops { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s5); }
.hxe-stop { display: grid; gap: var(--s4); align-content: start; padding: var(--s5); border-radius: 14px; border: 1px solid color-mix(in srgb, var(--hue) 35%, transparent); border-top: 3px solid var(--hue); background: var(--paper-alt); min-width: 0; }
.hxe-src { margin-top: 2px; font-family: var(--mono); font-size: 14px; color: var(--ink-2); overflow-wrap: anywhere; }
.hxe-checks { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s4); }
.hxe-checks li { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s1, 4px) var(--s2); }
.hxe-check { font-family: var(--mono); font-size: 14px; font-weight: 600; color: var(--ink); overflow-wrap: anywhere; }
.hxe-kind { padding: 0 var(--s2); border-radius: 999px; border: 1px solid color-mix(in srgb, var(--hue) 55%, transparent); font-size: 14px; color: var(--ink-row); }
.hxe-kind.is-unresolved { border-style: dashed; }
.hxe-check-l { flex-basis: 100%; font-size: 14px; line-height: 1.45; color: var(--ink-2); }

/* HOW LONG EACH ANSWER LASTS. Four bars on one scale. */
.hxe-bars { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s4); max-width: 60rem; }
.hxe-bars li { display: grid; grid-template-columns: minmax(0, 18rem) minmax(0, 1fr) 6rem; align-items: center; gap: var(--s4); }
.hxe-bar-l { display: grid; font-size: 15px; font-weight: 600; color: var(--ink); }
.hxe-bar-note { font-size: 14px; font-weight: 400; line-height: 1.4; color: var(--ink-2); }
/* THE BARS ARE BRAND, NOT A STEP HUE. A lifetime belongs to no one step, and a green bar beside a
   number would read as an Observed figure. */
.hxe-bar { position: relative; height: 16px; border-radius: 999px; background: var(--hairline); }
.hxe-bar-fill { position: absolute; inset: 0 auto 0 0; width: var(--w); border-radius: inherit; background: linear-gradient(90deg, color-mix(in srgb, var(--teal-dark) 60%, transparent), var(--brand-strong)); box-shadow: 0 0 12px color-mix(in srgb, var(--teal-dark) 45%, transparent); }
.hxe-bar-v { font-size: 15px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; text-align: right; }

@media (max-width: 1000px) {
  .hxe-stops { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 800px) {
  .hxe-reads { grid-template-columns: minmax(0, 1fr); }
  .hxe-bars li { grid-template-columns: minmax(0, 1fr) 5rem; }
  .hxe-bar-l { grid-column: 1 / -1; }
}
@media (max-width: 480px) {
  .hxe-read-step, .hxe-stop { padding: var(--s4); }
  .hxe-ceil li { grid-template-columns: 5.5rem minmax(0, 1fr) 1.5rem; }
}

/* ---- src/parts/kc.css ---- */
/* /security and /security/keys: the pages and their instruments, packages/ui/partials/kc-custody.ejs,
 * kc-map.ejs and kc-rotate.ejs.
 *
 * THE TREATMENTS ARE components/diagram-section.tsx's. The pedestal, the lit card and the ambient
 * pool come from rw.css by class. This file places them, draws the Raidiam band, the four wires and
 * the two kinds of key, and carries the pages' own bands.
 *
 * rw.css SORTS AFTER THIS FILE, so a rule here that meets an rw rule at equal specificity loses.
 * Every override of an rw class is written under `.kc` or `.kcm` for that reason.
 *
 * FOUR IDENTITY HUES AND NO STATE COLOUR. Each lane carries its hue in `--hue`. The only state on
 * these figures is the evidence mark the view renders beside a word, so --ok, --att and --no appear
 * nowhere in this file.
 */

/* ---- THE PAGES ---- */
.kc-page { --page-max: 1472px; }
.kc-page h2, .kc-page h3 { font-family: inherit; }
.kc-top { position: relative; padding-block: 3.5rem var(--s6); }
.kc-top-copy > * { margin: 0; }
.kc-eyebrow { font-size: 14px; font-weight: 600; letter-spacing: 0.22em; text-transform: uppercase; color: var(--brand-strong); }
.kc-headline { margin-top: var(--s4); line-height: 1.02; letter-spacing: -0.035em; max-width: 20ch; }
.kc-headline .accent { display: block; }
.kc-lead { margin-top: 1.25rem; max-width: 34rem; font-size: 17px; line-height: 1.55; color: var(--ink-lead); }
.kc-lead p { margin: 0; }
.kc-lead p + p { margin-top: var(--s3); }
.kc-actions { margin-top: var(--s6); display: flex; flex-wrap: wrap; gap: var(--s4); }
@media (min-width: 1100px) {
  .kc-top-copy { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); column-gap: var(--s7, 4rem); grid-template-areas: "eyebrow eyebrow" "head lead" "head actions"; align-items: start; }
  .kc-eyebrow { grid-area: eyebrow; }
  .kc-headline { grid-area: head; }
  .kc-lead { grid-area: lead; margin-top: var(--s4); }
  .kc-actions { grid-area: actions; }
}
.kc-sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; border: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; }

/* THE OUTCOME ROW, the reference's benefits row: ringed 52px glyphs, hairlines between. */
.kc-payoff { padding-block: var(--s6); }
.kc-outcomes { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); }
.kc-outcomes li { display: flex; flex-direction: column; align-items: center; text-align: center; padding: 0 var(--s4); }
.kc-outcomes li + li { border-left: 1px solid var(--hairline); }
.kc-outcome-i { width: 52px; height: 52px; }
.kc-outcome-i svg { width: 26px; height: 26px; }
.kc-outcome-t { margin: var(--s4) 0 0; font-size: 18px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.kc-outcome-l { margin: var(--s2) 0 0; max-width: 19rem; text-wrap: balance; font-size: 15px; line-height: 1.5; color: var(--ink-2); }
.kc-outcome-m { margin: var(--s2) 0 0; }
.kc-outcome-a { margin-top: var(--s2); font-size: 15px; font-weight: 600; color: var(--brand-strong); }
@media (max-width: 900px) {
  .kc-outcomes { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: var(--s6); }
  .kc-outcomes li + li { border-left: 0; }
  .kc-outcomes li:nth-child(even) { border-left: 1px solid var(--hairline); }
}
@media (max-width: 480px) {
  .kc-outcomes { grid-template-columns: minmax(0, 1fr); }
  .kc-outcomes li:nth-child(even) { border-left: 0; }
}

/* ---- THE INSTRUMENT ON /security ---- */
.kc { position: relative; margin: 0; min-width: 0; }
.kc-glow { top: 40px; }
/* ONE GRID, FOUR COLUMNS, FOUR ROWS: the band title, the Connect slots, the wires, the holders. The
   list of lanes takes rows two to four as a subgrid and each lane takes three of them as a subgrid
   again, so every slot, every wire and every card starts on one line across all four lanes. */
.kc-grid {
  position: relative; display: grid; column-gap: 20px;
  grid-template-columns: repeat(var(--lanes, 3), minmax(0, 1fr));
  grid-template-rows: auto auto auto auto 1fr;
}
/* THE RAIDIAM BAND is the hub treatment stretched across the four columns, behind the title and the
   slots. It is drawn by the grid rather than by an element, so no lane's markup sits inside it and
   each lane still reads as one list item. */
.kc-grid::before {
  content: ""; grid-column: 1 / -1; grid-row: 1 / 4; z-index: 0; border-radius: 16px;
  border: 1px solid color-mix(in srgb, var(--teal-dark) 35%, transparent);
  background: radial-gradient(120% 90% at 50% 0%, color-mix(in srgb, var(--teal-mid) 40%, transparent) 0%, color-mix(in srgb, var(--white) 92%, transparent) 60%);
  box-shadow: 0 0 40px color-mix(in srgb, var(--teal-dark) 12%, transparent), inset 0 1px 0 color-mix(in srgb, var(--brand-strong) 35%, transparent);
}
.kc-hub-head { position: relative; z-index: 1; grid-column: 1 / -1; grid-row: 1; display: flex; align-items: center; justify-content: center; gap: var(--s4); padding: var(--s5) var(--s5) var(--s4); text-align: left; }
.kc-hub-i { display: inline-flex; color: var(--brand-strong); filter: drop-shadow(0 0 10px var(--teal-dark)); }
.kc-hub-i svg { width: 40px; height: 40px; }
.kc-hub-t { margin: 0; font-size: 22px; line-height: 1.25; font-weight: 700; letter-spacing: normal; color: var(--ink); }
.kc-hub-l { margin: 2px 0 0; font-size: 15px; line-height: 1.45; color: var(--ink-2); }
.kc-lanes {
  position: relative; z-index: 1; list-style: none; margin: 0; padding: 0;
  grid-column: 1 / -1; grid-row: 3 / 6;
  display: grid; grid-template-columns: subgrid; grid-template-rows: subgrid;
}
.kc-lane { grid-row: span 3; display: grid; grid-template-rows: subgrid; min-width: 0; }

/* RAIDIAM'S OWN KEYS, in the band. Each is a private half Raidiam holds, so each carries the filled
   key in the brand, and each answers the same questions a lane card answers. */
.kc-own { position: relative; z-index: 1; grid-column: 1 / -1; grid-row: 2; padding: 0 var(--s3) var(--s4); }
.kc-own-h { margin: 0 0 var(--s3); text-align: center; font-size: 14px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-2); }
.kc-own-list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s4); }
.kc-own-key {
  --hue: var(--brand-strong);
  min-width: 0; padding: var(--s4); border-radius: 12px;
  border: 1px solid color-mix(in srgb, var(--teal-dark) 45%, transparent); border-top: 2px solid var(--brand-strong);
  background: var(--paper);
  box-shadow: 0 0 26px color-mix(in srgb, var(--teal-dark) 20%, transparent);
}
.kc-own-top { margin: 0; display: flex; flex-wrap: wrap; align-items: center; gap: var(--s3); }
.kc-own-t { font-size: 18px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.kc-own-does { margin: var(--s2) 0 0; font-size: 14px; line-height: 1.45; color: var(--ink-2); }
.kc-own-key .kc-rows { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--s4); }
.kc-own-note { margin: var(--s3) 0 0; font-size: 14px; line-height: 1.45; color: var(--ink-row); }

/* THE SLOT, where the lane meets Connect. A small lit tile in the lane's hue inside the band. */
.kc-slot {
  margin: 0 var(--s3) var(--s5); padding: var(--s3) var(--s4);
  display: grid; justify-items: center; align-content: start; gap: var(--s2); text-align: center;
  border-radius: 10px; border: 1px solid var(--hairline);
  border-top: 2px solid var(--hue);
  background: var(--paper);
  box-shadow: 0 0 22px color-mix(in srgb, var(--hue) 18%, transparent);
}
/* THE SLOT'S OWN LABEL shows only below 1100, where each slot stands apart from the band title and
   has to say which side it is. Above 1100 the band says it once for all four. */
.kc-slot-l { display: none; font-size: 14px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: var(--brand-strong); }
.kc-slot-t { margin: 0; font-size: 15px; line-height: 1.4; font-weight: 600; color: var(--ink); }

/* THE TWO KEYS. Filled is the private half, outline is the public half. */
.kc-badge {
  display: inline-flex; align-items: center; gap: 6px; padding: 3px 12px 3px 6px; border-radius: var(--pill);
  font-size: 14px; font-weight: 600; line-height: 1.3; color: var(--ink); background: var(--paper-alt);
}
.kc-badge-private { border: 1.5px solid var(--hue); box-shadow: 0 0 14px color-mix(in srgb, var(--hue) 30%, transparent); }
.kc-badge-public { border: 1px dashed color-mix(in srgb, var(--hue) 70%, transparent); }
.kc-badge-i { display: inline-flex; color: var(--hue); }
.kc-badge-i svg { width: 22px; height: 22px; }
.kc-badge-private .kc-badge-i { filter: drop-shadow(0 0 6px var(--hue)); }

/* THE WIRE between the band and the holder. A lit line with a filled head where something crosses,
   and a dashed line with no head where nothing does. The chip names what crosses. */
.kc-wire { position: relative; min-height: 104px; display: flex; align-items: center; justify-content: center; padding: var(--s3) var(--s2); }
.kc-wire-line { position: absolute; top: 0; bottom: 0; left: calc(50% - 1px); width: 2px; }
.kc-wire-up .kc-wire-line { background: var(--hue); box-shadow: 0 0 8px var(--hue); }
.kc-wire-none .kc-wire-line { border-left: 2px dashed var(--rule); }
.kc-wire-head {
  position: absolute; top: -2px; left: -5px; width: 0; height: 0;
  border-left: 6px solid transparent; border-right: 6px solid transparent; border-bottom: 12px solid var(--hue);
}
.kc-wire-pulse { position: absolute; left: -3px; bottom: 0; width: 8px; height: 8px; border-radius: 50%; background: var(--ink); box-shadow: 0 0 10px var(--hue); opacity: 0; }
.kc-wire-chip {
  position: relative; z-index: 1; margin: 0; max-width: 100%;
  padding: 4px var(--s3); border-radius: var(--pill); text-align: center;
  font-size: 14px; font-weight: 600; line-height: 1.35; color: var(--ink);
  background: var(--paper); border: 1px solid color-mix(in srgb, var(--hue) 55%, transparent);
}
.kc-wire-none .kc-wire-chip { color: var(--ink-2); border-color: var(--rule); border-style: dashed; }

/* THE HOLDER: a pedestal and a lit card. */
.kc-foot { display: flex; flex-direction: column; min-width: 0; }
.kc .kc-ped { margin-bottom: -6px; }
.kc .kc-card { flex: 1; display: flex; flex-direction: column; padding: var(--s4); min-width: 0; }
.kc-role { margin: 0; font-size: 14px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--hue); }
.kc-title { margin: var(--s1, 4px) 0 0; font-size: 18px; line-height: 1.25; font-weight: 700; letter-spacing: normal; color: var(--ink); }
.kc-sub { margin: 2px 0 0; font-size: 14px; line-height: 1.4; color: var(--ink-2); }
.kc-here { margin: var(--s3) 0 0; }
.kc-rows { margin: var(--s4) 0 0; display: grid; gap: var(--s3); }
.kc-rows > div { display: grid; gap: 2px; padding-left: var(--s3); border-left: 2px solid color-mix(in srgb, var(--hue) 55%, transparent); }
.kc-rows dt { font-size: 14px; font-weight: 600; color: var(--ink-row); }
.kc-rows dd { margin: 0; font-size: 14px; line-height: 1.4; color: var(--ink-2); }
.kc-stolen { margin-top: var(--s4); padding: var(--s3); border-radius: 8px; border: 1px dashed color-mix(in srgb, var(--hue) 50%, transparent); }
.kc-stolen-h { margin: 0; font-size: 14px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-row); }
.kc-stolen-t { margin: var(--s1, 4px) 0 0; font-size: 14px; line-height: 1.45; color: var(--ink); }
.kc-mark { margin: var(--s2) 0 0; font-size: 14px; }
.kc-caption { margin: var(--s5) auto 0; max-width: 60rem; font-size: 14px; line-height: 1.5; color: var(--ink-2); text-align: center; }
.kc-caption .ev { margin-left: var(--s2); }

@media (prefers-reduced-motion: no-preference) {
  .kc-wire-pulse-1, .kc-wire-pulse-2, .kc-wire-pulse-3, .kc-wire-pulse-4 { animation: kc-cross 6s ease-in infinite; }
  .kc-wire-pulse-3 { animation-delay: 3s; }
}
@keyframes kc-cross {
  0% { bottom: 0; opacity: 0; }
  8% { opacity: 1; }
  30% { bottom: calc(100% - 8px); opacity: 1; }
  36%, 100% { bottom: calc(100% - 8px); opacity: 0; }
}

/* ---- THE NARROW STATE: each lane carries its own length of the band ----
   Below 1100 four columns cannot carry four rows each. The band title becomes a hub of its own, and
   every slot takes the band's treatment, so each lane still reads top to bottom as the Raidiam side,
   the wire and the holder. Two lanes a row down to 700, one below it. */
@media (max-width: 1099px) {
  .kc-grid { display: block; }
  .kc-grid::before { display: none; }
  .kc-hub-head {
    margin-bottom: var(--s5); border-radius: 14px; padding: var(--s4);
    border: 1px solid color-mix(in srgb, var(--teal-dark) 35%, transparent);
    background: radial-gradient(120% 90% at 50% 0%, color-mix(in srgb, var(--teal-mid) 40%, transparent) 0%, color-mix(in srgb, var(--white) 92%, transparent) 60%);
  }
  .kc-own { padding: 0; margin-bottom: var(--s6); }
  .kc-own-h { text-align: left; }
  .kc-lanes { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-rows: none; column-gap: var(--s5); row-gap: var(--s6); }
  .kc-lane { grid-row: auto; grid-template-rows: auto auto 1fr; }
  .kc-slot {
    margin: 0;
    border: 1px solid color-mix(in srgb, var(--teal-dark) 35%, transparent); border-top: 2px solid var(--hue);
    background: radial-gradient(120% 90% at 50% 0%, color-mix(in srgb, var(--teal-mid) 40%, transparent) 0%, color-mix(in srgb, var(--white) 92%, transparent) 70%);
  }
  .kc-wire { min-height: 84px; }
  .kc-slot-l { display: block; }
}
@media (max-width: 700px) {
  .kc-lanes { grid-template-columns: minmax(0, 1fr); }
  .kc-own-list, .kc-own-key .kc-rows { grid-template-columns: minmax(0, 1fr); }
  .kc-hub-head { justify-content: flex-start; }
}

/* ---- THE HOLDER MAP ON /security/keys ---- */
.kcm { position: relative; margin: 0; min-width: 0; }
.kcm-legend { list-style: none; margin: 0 0 var(--s5); padding: 0; display: flex; flex-wrap: wrap; gap: var(--s2) var(--s5); }
.kcm-legend li { display: inline-flex; align-items: center; gap: var(--s2); font-size: 14px; font-weight: 600; color: var(--ink-row); }
.kcm-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--hue); box-shadow: 0 0 8px var(--hue); }
.kcm-sides { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); gap: var(--s5); align-items: stretch; }
.kcm-side { position: relative; min-width: 0; border-radius: 16px; padding: var(--s5); }
/* THE RAIDIAM SIDE is the hub treatment, the one /security gives Raidiam Connect. */
.kcm-side-raidiam {
  border: 1px solid color-mix(in srgb, var(--teal-dark) 35%, transparent);
  background: radial-gradient(120% 80% at 50% 0%, color-mix(in srgb, var(--teal-mid) 40%, transparent) 0%, color-mix(in srgb, var(--white) 92%, transparent) 60%);
  box-shadow: 0 0 40px color-mix(in srgb, var(--teal-dark) 12%, transparent), inset 0 1px 0 color-mix(in srgb, var(--brand-strong) 35%, transparent);
}
/* THE HOLDER SIDE is a dashed frame, which is a boundary. */
.kcm-side-holder { border: 1px dashed var(--rule); }
.kcm-side-h { margin: 0; display: flex; align-items: baseline; gap: var(--s2); font-size: 14px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-2); }
.kcm-count { font-size: 40px; line-height: 1; font-weight: 700; letter-spacing: -0.02em; color: var(--ink); }
.kcm-side-t { margin: var(--s2) 0 0; font-size: 18px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.kcm-side-l { margin: var(--s1, 4px) 0 0; font-size: 14px; line-height: 1.45; color: var(--ink-2); }
.kcm-tiles { list-style: none; margin: var(--s4) 0 0; padding: 0; display: grid; gap: var(--s3); }
.kcm-side-raidiam .kcm-tiles { grid-template-columns: minmax(0, 1fr); }
.kcm-side-holder .kcm-tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.kcm-tile {
  display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: var(--s3); row-gap: 2px; align-items: start; align-content: start;
  padding: var(--s3); border-radius: 10px; min-width: 0;
  border: 1px solid var(--hairline); border-left: 3px solid var(--hue);
  background: var(--paper);
}
.kcm-key { grid-row: span 2; display: inline-flex; color: var(--hue); filter: drop-shadow(0 0 6px var(--hue)); }
.kcm-key svg { width: 24px; height: 24px; }
.kcm-name { font-size: 15px; line-height: 1.3; font-weight: 600; color: var(--ink); }
.kcm-holds { font-size: 14px; line-height: 1.4; color: var(--ink-2); }
.kcm-caption { margin: var(--s4) 0 0; font-size: 14px; line-height: 1.5; color: var(--ink-2); }
@media (max-width: 1099px) {
  .kcm-sides { grid-template-columns: minmax(0, 1fr); }
  .kcm-side-raidiam .kcm-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .kcm-side-holder .kcm-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .kcm-side { padding: var(--s4); }
  .kcm-side-raidiam .kcm-tiles, .kcm-side-holder .kcm-tiles { grid-template-columns: minmax(0, 1fr); }
}

/* ---- THE ROTATION FIGURE ON /security/keys ---- */
.kcr { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s3); }
.kcr-row { padding: var(--s4); border-radius: 12px; border: 1px solid var(--hairline); border-top: 2px solid var(--hue); background: var(--paper-alt); }
.kcr-act { display: grid; grid-template-columns: minmax(0, 14rem) auto minmax(0, 12rem) auto minmax(0, 1fr); align-items: center; gap: var(--s3); }
.kcr-act p { margin: 0; }
.kcr-what { display: flex; align-items: center; gap: var(--s3); font-size: 16px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.kcr-key { display: inline-flex; flex: 0 0 auto; color: var(--hue); filter: drop-shadow(0 0 6px var(--hue)); }
.kcr-key svg { width: 24px; height: 24px; }
.kcr-arrow { display: inline-flex; color: var(--brand-strong); }
.kcr-arrow svg { width: 22px; height: 22px; }
.kcr-h { font-size: 14px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-2); }
.kcr-who { font-size: 15px; line-height: 1.4; font-weight: 600; color: var(--ink); }
.kcr-t { font-size: 15px; line-height: 1.45; color: var(--ink-row); }
.kcr-tenant { margin: var(--s3) 0 0; padding-top: var(--s3); border-top: 1px solid var(--hairline); display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); font-size: 14px; line-height: 1.45; color: var(--ink-2); }
.kcr-tenant-h { font-weight: 600; color: var(--ink-row); }
@media (max-width: 899px) {
  .kcr-act { grid-template-columns: minmax(0, 1fr); gap: var(--s2); }
  .kcr-arrow { transform: rotate(90deg); justify-self: start; margin-left: 2px; }
}

/* ---- THE KEYS PAGE'S OWN BANDS ---- */
.kc-band-h { margin: 0; font-size: 28px; line-height: 1.2; font-weight: 700; letter-spacing: -0.02em; color: var(--ink); }
.kc-band-l { margin: var(--s2) 0 var(--s5); max-width: 46rem; font-size: 16px; line-height: 1.55; color: var(--ink-2); }
.kc-drawer { border-top: 1px solid var(--hairline); border-bottom: 1px solid var(--hairline); }
.kc-drawer > summary { display: flex; align-items: center; gap: var(--s3); padding: var(--s4) 0; cursor: pointer; list-style: none; }
.kc-drawer > summary::-webkit-details-marker { display: none; }
.kc-drawer > summary::before { content: ""; width: 8px; height: 8px; flex: 0 0 auto; border-right: 2px solid var(--brand-strong); border-bottom: 2px solid var(--brand-strong); transform: rotate(-45deg); transition: transform 160ms ease; }
.kc-drawer[open] > summary::before { transform: rotate(45deg); }
.kc-drawer-t { margin: 0; font-size: 18px; font-weight: 700; color: var(--ink); }
.kc-drawer-body { padding-bottom: var(--s5); max-width: 52rem; }
@media (prefers-reduced-motion: reduce) { .kc-drawer > summary::before { transition: none; } }
.kc-page .as-rotation .sec-config { margin-top: var(--s5); max-width: 46rem; }

/* ---- src/parts/ldr.css ---- */
/* /live-demo: the page and its one instrument, packages/ui/partials/ldr-check.ejs.
 *
 * THE TREATMENTS ARE components/diagram-section.tsx's: the hub card for the anchor and the answer,
 * lit cards for the parties, pedestals under the anchor and the two leaves, bezier wires under a
 * glow, a filled arrowhead into the answer, and the ambient pool. The shared parts come from rw.css
 * by class; this file places them.
 *
 * IDENTITY HUES ON THE PARTIES, STATE COLOUR ON THE VERDICT ONLY. Each party carries `--hue` on its
 * own element. The verdict is derived rather than observed, so a compatible verdict is brand and
 * never green. --att and --no appear once each, beside the verdict word they colour.
 */

/* ---- THE PAGE ---- */
.ldr-page { --page-max: 1472px; }
.ldr-top-band { position: relative; padding-block: var(--s6) var(--s5); display: grid; gap: var(--s6); }
.ldr-copy > * { margin: 0; }
.ldr-copy .sc-eyebrow { font-size: 14px; font-weight: 600; letter-spacing: 0.22em; text-transform: uppercase; color: var(--brand-strong); }
.ldr-copy .sc-headline { margin-top: var(--s4); line-height: 1.02; letter-spacing: -0.035em; }
.ldr-copy .sc-headline .accent { color: var(--brand-strong); }
.ldr-copy .sc-lead { margin-top: 1.25rem; max-width: 34rem; font-size: 17px; line-height: 1.55; color: var(--ink-lead); }
/* BETWEEN 1100 AND 1500 THE COPY TAKES TWO COLUMNS OVER THE FIGURE, headline left and lead right,
   which is the rhythm your-own-assistant.ejs set. Above 1500 the copy sits beside the figure. */
@media (min-width: 1100px) and (max-width: 1499px) {
  .ldr-copy { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: var(--s7); grid-template-areas: "eyebrow eyebrow" "head lead"; align-items: end; }
  .ldr-copy .sc-eyebrow { grid-area: eyebrow; }
  .ldr-copy .sc-headline { grid-area: head; }
  .ldr-copy .sc-lead { grid-area: lead; }
}
@media (min-width: 1500px) {
  .ldr-top-band { grid-template-columns: minmax(0, 420px) minmax(0, 1fr); align-items: start; }
  .ldr-copy { padding-top: var(--s6); position: sticky; top: var(--s6); }
  .ldr-copy .sc-headline .accent { display: block; }
}

/* ---- THE OUTCOME ROW, the reference's benefits row: ringed 52px glyphs, hairlines between ---- */
.ldr-payoff { padding-block: var(--s6); }
.ldr-outcomes { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); }
.ldr-outcomes li { display: flex; flex-direction: column; align-items: center; text-align: center; padding: 0 var(--s4); }
.ldr-outcomes li + li { border-left: 1px solid var(--hairline); }
.ldr-outcome-i { width: 52px; height: 52px; }
.ldr-outcome-i svg { width: 26px; height: 26px; }
.ldr-outcome-t { margin: var(--s4) 0 0; font-size: 18px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.ldr-outcome-l { margin: var(--s2) 0 0; max-width: 19rem; text-wrap: balance; font-size: 15px; line-height: 1.5; color: var(--ink-2); }
@media (max-width: 900px) {
  .ldr-outcomes { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: var(--s6); }
  .ldr-outcomes li + li { border-left: 0; }
  .ldr-outcomes li:nth-child(even) { border-left: 1px solid var(--hairline); }
}
@media (max-width: 480px) {
  .ldr-outcomes { grid-template-columns: minmax(0, 1fr); }
  .ldr-outcomes li:nth-child(even) { border-left: 0; }
}

/* ---- THE INSTRUMENT ---- */
.ldr { position: relative; margin: 0; min-width: 0; display: grid; gap: var(--s5); }
.ldr-glow { top: 260px; }

/* THE CONTROL BAR, the action the page leads with. Two selects and the button in one row, as the
   reference's trust check bar draws them, wrapping below 760. */
.ldr-bar {
  position: relative; z-index: 1;
  display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) auto; gap: var(--s4); align-items: end;
  padding: var(--s4) var(--s5); border-radius: 14px;
  border: 1px solid color-mix(in srgb, var(--teal-dark) 30%, transparent);
  background: linear-gradient(180deg, var(--paper-alt) 0%, var(--paper) 100%);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--brand-strong) 25%, transparent);
}
.ldr-field { display: grid; gap: var(--s2); min-width: 0; }
.ldr-field-l { font-size: 14px; font-weight: 600; color: var(--ink-2); }
.ldr-select {
  width: 100%; min-height: 44px; padding: 0 var(--s4);
  border-radius: 10px; border: 1px solid var(--rule);
  background: var(--paper); color: var(--ink); font: inherit; font-size: 15px;
}
.ldr-select:focus-visible { outline: 2px solid var(--brand-strong); outline-offset: 2px; }
.ldr-run { min-height: 44px; }
@media (max-width: 1023px) {
  .ldr-bar { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .ldr-run { grid-column: 1 / -1; width: 100%; justify-content: center; }
}
@media (max-width: 640px) {
  .ldr-bar { grid-template-columns: minmax(0, 1fr); }
}

/* THE STAGE. The anchor, a rail, the middle row, the join and the answer, all centred. */
.ldr-stage { position: relative; z-index: 1; display: grid; justify-items: center; }
.ldr-anchor-row { display: grid; justify-items: center; width: 100%; }
.ldr-card { width: 100%; max-width: 360px; text-align: center; }
.ldr-anchor-row .ldr-card { max-width: 460px; }
/* WIDE, THE ANCHOR READS AS TWO LINES: its kind and name, then its host and where it came from. It
   is the one card every wire ends on, and stacked it pushed the answer below a 900px window. */
@media (min-width: 900px) {
  .ldr-anchor-row .ldr-card { max-width: 640px; display: flex; flex-wrap: wrap; justify-content: center; align-items: baseline; column-gap: var(--s3); padding: var(--s3) var(--s5); }
  .ldr-anchor-row .ldr-card > .ldr-name { margin-top: 0 !important; }
  .ldr-anchor-row .ldr-card > .ldr-host { flex-basis: auto; }
  .ldr-anchor-row .ldr-card > .ldr-src { margin-top: var(--s1) !important; }
  .ldr-anchor-row .ldr-card > .ldr-kind { flex-basis: auto; }
}
.ldr-card > p { margin: 0; }
.ldr-card.rw-hub { padding: var(--s4) var(--s5); }
.ldr-kind { font-size: 14px; font-weight: 600; letter-spacing: 0.18em; text-transform: uppercase; color: var(--hue, var(--brand-strong)); }
.ldr-card[data-role="anchor"] .ldr-kind { color: var(--brand-strong); }
.ldr-name { margin-top: var(--s1) !important; font-size: 17px; font-weight: 700; line-height: 1.3; color: var(--ink); }
.ldr-host { margin-top: var(--s1) !important; font-family: var(--mono); font-size: 14px; line-height: 1.4; color: var(--ink-2); overflow-wrap: anywhere; }
.ldr-src { margin-top: var(--s3) !important; display: flex; justify-content: center; font-size: 14px; }
.ldr-src-declared { align-items: center; gap: var(--s2); color: var(--ink-2); }
.ldr-dot { width: 7px; height: 7px; border-radius: 50%; border: 1px solid var(--ink-2); }
.ldr-caveat { margin-top: var(--s1) !important; font-size: 14px; color: var(--ink-2); }
.ldr-ped { margin-bottom: calc(-1 * var(--s3)); }

/* A RAIL is a vertical wire between two cards, with the hop word on it. The line is a pseudo
   element so the label can sit over it on the page ground. */
.ldr-rail { position: relative; display: flex; align-items: center; justify-content: center; min-height: 36px; width: 100%; }
.ldr-rail::before {
  content: ""; position: absolute; left: 50%; top: 0; bottom: 0; width: 2px; transform: translateX(-50%);
  background: var(--hue, var(--teal-dark)); opacity: 0.8;
  box-shadow: 0 0 8px var(--hue, var(--teal-dark));
}
.ldr-rail-l {
  position: relative; padding: 2px var(--s3); border-radius: 999px;
  border: 1px solid var(--hairline); background: var(--paper);
  font-size: 14px; line-height: 1.4; color: var(--ink-2); text-align: center;
}

/* THE MIDDLE ROW, WIDE. Five cells in a row: agent, wire, authority, wire, resource. THE COLUMNS ARE
   SIZED IN PER CENT, 25, 9, 32, 9 and 25, so the two side columns have their centres at exactly 12.5
   and 87.5 per cent at every width, which is where the join drawing in the partial meets them. With
   fr units the centres moved with the width and the wires missed the tails by up to 13px at 900.
   Every column opens with a 68px pedestal, so the first card in each starts at one height and the
   wires meet all three at one line. */
.ldr-mid {
  --line: 130px;
  width: 100%;
  display: grid; align-items: stretch;
  grid-template-columns: minmax(0, 25%) minmax(0, 9%) minmax(0, 32%) minmax(0, 9%) minmax(0, 25%);
  grid-template-areas: "agent wa auth wr res";
}
.ldr-col[data-col="authority"] .ldr-card { max-width: 440px; }
.ldr-col { display: flex; flex-direction: column; align-items: center; min-width: 0; padding: 0 var(--s2); }
.ldr-col[data-col="agent"] { grid-area: agent; }
.ldr-col[data-col="authority"] { grid-area: auth; }
.ldr-col[data-col="resource"] { grid-area: res; }
.ldr-wire[data-wire="agent"] { grid-area: wa; }
.ldr-wire[data-wire="resource"] { grid-area: wr; }
.ldr .ldr-narrow { display: none; }
.ldr .ldr-fork { display: none; }
/* THE TAIL carries each side's line down to the bottom of the row, where the join starts, so a
   shorter column does not leave its wire starting in the air. */
.ldr-tail { flex: 1 1 auto; min-height: 16px; width: 2px; background: var(--hue); opacity: 0.8; box-shadow: 0 0 8px var(--hue); }

/* A WIRE is horizontal, from the authority out to a side, at the height of the first card's middle.
   The arrowhead points at the side, because the authority lists it. */
.ldr-wire { position: relative; }
.ldr-wire::before {
  content: ""; position: absolute; left: 0; right: 0; top: var(--line); height: 2px;
  background: var(--d-violet); opacity: 0.85; box-shadow: 0 0 8px var(--d-violet);
}
.ldr-wire::after {
  content: ""; position: absolute; top: calc(var(--line) - 5px); width: 10px; height: 12px;
  background: var(--hue);
}
.ldr-wire[data-wire="agent"]::after { left: 0; clip-path: polygon(0 50%, 100% 0, 100% 100%); }
.ldr-wire[data-wire="resource"]::after { right: 0; clip-path: polygon(0 0, 100% 50%, 0 100%); }
.ldr-wire-l { position: absolute; left: 0; right: 0; top: calc(var(--line) - 8px); transform: translateY(-100%); text-align: center; font-size: 14px; line-height: 1.3; color: var(--ink-2); padding: 0 var(--s1); }

.ldr-join { width: 100%; height: 52px; }
.ldr .ldr-join-narrow { display: none; }
.ldr-head {
  display: block; width: 16px; height: 12px; margin-top: -12px;
  background: var(--brand-strong); clip-path: polygon(0 0, 100% 0, 50% 100%);
  filter: drop-shadow(0 0 6px var(--brand-strong));
}

/* THE MIDDLE ROW, NARROW. The authority on top, the fork, and the two sides under it, side by
   side, because the claim is that they meet. The hop words move onto rails inside each side. */
@media (max-width: 899px) {
  .ldr-mid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-template-areas: "auth auth" "fork fork" "agent res";
  }
  .ldr-wire { display: none; }
  .ldr .ldr-fork { display: block; grid-area: fork; width: 100%; height: 56px; }
  .ldr-fork .rw-wire { stroke: var(--d-violet); }
  .ldr .ldr-narrow { display: flex; }
  .ldr .ldr-join-wide { display: none; }
  .ldr .ldr-join-narrow { display: block; }
}

/* ---- THE ANSWER ---- */
.ldr-answer { width: 100%; max-width: 620px; margin-top: var(--s3); display: grid; gap: var(--s3); justify-items: center; }
.ldr-answer > p, .ldr-answer > ul, .ldr-answer > h2 { margin: 0; }
/* A RUN LANDS ON THE ANSWER, with the row of cards above it still in view where the window is tall
   enough: the margin leaves room for the cards and never less than the 62px sticky masthead. */
.ldr-answer { scroll-margin-top: clamp(88px, calc(100vh - 520px), 400px); }
.ldr-answer-t { font-size: 14px; font-weight: 600; letter-spacing: 0.22em; text-transform: uppercase; color: var(--brand-strong); }
.ldr-idle { font-size: 17px; color: var(--ink-lead); }
.ldr-verdict { font-size: 34px; font-weight: 700; line-height: 1.1; letter-spacing: -0.02em; color: var(--brand-strong); }
.ldr-verdict[data-verdict="partly"], .ldr-verdict[data-mode="unsettled"] { color: var(--att); }
.ldr-verdict[data-verdict="incompatible"], .ldr-verdict[data-mode="refused"] { color: var(--no); }
.ldr-verdict[data-mode="declared"] { color: var(--ink); }
.ldr-trouble { font-size: 16px; line-height: 1.5; color: var(--ink); max-width: 30rem; }
.ldr-failed { list-style: none; padding: 0; font-family: var(--mono); font-size: 14px; color: var(--ink-2); }
.ldr-tools { list-style: none; padding: 0; width: 100%; display: grid; gap: var(--s2); text-align: left; }
.ldr-tool {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.2fr); gap: var(--s3); align-items: baseline;
  padding: var(--s2) var(--s3); border-radius: 8px; border: 1px solid var(--hairline); background: var(--paper);
  font-size: 14px;
}
.ldr-tool-n { color: var(--ink); overflow-wrap: anywhere; }
.ldr-tool-t { color: var(--brand-strong); overflow-wrap: anywhere; }
.ldr-tool-w { color: var(--ink-2); }
.ldr-tool[data-inside="false"] .ldr-tool-t { color: var(--ink-2); text-decoration: line-through; }
.ldr-gate, .ldr-env { font-size: 14px; line-height: 1.5; color: var(--ink-2); max-width: 34rem; }
.ldr-gate { color: var(--ink); }
.ldr-more { font-size: 15px; }

/* THE PHONE STATE. The cards lose their horizontal padding and the tool rows stack their values. */
@media (max-width: 640px) {
  .ldr-card.rw-card { padding: var(--s3) var(--s3) var(--s4); }
  .ldr-name { font-size: 15px; }
  .ldr-tool { grid-template-columns: minmax(0, 1fr); gap: var(--s1); }
  .ldr-verdict { font-size: 28px; }
  .ldr-card.rw-hub { padding: var(--s3) var(--s4); }
}

/* ---- src/parts/live.css ---- */
/* The live demonstration figure and the journey header slots it arrives with.
   Partials: packages/ui/partials/resolve-seq.ejs, packages/ui/partials/journey-head.ejs.

   ONE BRAND ELEMENT. The Connect panel is the only object in the figure that carries the brand
   fill, and every rule that names var(--teal) sits under [data-treat="product"] so the one colour
   rule can see it. The agent, the platform and the resource are the customer's and the reference
   estate's: a card ground, a rule stroke, ink text. The rail's step markers take var(--teal-dark),
   which is the accent the site already gives a link and a button, on a var(--wash-teal) ground,
   which is the ground it already gives a call to action. Neither is the product fill.

   THE THREE IDENTITY HUES, AND THE ONE TREATMENT. The agent takes --d-blue, the platform --d-magenta
   and the resource --d-sand, which are the same three the hero instrument gives them in
   packages/ui/partials/lvp-arrive.ejs, so a reader carries one colour from the picture into the
   worked detail. A hue says WHICH panel and nothing else. Raidiam Connect keeps var(--teal), which
   marks a Raidiam product everywhere on this site: the hero's fourth hue, --d-violet, belongs to the
   authority, and the authority is what Connect publishes for rather than Connect itself.

   NO GREEN. Green on this site means proven or read on the wire. Every panel in this figure is
   drawn from the estate declaration rather than run, so a green tick beside any of it would be a
   false claim in the site's own colour language. The ticks take the colour of the text around
   them. The one red is the refusal in the resource list, which names a refusal rather than an
   absence of proof.

   WHAT HAPPENS BELOW 1440. Three columns with a wire between them is the shape that breaks a
   narrow screen. The flow is a five track grid at full width and one track at 1180 and below, and
   the wires turn through ninety degrees with it rather than being hidden, because the wire is what
   says the request travels. The rail steps go four across, then two at 1100, then one at 620.

   1180 IS A MEASURED NUMBER, NOT A ROUND ONE. Below it the side columns fall under about 280px of
   inner width and records.agents.showcase.raidiam.io no longer sets on one line at 13px mono, so
   the host broke mid label. Measured at 1024 before the change: the resource panel was 236px wide
   and 1489px tall, with the host reading "ase.raidiam.io". Every width from 360 to 1440 was then
   checked for sideways scroll, and scrollWidth equals clientWidth at all seventeen. */

/* ---- the journey header's two optional slots ---- */

/* The same eyebrow serves the page header and the demonstration band's head. */
.journey-head .jh-eyebrow, .band-head .jh-eyebrow {
  margin: 0;
  font-size: var(--t-label); font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--teal-dark);
}
.journey-head .jh-note {
  border: 1px solid var(--rule);
  border-left: 3px solid var(--teal-dark);
  border-radius: var(--r-2);
  background: var(--white);
  padding: var(--s4) var(--s5);
  display: grid; gap: var(--s3);
  max-width: var(--measure-notes);
}
.journey-head .jh-note p { font-size: var(--t-small); color: var(--ink-2); margin: 0; }
.journey-head .jh-note .jh-note-head { font-weight: 600; color: var(--ink); }

/* ---- the four step rail ---- */

.live-seq { display: grid; gap: var(--s6); }

.live-seq .ls-rail {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s4);
}
.live-seq .ls-step {
  position: relative;
  display: grid; grid-template-columns: auto minmax(0, 1fr); grid-template-rows: auto auto;
  column-gap: var(--s3); row-gap: var(--s1);
  align-items: start;
  padding-right: var(--s5);
}
/* The connector between one step and the next. It stops short of the following marker rather than
   running under it, and the last step draws none.

   IT IS A REAL ELEMENT AND NOT A PSEUDO ELEMENT ON THE STEP, which is the difference between a
   number axe measures and a number it skips. As .ls-step::after it made .ls-step an ancestor of the
   step number carrying a pseudo element, and axe answered "Element's background color could not be
   determined due to a pseudo element" for three of the four numbers: incomplete, not passing, so
   the contrast of the accent on the teal wash went unchecked. Measured, not reasoned about: the
   three incompletes were in the axe run and went to zero when this became a span. */
.live-seq .ls-link {
  position: absolute; top: 17px;
  left: calc(100% - var(--s5) + var(--s1)); right: calc(var(--s1) - var(--s4));
  height: 2px; background: var(--rule);
}
.live-seq .ls-step:last-child { padding-right: 0; }

.live-seq .ls-marker {
  grid-row: 1; align-self: center;
  width: 34px; height: 34px; border-radius: var(--pill);
  display: grid; place-items: center;
  background: var(--wash-teal);
  border: 1.5px solid var(--teal-dark);
  box-shadow: 0 0 18px -6px color-mix(in srgb, var(--teal-dark) 70%, transparent);
}
.live-seq .ls-n { font-size: var(--t-label); font-weight: 700; color: var(--teal-dark); }
.live-seq .ls-step-name { grid-column: 2; grid-row: 1; align-self: center; font-size: var(--t-body); font-weight: 600; color: var(--ink); }
.live-seq .ls-step-note { grid-column: 2; grid-row: 2; font-size: var(--t-small); color: var(--ink-2); }
/* A STEP WITH NO NOTE CLOSES ITS ROW RATHER THAN HOLDING IT OPEN. The rail carries the four names
   and no notes on /use-cases/resolved-not-registered, because the hero card, the rail and the panel
   tag each named the same step and the note under a rail step said what the panel beside it draws.
   Without this the empty span still takes its grid row and the rail stands 20px taller than its
   content. */
.live-seq .ls-step-note:empty { display: none; }

/* ---- the three columns ---- */

/* THE FLOW IS ONE GRID AND EVERY PANEL IS PLACED IN IT.
   The middle column holds two panels, so the wire into it has to meet Connect and the wire out of
   it has to leave the platform. Wrapping the middle pair in a column of their own centred both
   wires on the gap between them, pointing at nothing. Placing all seven children in the same grid
   puts each wire in the row of the panel it touches, and it also makes the source order the
   reading order: agent, wire, Connect, wire, platform, wire, resource. That is the order the one
   column layout at 980 needs, so the narrow case falls out of the same markup. */
.live-seq .ls-flow {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--s9) minmax(0, 1.12fr) var(--s9) minmax(0, 1fr);
  grid-template-rows: auto auto minmax(0, 1fr);
  align-items: stretch;
}
.live-seq .ls-agent { grid-column: 1; grid-row: 1 / -1; }
.live-seq .ls-join-a { grid-column: 2; grid-row: 1; }
.live-seq .ls-connect { grid-column: 3; grid-row: 1; }
.live-seq .ls-join-down { grid-column: 3; grid-row: 2; }
.live-seq .ls-platform { grid-column: 3; grid-row: 3; }
.live-seq .ls-join-b { grid-column: 4; grid-row: 3; }
.live-seq .ls-resource { grid-column: 5; grid-row: 1 / -1; }

/* THE HUE PER PANEL. It is set on the panel and read by the rules under it, so one line changes an
   actor's colour everywhere it appears rather than in four places. The Connect panel sets none: the
   rules that paint it all sit under [data-treat="product"] and name var(--teal). */
.live-seq .ls-agent { --ls-hue: var(--d-blue); }
.live-seq .ls-platform { --ls-hue: var(--d-magenta); }
.live-seq .ls-resource { --ls-hue: var(--d-sand); }

/* A flex column rather than a grid, so the source line can be pushed to the foot of a panel that
   stretches past its own content. */
.live-seq .ls-panel {
  min-width: 0;
  background: var(--white);
  border: 1px solid var(--rule);
  /* The top edge and the inset highlight take the panel's own hue, which is the reference's
     environment card and the same treatment the hero cards use. A panel with no hue keeps the rule,
     so the Connect panel is unchanged. */
  border-top-color: var(--ls-hue, var(--rule));
  box-shadow: inset 0 1px 0 var(--ls-hue, transparent);
  border-radius: var(--r-3);
  padding: var(--s5);
  display: flex; flex-direction: column; gap: var(--s4);
}
/* The panel's own glyph and its step number carry the hue too, so the colour is on the thing that
   names the panel rather than only on its edge. */
.live-seq .ls-agent .ls-glyph, .live-seq .ls-platform .ls-glyph, .live-seq .ls-resource .ls-glyph { color: var(--ls-hue, var(--ink-2)); }
.live-seq .ls-agent .ls-tag-n, .live-seq .ls-platform .ls-tag-n, .live-seq .ls-resource .ls-tag-n { border-color: var(--ls-hue); }
.live-seq .ls-tag {
  margin: 0; display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2);
  font-size: var(--t-label); font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--ink-2);
}
/* The treatment chip closes the row. Every runtime component in the figure is labelled, and the
   Connect panel carries its chip as well as the fill, so the reader is never asked to infer the
   treatment from colour alone. */
.live-seq .ls-tag .treat { margin-left: auto; letter-spacing: normal; text-transform: none; }
.live-seq .ls-tag-n {
  width: 22px; height: 22px; border-radius: var(--pill);
  display: grid; place-items: center;
  border: 1px solid var(--rule);
  letter-spacing: normal;
}

.live-seq .ls-id { display: flex; gap: var(--s3); align-items: center; }
.live-seq .ls-glyph { width: 34px; height: 34px; flex: none; color: var(--ink-2); }
.live-seq .ls-glyph svg { width: 100%; height: 100%; display: block; }
.live-seq .ls-id-text { display: grid; gap: 2px; min-width: 0; }
.live-seq .ls-title { font-size: var(--t-h3); font-weight: 600; line-height: var(--t-h3-line); color: var(--ink); }
.live-seq .ls-sub { font-size: var(--t-small); color: var(--ink-2); overflow-wrap: break-word; }
/* A host sits on its own line at the full width of the panel rather than beside the glyph. Beside
   it, records.agents.showcase.raidiam.io was three characters wider than the space left over and
   broke mid label. */
.live-seq .ls-hosts { margin: calc(0px - var(--s2)) 0 0; display: grid; gap: 2px; min-width: 0; }
/* The break opportunities come from the <wbr> the partial puts after each dot, not from a wrapping
   mode. A grid item's min-width is auto and break-word does not reduce a string's min-content
   width, so records.agents.showcase.raidiam.io held its column open and the page scrolled sideways
   by 19px at 1100, 51 at 1000 and 54 at 990. anywhere cured that and broke the name mid label
   instead. With the joints marked, the name sets on one line where there is room and breaks after
   a dot where there is not. */
.live-seq .ls-hosts .mono { min-width: 0; font-size: 13px; color: var(--ink-2); overflow-wrap: break-word; }

/* ---- the agent ---- */

.live-seq .ls-say {
  margin: 0; padding: var(--s4);
  background: var(--paper-alt);
  border-radius: var(--r-2);
  border: 1px solid var(--rule);
}
.live-seq .ls-say p { margin: 0; font-size: var(--t-body); color: var(--ink); }

.live-seq .ls-facts { margin: 0; display: grid; gap: var(--s3); }
.live-seq .ls-fact { display: grid; gap: 2px; }
.live-seq .ls-facts dt { font-size: var(--t-label); font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-2); }
.live-seq .ls-facts dd { margin: 0; font-size: var(--t-small); color: var(--ink); overflow-wrap: anywhere; }

/* ---- Raidiam Connect, the one product in the picture ----

   The ground is a token rather than a colour-mix, because axe cannot resolve a mix and reports the
   text on it as incomplete rather than passing. The glow is a shadow, where no text lands. */

.live-seq .ls-connect[data-treat="product"] {
  position: relative;
  border: 1.5px solid var(--teal);
  background: var(--wash-teal);
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--teal) 22%, transparent),
    0 0 24px -4px color-mix(in srgb, var(--teal) 45%, transparent),
    0 0 70px -14px color-mix(in srgb, var(--teal) 55%, transparent),
    inset 0 1px 0 0 color-mix(in srgb, var(--teal) 45%, transparent);
}
/* The breath is a second glow layer faded in and out, NOT a keyframe that carries the colour. A
   keyframe block reads to the stylesheet test as a rule whose selector is "from", so a var(--teal)
   inside one is teal on a selector that names no product and the one colour rule refuses it. The
   colour stays on the rule below, which names the product; the animation moves opacity only. */
.live-seq .ls-connect[data-treat="product"]::before {
  content: ""; position: absolute; inset: -2px; border-radius: inherit; pointer-events: none;
  opacity: 0;
  box-shadow:
    0 0 34px -4px color-mix(in srgb, var(--teal) 55%, transparent),
    0 0 96px -12px color-mix(in srgb, var(--teal) 60%, transparent);
  animation: ls-glow 6s ease-in-out infinite alternate;
}
.live-seq .ls-connect[data-treat="product"] .ls-tag { color: var(--teal); }
.live-seq .ls-connect[data-treat="product"] .ls-tag-n { border-color: var(--teal); }
.live-seq .ls-lockup {
  margin: 0; display: flex; flex-wrap: wrap; align-items: center; column-gap: var(--s3); row-gap: var(--s2);
}
.live-seq .ls-wordmark { height: 21px; width: auto; }
.live-seq .ls-connect-word {
  font-size: var(--t-h3); font-weight: 700; letter-spacing: 0.06em; line-height: 1; color: var(--ink);
}
.live-seq .ls-connect-line { margin: 0; font-size: var(--t-small); color: var(--ink-2); }
.live-seq .ls-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s3); }
.live-seq .ls-list li { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--s3); align-items: start; font-size: var(--t-small); color: var(--ink); }
.live-seq .ls-list .mark { width: 15px; height: 15px; margin-top: 3px; }

/* ---- the platform that reads it ---- */

.live-seq .ls-holds {
  margin: 0; display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--s3); align-items: start;
  padding: var(--s3) var(--s4);
  background: var(--wash-no);
  border-radius: var(--r-2);
  font-size: var(--t-small); color: var(--ink);
}
.live-seq .ls-holds .mark { color: var(--no); width: 15px; height: 15px; margin-top: 3px; }
.live-seq .ls-checks {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s2) var(--s4);
}
.live-seq .ls-checks li { display: flex; gap: var(--s2); align-items: center; font-size: var(--t-small); color: var(--ink); }
.live-seq .ls-checks .mark { width: 14px; height: 14px; color: var(--ink-2); }
.live-seq .ls-token {
  margin: 0; padding: var(--s3) var(--s4);
  border: 1px dashed var(--rule); border-radius: var(--r-2);
  font-size: var(--t-small); color: var(--ink);
}

/* ---- the resource ---- */

.live-seq .ls-verdict {
  margin: 0; display: flex; gap: var(--s2); align-items: center;
  padding: var(--s3) var(--s4);
  background: var(--paper-alt);
  border: 1px solid var(--rule);
  border-radius: var(--r-2);
  font-size: var(--t-body); font-weight: 600; color: var(--ink);
}
.live-seq .ls-verdict .mark { width: 17px; height: 17px; color: var(--ink-2); }
.live-seq .ls-items { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s3); }
.live-seq .ls-items li {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--s3); align-items: start;
  padding-bottom: var(--s3); border-bottom: 1px solid var(--rule);
}
.live-seq .ls-items li:last-child { padding-bottom: 0; border-bottom: 0; }
.live-seq .ls-items .mark { width: 16px; height: 16px; margin-top: 3px; color: var(--ink-2); }
.live-seq .ls-item-text { display: grid; gap: 2px; min-width: 0; }
.live-seq .ls-item-label { font-size: var(--t-small); font-weight: 600; color: var(--ink); }
.live-seq .ls-item-note { font-size: var(--t-small); color: var(--ink-2); overflow-wrap: anywhere; }
/* Red names a refusal, never a treatment and never an unproven step. */
.live-seq .ls-items li[data-mark="no"] .mark { color: var(--no); }
.live-seq .ls-items li[data-mark="no"] .ls-item-label { color: var(--no); }

/* ---- what the figure draws, said on the figure ---- */

/* margin-top: auto pushes the source line to the foot of a panel that stretches past its content.
   It lives on this rule and not on a second one earlier in the file, where `margin: 0` here would
   have silently undone it. */
.live-seq .ls-drawn {
  margin: auto 0 0; padding-top: var(--s3); border-top: 1px solid var(--rule);
  font-size: var(--t-label); color: var(--ink-2);
}
.live-seq .ls-note { margin: 0; font-size: var(--t-small); color: var(--ink-2); max-width: var(--measure-notes); }

/* ---- the wires ----

   The pulse travels from the sender to the receiver and says which way the request goes. It is
   decoration: the arrowhead carries the direction without it, and reduced motion stops it. */

.live-seq .ls-join { display: grid; place-items: center; padding: 0 var(--s2); }
.live-seq .ls-wire { position: relative; display: block; width: 100%; height: 2px; background: var(--rule); }
.live-seq .ls-wire::after {
  content: ""; position: absolute; right: 0; top: 50%;
  width: 8px; height: 8px; transform: translateY(-50%) rotate(45deg);
  border-top: 2px solid var(--rule); border-right: 2px solid var(--rule);
}
.live-seq .ls-pulse {
  position: absolute; top: 50%; left: 0; width: 7px; height: 7px; margin: -3.5px 0 0 -3.5px;
  border-radius: var(--pill); background: var(--teal-dark);
  animation: ls-travel 3.4s ease-in-out infinite;
}

/* The join inside the middle column runs downward at every width. */
.live-seq .ls-join-down { padding: var(--s4) 0; }
.live-seq .ls-join-down .ls-wire { width: 2px; height: var(--s7); }
.live-seq .ls-join-down .ls-wire::after {
  right: 50%; top: auto; bottom: 0;
  transform: translateX(50%) rotate(135deg);
}
.live-seq .ls-join-down .ls-pulse { animation-name: ls-travel-down; }

@keyframes ls-travel {
  0% { left: 0; opacity: 0; }
  12% { opacity: 1; }
  88% { opacity: 1; }
  100% { left: 100%; opacity: 0; }
}
@keyframes ls-travel-down {
  0% { top: 0; opacity: 0; }
  12% { opacity: 1; }
  88% { opacity: 1; }
  100% { top: 100%; opacity: 0; }
}
@keyframes ls-glow {
  from { opacity: 0; }
  to { opacity: 1; }
}

@media (max-width: 1100px) {
  .live-seq .ls-rail { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s5) var(--s4); }
  .live-seq .ls-step:nth-child(2) { padding-right: 0; }
  .live-seq .ls-step:nth-child(2) .ls-link { display: none; }
}

@media (max-width: 1180px) {
  .live-seq .ls-flow { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; }
  .live-seq .ls-agent, .live-seq .ls-join-a, .live-seq .ls-connect,
  .live-seq .ls-join-down, .live-seq .ls-platform, .live-seq .ls-join-b,
  .live-seq .ls-resource { grid-column: 1; grid-row: auto; }
  .live-seq .ls-join { padding: var(--s4) 0; }
  .live-seq .ls-join .ls-wire { width: 2px; height: var(--s7); }
  .live-seq .ls-join .ls-wire::after {
    right: 50%; top: auto; bottom: 0;
    transform: translateX(50%) rotate(135deg);
  }
  .live-seq .ls-join .ls-pulse { animation-name: ls-travel-down; }
}

@media (max-width: 620px) {
  .live-seq .ls-rail { grid-template-columns: minmax(0, 1fr); gap: var(--s4); }
  .live-seq .ls-step, .live-seq .ls-step:nth-child(2) { padding-right: 0; }
  .live-seq .ls-link { display: none; }
  .live-seq .ls-panel { padding: var(--s4); }
  .live-seq .ls-checks { grid-template-columns: minmax(0, 1fr); }
}

/* MEASURED, AND THE MEASUREMENT SAYS THIS BLOCK IS THE SECOND LINE AND NOT THE FIRST.
   The base sheet already sets animation-duration: 0.001ms and animation-iteration-count: 1 on
   everything under reduced motion, and an infinite alternate animation held to one iteration of
   0.001ms finishes before it can be seen. Removing these three rules and sampling the page twice,
   900ms apart, under a reduced motion context: no pulse moved and no animation was running, the
   same reading as with them. The probe is calibrated, because the same sampling under
   no-preference caught all three pulses moving and the glow's opacity rising from 0.014 to 0.116.
   So this block states the intent and holds if the global rule is ever narrowed. It is not what
   stops the motion today, and saying otherwise would be a claim nothing supports. */
@media (prefers-reduced-motion: reduce) {
  .live-seq .ls-pulse { animation: none !important; opacity: 1; left: 0; top: 0; }
  .live-seq .ls-join-down .ls-pulse, .live-seq .ls-join .ls-pulse { animation: none !important; }
  .live-seq .ls-connect[data-treat="product"]::before { animation: none !important; opacity: 0; }
}

/* ---- src/parts/lv-page.css ---- */
/*
 * /use-cases/resolved-not-registered, the sixth use case.
 * View: apps/site/src/views/live.ejs. Content: apps/site/content/journey-2-admit-with-no-record.md.
 *
 * WHAT THIS FILE IS. The page rules for the one use case that never went through the reference
 * port. Every measure below is read off the ported sibling, packages/ui/src/parts/ss.css, which
 * took them from /tmp/claude-501/rw-live/app/use-cases/02/page.tsx, so the six use cases share one
 * type scale, one band rhythm and one hero column.
 *
 * WHAT IT REFUSES TO DRAW, AND WHY.
 *
 *   NO HERO PHOTOGRAPH. This page drew one, held to the right, with a veil over it. None of its
 *   five siblings does. A photograph on one page of six is what made this route read as another
 *   product, and it was carrying a headline about a control the page no longer has.
 *
 *   NO PANEL AROUND THE CHECK, NO DISCLOSURE RULES, NO QUIET GROUND BAND. The check, the two
 *   disclosures and the strip that sat on --paper-alt are gone from the view, so the rules that
 *   painted them are gone from here. Around 130 lines of this file drew elements no route renders.
 *
 *   NO STATE COLOUR ON AN IDENTITY. The four identity hues below say WHICH actor, and nothing about
 *   whether anything is trusted, permitted or read. Every state word on this page is drawn by
 *   packages/ui/partials/ev.ejs, which refuses an Observed mark that links no artefact, so the two
 *   vocabularies never meet: a hue is an edge and a glyph, a state is a mark beside a word.
 *
 *   NO HUE ON RAIDIAM CONNECT. var(--teal) marks a Raidiam product wherever it appears on this site,
 *   and the Connect panel in the worked example is the one product in the picture. A fifth identity
 *   hue there would replace a treatment a reader already knows with one they would have to learn.
 *
 * THE PREFIX IS lvp- AND EVERY RULE CARRIES IT. Three files paint with an lv- prefix: this one,
 * lv.css, and uc-live-bands.css, which the other use case pages render. A bare `.lv-build` rule
 * here would follow those pages to routes this work never looked at, so every selector below starts
 * at `.lvp-page` or at an lvp- class.
 *
 * EVERY GROUND IS A PLAIN TOKEN. packages/ui/tools/contrast.mjs enumerates token pairs by name and
 * reads no CSS, so a colour-mix under text is gated by nothing. There is no mix in this file.
 */

/* ==========================================================================
   1. The measure, and the band rhythm
   ==========================================================================
   A use case page takes 1216px. `.wrap` reads --page-max on the element it is set on, and the
   reference writes its container as a BOX, so the number is that box less its 64px of padding.

   NO BAND CARRIES A TOP RULE AND EVERY BAND PADS ONLY ABOVE, which is `.wrap.sw-page > .band` in
   ss.css, read on 16 September 2026. The site default puts a hairline over every band, and eleven
   rules down one page is a documentation layout. */
.lvp-page { --page-max: 1216px; }
.wrap.lvp-page > .band { border-top: 0; padding-block: var(--s8) 0; }
.wrap.lvp-page > .lvp-top { padding-block: 3.5rem 0; }
.wrap.lvp-page > .lvp-sum-band { padding-block: var(--s7) 0; }
.wrap.lvp-page > .lvp-tail { padding-block: var(--s7) var(--s8); }
.wrap.lvp-page > .band:last-child { padding-bottom: var(--s8); }

/* ==========================================================================
   2. The hero, and the instrument in it
   ==========================================================================
   THE COPY COLUMN IS 460 AND THE INSTRUMENT TAKES THE 708 BESIDE IT. The sibling, ss.css, sets 500
   beside a figure at a 1376 measure. This page is 1216, so the pair is 460 + 48 + 708, and 708 by
   440 is the frame packages/ui/partials/lvp-arrive.ejs is drawn in. The two numbers are the same
   number: the figure places its words as percentages of that frame, so a column width that did not
   match would put a label off its card.

   THE COPY GOES ON TOP BELOW 1280, WHICH IS CLAUDE.md RULE 5 AND A MEASURED NUMBER. 1280 is the
   viewport at which `.wrap` reaches its full 1216, so above it the figure column is exactly 708 and
   the drawing is at 1:1 with the type inside it. One pixel below, the whole box shrinks while the
   type does not, and at 1200 the three lower cards fall to 182 with 16px titles in them. Under the
   breakpoint the instrument takes the full measure instead, where it is 1152 wide at 1216 and never
   under 690 before the narrow state takes over at 760. */
.lvp-top {
  display: grid;
  grid-template-columns: minmax(0, 460px) minmax(0, 1fr);
  gap: var(--s7);
  align-items: center;
}
.lvp-top-copy { max-width: 31.25rem; }
.lvp-top-copy > * { margin: 0; }
.lvp-top-figure { min-width: 0; }
@media (max-width: 1279px) {
  .lvp-top { grid-template-columns: minmax(0, 1fr); gap: var(--s6); align-items: start; }
  .lvp-top-copy { max-width: 42rem; }
}

/* THE HERO TYPE AND ITS RHYTHM, the sibling's line for line, which is the reference's:
     eyebrow  14px, weight 600, uppercase, tracking 0.28em, --slate
     h1       mt-4, 52px, weight 700, line height 1.04, tracking -0.03em
     lead     mt-5, max-width 460, 17px, line height 1.6, --ink-lead
     actions  mt-8, gap-4
   ONE VALUE IS HELD RATHER THAN COPIED. The eyebrow is 14px, not the reference's 13px, because
   14px is the floor and packages/ui/tests/stylesheet.test.ts enforces it across the bundle. */
.lvp-top-copy .sc-eyebrow { letter-spacing: 0.28em; color: var(--slate); }
/* THE SIZE IS THE SCALE'S, NOT THIS PAGE'S. It read 52px, a literal, and the media query below then
   handed the same headline back to --t-display under 760. So one headline had two sizes from two
   files, and the route's own step in packages/ui/src/parts/display-scale.css already resolves to
   clamp(36px, 4.2vw, 52px) here: 52px at 1440 and a size that fits at 390. Naming the token gives
   the identical rendering at 1440 and stops the literal drifting from the scale. */
.lvp-top-copy .sc-headline { margin-top: var(--s4); max-width: 100%; font-size: var(--t-display); line-height: 1.04; letter-spacing: -0.03em; }
/* TWO LINES, AS THE SIBLING SETS IT: the statement, then the accented tail under it. */
.lvp-top-copy .sc-headline .accent { display: block; }
.lvp-top-copy .sc-lead { margin-top: 1.25rem; max-width: 28.75rem; color: var(--ink-lead); }
.lvp-top-copy .sc-lead p { margin: 0; font-size: 17px; line-height: 1.6; color: var(--ink-lead); }
.lvp-top-copy .sc-actions { margin-top: var(--s6); gap: var(--s4); }
@media (max-width: 760px) {
  /* The reference is not designed narrow. 52px in a 360px column breaks a headline mid word, so the
     display scale takes over below the width the reference's own measure stops working at. */
  .lvp-top-copy .sc-headline { font-size: var(--t-display); line-height: var(--t-display-line); }
}

/* ==========================================================================
   2b. The hero instrument
   ==========================================================================
   packages/ui/partials/lvp-arrive.ejs. Four cards on one drawing: the agent, the authority above,
   the platform in the middle holding nothing, and the resource.

   THE WRAPPER HOLDS THE ASPECT RATIO AND THAT IS WHAT MAKES THE FIGURE WORK. The svg carries the
   wires in a 708 by 440 viewBox and every card is placed as a percentage of the same two numbers.
   A box of any width with that ratio puts a card edge exactly where the wire meets it, so there is
   one set of coordinates rather than two that drift.

   EACH CARD IS THE REFERENCE'S ENVIRONMENT CARD: a vertical gradient panel, a hairline border, and
   an inset highlight in the card's own hue with the top border tinted to match, so the card reads as
   lit from above by the thing it is. */
/* THE FIGURE HAS A NATURAL SIZE AND IT STOPS THERE. The box carries the aspect ratio, so every
   coordinate in it scales with the width, and the words inside it do not: at the 1216 measure in the
   stacked state the drawing was 1215 wide, the arrowheads were 72 per cent larger than drawn and the
   resolve channel stood 250px of empty. Measured at 1279 before this line. Capped at its own 708 and
   centred, the figure is 1:1 from 708 up and scales down under it, which is the one direction a
   drawing with fixed size type can take. */
.lvp-arrive { position: relative; width: 100%; max-width: 44.25rem; margin-inline: auto; aspect-ratio: 708 / 500; }
.lvp-arrive-wires { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
/* The stroke keeps its width whatever the box does to the viewBox, so a figure at 420 wide draws the
   same 1.6px wire as one at 708. */
.lvp-arrive-wire { stroke-width: 1.6; vector-effect: non-scaling-stroke; }
/* THE ASK IS DASHED AND THE ANSWER IS SOLID. The platform's question travels; the authority's
   statement is a signed object that already exists. It is the one distinction the two arcs make. */
.lvp-arrive-wire-ask { stroke-dasharray: 4 5; }

.lvp-arrive-node {
  position: absolute;
  display: grid;
  align-content: start;
  grid-template-rows: auto auto 1fr;
  gap: var(--s3);
  padding: var(--s4);
  min-width: 0;
  border: 1px solid var(--rule);
  border-top-color: var(--lvp-hue);
  border-radius: var(--r-2);
  background: linear-gradient(180deg, var(--white), var(--paper-alt));
  box-shadow: inset 0 1px 0 var(--lvp-hue);
}
.lvp-arrive-step {
  display: flex;
  gap: var(--s2);
  align-items: center;
  margin: 0;
  font-size: var(--t-label);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.lvp-arrive-n {
  display: inline-grid;
  place-items: center;
  width: 20px;
  height: 20px;
  border: 1px solid var(--lvp-hue);
  border-radius: 50%;
  font-size: var(--t-label);
  font-weight: 700;
  letter-spacing: normal;
  color: var(--ink);
}
/* THE GLYPH STANDS OVER THE TEXT IN THE THREE LOWER CARDS, and beside it in the authority card.
   A 207px card with a glyph in the column beside the words leaves 165 for a name, and "The records
   and transfers resources" set four lines deep and left the card. The authority card is 320 wide and
   stands alone, so it keeps the row. */
.lvp-arrive-face { display: flex; flex-direction: column; gap: var(--s3); align-items: start; min-width: 0; }
.lvp-arrive-glyph { flex: none; width: 26px; height: 26px; }
.lvp-arrive-glyph svg { display: block; width: 100%; height: 100%; }
.lvp-arrive-text { display: grid; gap: 3px; min-width: 0; }
.lvp-arrive-name { font-size: var(--t-body); font-weight: 600; line-height: 1.25; color: var(--ink); }
.lvp-arrive-line { font-size: var(--t-small); line-height: 1.45; color: var(--ink-2); }
.lvp-arrive-auth .lvp-arrive-face { flex-direction: row; gap: var(--s3); align-items: center; }

/* THE EMPTY SHELF. The slots are drawn in the rule and the crosses in the faint ink. Neither is the
   refusal red: nothing failed here, the platform simply holds nothing, and that is the state the
   whole page is about. */
/* THE SHELF STANDS OVER ITS SENTENCE RATHER THAN BESIDE IT, for the same reason the glyph does: the
   drawing is 76px of a 175px column and the sentence beside it wrapped to four words a line. It sits
   at the foot of the card, which is where a platform's own store sits in the picture. */
.lvp-arrive-holds {
  display: grid;
  gap: var(--s2);
  justify-items: start;
  margin-top: auto;
  margin: 0;
  padding-top: var(--s3);
  border-top: 1px solid var(--hairline);
  font-size: var(--t-small);
  line-height: 1.4;
  color: var(--ink);
}
.lvp-arrive-shelf { flex: none; width: 76px; height: 18px; fill: none; stroke: var(--rule); stroke-width: 1.2; }
.lvp-arrive-shelf-x { stroke: var(--faint); stroke-width: 1.4; stroke-linecap: round; }

/* THE TWO WORDS ON THE RESOLVE CHANNEL. They sit in the corners the arcs leave empty, the ask on the
   left with the arc that rises and the answer on the right with the arc that falls, each aligned to
   the arc it names. */
.lvp-arrive-arc {
  position: absolute;
  display: grid;
  align-content: center;
  margin: 0;
  font-size: var(--t-small);
  line-height: 1.35;
  color: var(--ink-2);
}
.lvp-arrive-arc-up { text-align: right; }

@media (max-width: 760px) {
  /* THE NARROW STATE IS DESIGNED, NOT STACKED. The wires go, because a bezier drawn for a 708 by 440
     box across a 328px column is a scribble, and the four cards become one column in the order a
     reader meets them. The step number on each card is what carries the sequence the wires carried,
     which is why it is on the card rather than on the wire. */
  .lvp-arrive { position: static; aspect-ratio: auto; display: grid; gap: var(--s4); }
  .lvp-arrive-wires { display: none; }
  .lvp-arrive-node, .lvp-arrive-arc { position: static !important; width: auto !important; height: auto !important; bottom: auto !important; }
  /* THE ORDER IS THE STEP ORDER, AND EVERY CHILD NAMES ITS OWN. The drawing puts the authority first
     in the markup because it is the top of the picture, so the six children are re-ordered here into
     the order a reader meets them: the agent, the ask, the authority, the answer, the platform, the
     resource. An item left on the default order sorts ahead of all of them, which put Act second. */
  .lvp-arrive-agent { order: 1; }
  .lvp-arrive-arc-up { order: 2; text-align: left; }
  .lvp-arrive-auth { order: 3; }
  .lvp-arrive-arc-down { order: 4; }
  .lvp-arrive-plat { order: 5; }
  .lvp-arrive-res { order: 6; }
}

/* ==========================================================================
   3. The walk
   ==========================================================================
   packages/ui/partials/resolve-seq.ejs, at the full measure: the four step rail, then the agent,
   Raidiam Connect over the platform that reads it, and the resource.

   THE READING KEY THAT STOOD OVER IT IS GONE, AND SO ARE ITS RULES. `uc-live-stack` drew four things
   this page reads back and two it does not, as a strip of chips. The hero instrument draws the same
   four as the four nodes of the picture, so the strip was a key to a figure that says what the
   figure says. The rules that sized it went with the call. */
.lvp-figure-head { margin-bottom: var(--s5); }
.lvp-figure-head .sc-eyebrow { letter-spacing: 0.22em; color: var(--slate); }
.lvp-figure-title { margin: 0; max-width: 34ch; }

/* ==========================================================================
   4. The proof strip, removed
   ==========================================================================
   Fifty five rules drew five columns of read titles, notes and evidence marks. The strip is off the
   claim page and its five reads are in `## technical`, which the evidence route renders, so the
   rules that painted it are gone rather than left to be found by the next person searching for
   `.lvp-proof`. packages/ui/partials/lvp-proof.ejs went with them. */

/* ==========================================================================
   5. The outcome row
   ==========================================================================
   packages/ui/partials/lv-build.ejs draws the payoff sentence and the four ringed cells, and lv.css
   sets both. This block states only what is particular to this band: the payoff sits closer to the
   cells than lv.css's centred default, because on this page the two are one node rather than a
   heading over a separate strip. */
.lvp-sum .lv-payoff { margin-bottom: var(--s6); }
@media (max-width: 860px) {
  /* Four cells at 860 come out at 190 each and "What your platform reads" breaks to three lines, so
     the strip goes to two columns and the hairline follows the first of each pair. */
  .lvp-sum .lv-build { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: var(--s6); }
  .lvp-sum .lv-build-cell:nth-child(odd) { padding-left: 0; border-left: 0; }
}
@media (max-width: 520px) {
  .lvp-sum .lv-build { grid-template-columns: minmax(0, 1fr); }
  .lvp-sum .lv-build-cell { padding-left: 0; border-left: 0; }
}

/* ==========================================================================
   6. The worked example, the bound
   ==========================================================================
   packages/ui/partials/uc-live-ceiling.ejs draws the two panels and uc-live-bands.css sets them.
   This block sets the band head over them and nothing else. */
.lvp-bound-title { margin: 0; max-width: 32ch; }
.lvp-bound-lede { max-width: 62ch; }
.lvp-bound-lede p { margin: 0; font-size: 17px; line-height: 1.6; color: var(--ink-lead); }

/* ==========================================================================
   7. The tail
   ==========================================================================
   The evidence link, the closing panel, one call to action and the next use case, in the order every
   ported use case uses them. Each partial carries its own rules; this only spaces the group. */
.lvp-tail > * + * { margin-top: var(--s7); }

/* ---- src/parts/lv-trust.css ---- */
/*
 * /live-demo/boundary, the trust check.
 * View: apps/site/src/views/live-trust.ejs. Content: apps/site/content/live-trust.md.
 * Partials: packages/ui/partials/lv-controls.ejs, packages/ui/partials/lv-panels.ejs,
 *           packages/ui/partials/lvb-figure.ejs.
 *
 * WHAT THIS IS. A port of the reference route /live-demo/boundary, measured out of
 * /tmp/claude-501/rw-live/app/live-demo/boundary/page.tsx rather than read off a screenshot. Every
 * number below is the reference's own, converted from its utility classes at four pixels to the
 * unit: p-5 is 20px, gap-5 is 20px, rounded-2xl is 16px, rounded-xl is 12px, rounded-lg is 8px,
 * px-3.5 py-3 is 14px by 12px.
 *
 * WHERE IT DEPARTS FROM THE REFERENCE, AND WHY.
 *
 * TYPE. The reference sets 10px, 11px, 12px and 13px across about sixty declarations. The floor
 * here is 14px and packages/ui/tests/stylesheet.test.ts holds it over the whole bundle, so those
 * four sizes collapse into one. Everything that follows from that is a spacing decision rather than
 * a size decision: the panels take more of the row, the showcase splits into two columns only above
 * 1500px, and the progress row is designed to run onto two lines rather than being allowed to.
 *
 * COLOUR. The reference writes its greys as alpha over a ground, which the contrast gate cannot
 * name, so each one is resolved to the opaque token nearest it. Its rule is a pale blue at fourteen
 * per cent, which reaches about 1.2 against a card and is under the component floor of 3. The edge
 * of anything a person operates takes var(--rule), which is that hue lifted until it clears the
 * floor. A divider
 * or a card edge that a reader loses nothing by losing takes var(--hairline), which is the soft
 * form. That split is the one the two tokens' own role notes ask for.
 *
 * THE FOUR IDENTITY HUES, AND HOW THEY DIFFER FROM THE STATE COLOURS. --d-blue, --d-violet,
 * --d-magenta and --d-sand mean nothing on their own. They answer WHICH ONE of a set a thing is:
 * which agent in the list, which field of the bar, which step of the check, which destination at the
 * foot. They arrive on an element as --hue, set by the element's position in its own list, and the
 * element reads them with a fallback so a slot outside a set still draws.
 *
 * --ok, --no and --att answer what is TRUE of a thing, and each of them always sits beside a word:
 * an Observed mark with the artefact it read, a refused chip with the word "Not met", a verdict with
 * its name. Where the two meet, state wins: a check row at data-tone="no" repaints its tile in --no
 * over the hue, which is why that rule sits after the hue rule and carries the higher specificity.
 *
 * WHAT THIS FILE REFUSES TO DRAW. No green that is not under an Observed mark or a state chip, both
 * of which are drawn by partials that link an artefact or carry a word. No hue on anything that is
 * not one of a set, which is why the Connect hub and its ring stay brand. No brand fill on the
 * ownership marker token, which marks a Raidiam product and nothing on this page is one.
 */

/* ==========================================================================
   1. The page and its container
   ==========================================================================
   The reference puts `mx-auto max-w-[1536px] px-8` on every section of both live routes. At 1440 the
   gutter token resolves to 32px, which is the reference's own, and it narrows on a phone. */
.lvb-page { background: var(--paper); }
/* THE CONTAINER IS THE SITE'S, NOT A SECOND COPY OF IT. This read `max-width: 1536px` and that is
   wrong twice over: it duplicated `.wrap`, which every other page uses, and it took the reference's
   BOX as a measure when --page-max is the CONTENT width and the gutter sits outside it. The audit
   read this page's measure as 0 because no `main .wrap` existed on it. One formula, one place. */
.lvb-wrap { width: min(100% - 2 * var(--gutter), var(--page-max)); margin-inline: auto; }

/* ==========================================================================
   2. The hero
   ==========================================================================
   THE HERO CARRIES A FIGURE NOW. It used to place a raster globe at the top right, where the mode
   switch and the status line sat on top of it and the headline ran under it. The comp puts the
   instrument beside the copy and the switch above both, so the band is two rows: the switch and the
   last read at the top, the copy and the figure under them.

   The ambient glow is the treatment CLAUDE.md names: one very large, very soft ellipse behind the
   band, which is what stops the ground reading flat. */
.lvb-hero { position: relative; overflow: hidden; }
.lvb-glow {
  position: absolute; left: 50%; top: -220px; width: 1100px; height: 620px; transform: translateX(-30%);
  border-radius: 50%; pointer-events: none;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--teal-dark) 16%, transparent), transparent 72%);
}
.lvb-hero-in { position: relative; padding-top: 28px; padding-bottom: 28px; }
.lvb-hero-top { display: flex; justify-content: flex-end; }
.lvb-hero-row { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s5); align-items: center; }
.lvb-copy { min-width: 0; }
.lvb-eyebrow {
  margin: 0; font-size: var(--t-label); line-height: var(--t-label-line); font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.28em; color: var(--teal-dark);
}
/* THE SIZE COMES FROM THE ROUTE. This page is a use case in the reference and the reference sets 52
   there, so the size is not declared here: src/parts/display-scale.css narrows --t-display for
   /live-demo/boundary and this rule reads it. It scales down rather than being fixed, because this
   site is read at widths the reference never designed for. */
.lvb-h1 {
  margin: 12px 0 0; font-family: var(--display); font-size: var(--t-display);
  line-height: 1.02; letter-spacing: -0.03em; font-weight: 700; color: var(--ink); text-wrap: balance;
}
.lvb-h1 .lvb-accent { color: var(--teal-dark); }
.lvb-lead { margin: 12px 0 0; max-width: 560px; font-size: 16px; line-height: 1.6; color: var(--ink-2); text-wrap: pretty; }

/* ---- The boundary figure. Partial: packages/ui/partials/lvb-figure.ejs ----
   THE FOUR IDENTITY HUES ARE THE FIGURE. Each declared agent and each declared resource takes one of
   --d-blue, --d-violet, --d-magenta and --d-sand by its position in the declared list, and the same
   hue marks that agent in the list below. A hue answers WHICH ONE. It carries no state, which is why
   green, red and amber are absent from the figure: nothing has been read when the hero is drawn.
   The hues arrive from the partial as inline fill and stroke, because a node's hue is a property of
   the entity rather than of the slot it sits in. */
.lvb-fig-hold { min-width: 0; display: flex; justify-content: center; }
.lvb-fig-wrap { width: 100%; max-width: 720px; min-width: 0; }
.lvb-fig { width: 100%; height: auto; display: block; overflow: visible; }
.lvb-fig-globe { fill: none; stroke: var(--teal-dark); stroke-width: 1; opacity: 0.16; }
.lvb-fig-bound { stroke: var(--teal-dark); stroke-width: 1; stroke-dasharray: 3 7; opacity: 0.55; }
.lvb-fig-arc { stroke-width: 1.5; opacity: 0.6; }
.lvb-fig-halo { opacity: 0.16; }
.lvb-fig-ring { fill: none; stroke-width: 1.6; }
.lvb-fig-core { opacity: 0.9; }
.lvb-fig-hub-halo { fill: var(--teal-dark); opacity: 0.12; }
.lvb-fig-hub-ring { fill: none; stroke: var(--teal-dark); stroke-width: 1.4; }
.lvb-fig-hub-core { fill: var(--brand-strong); opacity: 0.85; }
/* THE THREE GROUP NAMES SIT UNDER THE DRAWING AS HTML, not as text inside it. An SVG text element
   scales with the viewBox, so a declared 14px renders at about 12px at 1440 and at about 7px on a
   phone. The stylesheet floor would pass it and a reader would not. The three columns line up with
   the two node columns and the hub by their alignment rather than by a measured offset. */
.lvb-fig-legend {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: baseline;
  gap: var(--s3); margin: var(--s2) 0 0;
}
.lvb-fig-label {
  font-size: var(--t-label); line-height: var(--t-label-line); font-weight: 600;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink-2);
}
.lvb-fig-legend .lvb-fig-label:last-child { text-align: right; }
.lvb-fig-label-hub { color: var(--teal-dark); }

/* The block at the right of the hero: the mode switch, then the state of the last read and the way
   back to an unasked page. Hidden below 1024, which is where the reference hides it. */
.lvb-aside { display: none; }
.lvb-status { display: flex; align-items: center; gap: var(--s4); flex-wrap: wrap; justify-content: flex-end; font-size: var(--t-label); line-height: var(--t-label-line); }
.lvb-status .ev { font-weight: 600; }
.lvb-status-idle { margin: 0; color: var(--ink-2); }
.lvb-reset { display: inline-flex; align-items: center; gap: 6px; color: var(--ink-2); text-decoration: none; }
.lvb-reset:hover { color: var(--ink); }

/* ==========================================================================
   3. The mode switch
   ==========================================================================
   Shell: inline flex, gap 4, radius 12, 4px of padding, a brand edge at 40 per cent and the
   reference's two shadows. Tabs: radius 8, 16px by 8px. The current one takes the brand fill and the
   dark text the brand needs. */
.lvb-modes { display: inline-flex; align-items: center; gap: var(--s3); }
.lvb-modes-label {
  margin: 0; font-size: var(--t-label); line-height: var(--t-label-line); font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.18em; color: var(--ink-2);
}
.lvb-modes-set {
  display: inline-flex; align-items: center; gap: var(--s1); padding: var(--s1);
  border: 1px solid color-mix(in srgb, var(--teal-dark) 40%, transparent);
  border-radius: 12px; background: var(--white);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.2), 0 8px 24px -12px rgba(0, 0, 0, 0.35);
}
.lvb-mode {
  border-radius: 8px; padding: var(--s2) var(--s4); font-size: var(--t-label); line-height: var(--t-label-line);
  font-weight: 600; color: var(--ink-nav); text-decoration: none; white-space: nowrap;
}
.lvb-mode:hover { color: var(--ink); background: var(--paper-alt); }
.lvb-mode[aria-current="page"] { background: var(--teal-deep); color: var(--on-brand); }

/* ==========================================================================
   4. The control bar
   ==========================================================================
   The reference bar is a card at 16px of padding with a 50 per cent panel ground, stacked below
   1024 and a row above it, and the button does not shrink. */
.lvb-bar {
  display: flex; flex-direction: column; align-items: stretch; gap: var(--s4);
  padding: var(--s4); border: 1px solid var(--hairline); border-radius: 16px; background: var(--paper-alt);
}
.lvb-field { flex: 1 1 0; min-width: 0; }
p.lvb-field-label { margin-top: 0; }
.lvb-field-label {
  display: flex; align-items: center; gap: var(--s2); margin-bottom: var(--s2);
  font-size: var(--t-label); line-height: var(--t-label-line); font-weight: 600; color: var(--ink-2);
}
/* The numbered circle. The reference draws it at 16px with a 10px digit; at the 14px floor the digit
   needs 20px of circle to sit in.

   ONE IDENTITY HUE PER FIELD, and the number and the hue say the same thing twice: which of the four
   this is. None of the four hues means anything about the field's value, which is why a field that a
   reader cannot change carries a hue exactly as a select does. The digit stays dark because all four
   hues are light. */
.lvb-n {
  display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px;
  border-radius: var(--pill); background: var(--hue, var(--teal-deep)); color: var(--on-brand);
  font-size: var(--t-label); line-height: 1; font-weight: 700; flex: none;
}
.lvb-bar .lvb-field:nth-child(4n + 1) { --hue: var(--d-blue); }
.lvb-bar .lvb-field:nth-child(4n + 2) { --hue: var(--d-violet); }
.lvb-bar .lvb-field:nth-child(4n + 3) { --hue: var(--d-magenta); }
.lvb-bar .lvb-field:nth-child(4n + 4) { --hue: var(--d-sand); }
.lvb-control { position: relative; display: flex; align-items: center; margin: 0; }
.lvb-control .lvb-i { position: absolute; right: 14px; color: var(--ink-2); pointer-events: none; }
.lvb-select {
  width: 100%; appearance: none; border: 1px solid var(--rule); border-radius: 8px;
  background: var(--white); color: var(--ink); font-family: inherit;
  font-size: var(--t-label); line-height: var(--t-label-line); font-weight: 500;
  padding: 12px 40px 12px 14px;
}
.lvb-select:hover { border-color: color-mix(in srgb, var(--teal-dark) 40%, var(--rule)); }
/* The two fields that are not choices. Same slot, same height, no control and no hover, so a reader
   can see at a glance which two of the four they can change. */
.lvb-control[data-kind="fixed"] { padding: 12px 14px; border: 1px dashed var(--hairline); border-radius: 8px; background: var(--paper); }
.lvb-fixed { font-size: var(--t-label); line-height: var(--t-label-line); color: var(--ink-2); overflow-wrap: anywhere; }
.lvb-run {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2); flex: none;
  border: 0; border-radius: 8px; padding: 12px 28px; background: var(--teal-deep); color: var(--on-brand);
  font-family: inherit; font-size: var(--t-small); line-height: var(--t-small-line); font-weight: 600; cursor: pointer;
}
.lvb-run:hover { background: var(--brand-strong); }
.lvb-bar-note { margin: var(--s3) 0 0; font-size: var(--t-label); line-height: var(--t-label-line); color: var(--ink-2); }
/* THE SECOND LINE NAMES THE ID OR THE PARAMETER, so it sets in the ink rather than the muted ink:
   it is the part a reader acts on. No state colour. A pair this estate does not carry is not a
   failure of anything, and painting it red would say the check refused where it never ran. */
.lvb-bar-which { margin: var(--s2) 0 0; font-size: var(--t-label); line-height: var(--t-label-line); color: var(--ink); }

/* ==========================================================================
   5. The three panels
   ==========================================================================
   One column, then three equal columns at 1024, with a 20px gap, which is the reference's grid. */
.lvb-panels { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s5); padding-top: var(--s5); }
/* minmax(0, 1fr) RATHER THAN 1fr. A bare 1fr track is at least its min content, and at 390 one panel held
   the track to 426px and the page scrolled sideways. Measured on 29 September 2026, on the live site too. */
.lvb-panel {
  padding: var(--s5); border: 1px solid var(--hairline); border-radius: 16px; background: var(--paper-alt);
}
/* The hub. A brand edge at a quarter and an inset brand glow, and no outer glow and no gradient: it
   is a different treatment from the hub card on the home page and is not that one. */
.lvb-panel-hub {
  display: flex; flex-direction: column;
  border-color: color-mix(in srgb, var(--teal-dark) 25%, transparent);
  box-shadow: inset 0 0 60px color-mix(in srgb, var(--teal-dark) 5%, transparent);
}
.lvb-panel-head { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; }
.lvb-panel-head > div { min-width: 0; flex: 1 1 12rem; }
.lvb-panel-title {
  margin: 0; font-family: var(--sans); font-size: var(--t-small); line-height: var(--t-small-line);
  font-weight: 700; text-transform: uppercase; letter-spacing: 0.025em; color: var(--ink);
}
.lvb-panel-sub { margin: 2px 0 0; font-size: var(--t-label); line-height: var(--t-label-line); color: var(--ink-2); }

/* The icon tile: square, one pixel of edge, the glyph centred. Four sizes on the reference and two
   of them are used here. */
.lvb-tile {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  border: 1px solid color-mix(in srgb, var(--teal-dark) 40%, transparent); border-radius: 8px; color: var(--teal-dark);
}
.lvb-tile[data-size="36"] { width: 36px; height: 36px; }
.lvb-tile[data-size="32"] { width: 32px; height: 32px; border-radius: 6px; }
.lvb-tile[data-hue="customer"] { border-color: color-mix(in srgb, var(--slate) 45%, transparent); color: var(--slate); }

/* The pill. The reference sets 10px inside 10px by 4px of padding; at the floor it needs 8px by 4px
   and the same round edge. */
.lvb-pill {
  display: inline-flex; align-items: center; gap: 6px; flex: none;
  border: 1px solid var(--hairline); border-radius: var(--pill); padding: 4px 10px;
  font-size: var(--t-label); line-height: var(--t-label-line); font-weight: 600; color: var(--ink-2);
}
.lvb-pill[data-hue="customer"] { border-color: color-mix(in srgb, var(--slate) 40%, transparent); color: var(--slate); }

/* ---- Panel one: the agents ---- */
.lvb-showcase { display: grid; grid-template-columns: 1fr; gap: var(--s3); margin-top: var(--s4); }
.lvb-agents { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; align-content: start; }
/* ONE HUE PER DECLARED AGENT, IN THE ORDER THE ESTATE DECLARES THEM, and it is the hue the same
   agent takes in the hero figure. A reader who picks a colour out of the instrument finds it again
   here. The hue is identity: it does not say the agent is trusted, permitted or reachable, and the
   answer to each of those is drawn elsewhere on the page as a word beside a mark. The list cycles
   through four hues because there are four and this estate declares six agents. */
.lvb-agents .lvb-agent:nth-child(4n + 1) { --hue: var(--d-blue); }
.lvb-agents .lvb-agent:nth-child(4n + 2) { --hue: var(--d-violet); }
.lvb-agents .lvb-agent:nth-child(4n + 3) { --hue: var(--d-magenta); }
.lvb-agents .lvb-agent:nth-child(4n + 4) { --hue: var(--d-sand); }
.lvb-agent {
  display: flex; align-items: center; gap: 10px; padding: 10px 10px 10px 8px; min-width: 0;
  border: 1px solid var(--rule); border-left: 3px solid var(--hue, var(--rule));
  border-radius: 8px; background: var(--white); text-decoration: none;
}
.lvb-agent .lvb-tile { border-color: var(--hue, var(--teal-dark)); color: var(--hue, var(--teal-dark)); }
.lvb-agent:hover { border-top-color: color-mix(in srgb, var(--teal-dark) 45%, var(--rule)); }
.lvb-agent[aria-current="true"] { border-top-color: color-mix(in srgb, var(--teal-dark) 60%, transparent); background: var(--wash-teal); }
.lvb-agent-who { min-width: 0; }
.lvb-agent-name { display: block; font-size: var(--t-label); line-height: var(--t-label-line); font-weight: 700; color: var(--ink); }
.lvb-agent-org { display: block; font-size: var(--t-label); line-height: var(--t-label-line); color: var(--ink-2); }

.lvb-detail { padding: 14px; border: 1px solid var(--hairline); border-radius: 8px; background: var(--white); }
.lvb-detail-head { display: flex; align-items: flex-start; gap: 10px; }
.lvb-detail-head > div { min-width: 0; display: grid; gap: 6px; justify-items: start; }
.lvb-detail-name { margin: 0; font-size: var(--t-label); line-height: var(--t-label-line); font-weight: 700; color: var(--ink); }
.lvb-kv { margin-top: var(--s3); }
.lvb-k { margin: var(--s3) 0 0; font-size: var(--t-label); line-height: var(--t-label-line); color: var(--ink-2); }
.lvb-v { margin: 2px 0 0; font-size: var(--t-label); line-height: var(--t-label-line); font-weight: 600; color: var(--ink); overflow-wrap: anywhere; }
.lvb-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.lvb-chip {
  border-radius: 6px; padding: 4px 8px; background: var(--paper-alt); color: var(--slate);
  font-size: var(--t-label); line-height: var(--t-label-line);
}

/* ---- Panel two: what the check read ---- */
.lvb-hub-head { display: grid; justify-items: center; text-align: center; gap: 4px; }
.lvb-hub-title {
  margin: 0; display: inline-flex; align-items: center; gap: 10px;
  font-size: var(--t-small); line-height: 1; font-weight: 700; letter-spacing: 0.025em;
  text-transform: uppercase; color: var(--ink);
}
/* The mark is a ring of brand light with the wordmark's counter in it. The reference draws a letter
   in a glowing circle; the letter is a placeholder for an asset this estate does not declare, so the
   ring is drawn and the letter is left out. */
.lvb-hub-mark {
  width: 34px; height: 34px; border-radius: var(--pill); flex: none;
  border: 1px solid color-mix(in srgb, var(--teal-dark) 60%, transparent);
  box-shadow: 0 0 24px color-mix(in srgb, var(--teal-dark) 40%, transparent);
}
/* ONE IDENTITY HUE PER CHECK ROW. Five rows, five things the check does, and the hue separates them
   in a column where every row is the same shape. It says which step, never how the step went: a step
   that refused takes the refused tone below, which overrides the hue on the tile, and the mark at the
   end of the row carries the word and the artefact. */
.lvb-checks { display: grid; gap: 10px; margin-top: var(--s4); }
.lvb-checks .lvb-check:nth-child(4n + 1) { --hue: var(--d-blue); }
.lvb-checks .lvb-check:nth-child(4n + 2) { --hue: var(--d-violet); }
.lvb-checks .lvb-check:nth-child(4n + 3) { --hue: var(--d-magenta); }
.lvb-checks .lvb-check:nth-child(4n + 4) { --hue: var(--d-sand); }
.lvb-check .lvb-tile { border-color: var(--hue, var(--teal-dark)); color: var(--hue, var(--teal-dark)); }
.lvb-check {
  display: flex; align-items: center; gap: var(--s3); padding: 12px 14px;
  border: 1px solid var(--hairline); border-radius: 12px; background: var(--white);
}
/* A step that read the answer an earlier step fetched takes a dashed edge, the way the answer on
   /live draws the same fact, so three rows never read as three requests. */
.lvb-check[data-reused="true"] { border-style: dashed; }
.lvb-check[data-tone="no"] { border-color: color-mix(in srgb, var(--no) 40%, transparent); background: var(--wash-no); }
.lvb-check[data-tone="no"] .lvb-tile { border-color: color-mix(in srgb, var(--no) 50%, transparent); color: var(--no); }
.lvb-check-say { min-width: 0; flex: 1 1 auto; }
/* The mark keeps its words on one line and the row's body takes what is left. Two words broken over
   two lines beside a one line body reads as a second sentence. */
.lvb-check > .ev, .lvb-check > .state { flex: none; white-space: nowrap; }
/* ON A PHONE THE MARK TAKES ITS OWN LINE under the body, indented past the tile. Kept on the row, it
   held each check at 376px in a 300px panel and the page scrolled sideways at 390. */
@media (max-width: 30rem) {
  .lvb-check { flex-wrap: wrap; }
  .lvb-check-say { flex-basis: calc(100% - 48px); }
  .lvb-check > .ev, .lvb-check > .state { margin-left: 48px; }
}
.lvb-check-title { margin: 0; font-size: var(--t-label); line-height: var(--t-label-line); font-weight: 600; color: var(--ink); }
.lvb-check-body { margin: 2px 0 0; font-size: var(--t-label); line-height: var(--t-label-line); color: var(--ink-2); }
.lvb-empty {
  margin: var(--s4) 0 0; padding: var(--s5); border: 1px dashed var(--rule); border-radius: 12px;
  font-size: var(--t-label); line-height: var(--t-label-line); color: var(--ink-2); text-align: center;
}
.lvb-panel-hub > .lvb-empty { margin-block: auto; }

/* ---- Panel three: the customer side ---- */
.lvb-resource {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: var(--s4);
  padding: 14px; border: 1px solid var(--hairline); border-radius: 12px; background: var(--white);
}
.lvb-resource-who { min-width: 0; flex: 1 1 10rem; }
.lvb-resource-name { margin: 0; font-size: var(--t-label); line-height: var(--t-label-line); font-weight: 700; color: var(--ink); }
.lvb-resource-org { margin: 2px 0 0; font-size: var(--t-label); line-height: var(--t-label-line); color: var(--ink-2); }
.lvb-block-title { margin: 0 0 var(--s2); font-size: var(--t-label); line-height: var(--t-label-line); font-weight: 700; color: var(--ink); }
.lvb-panel > .lvb-block-title { margin-top: var(--s4); }
.lvb-policy { display: grid; gap: var(--s2); }
.lvb-policy-row {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s3); flex-wrap: wrap;
  padding: 8px 12px; border: 1px solid var(--hairline); border-radius: 8px; background: var(--white);
}
.lvb-policy-label { font-size: var(--t-label); line-height: var(--t-label-line); color: var(--ink); }
.lvb-policy-note { margin: 4px 0 0; font-size: var(--t-label); line-height: var(--t-label-line); color: var(--ink-2); }
.lvb-policy-source { margin: var(--s3) 0 0; font-size: var(--t-label); line-height: var(--t-label-line); color: var(--ink-2); }
.lvb-decision { margin-top: var(--s4); padding: 14px; border: 1px solid var(--hairline); border-radius: 12px; background: var(--white); }
.lvb-decision-row { display: flex; align-items: flex-start; gap: 10px; }
.lvb-decision-row .mark { width: 22px; height: 22px; color: var(--ink-2); }
.lvb-decision-word { margin: 0; font-size: var(--t-label); line-height: var(--t-label-line); font-weight: 700; text-transform: uppercase; letter-spacing: 0.02em; color: var(--ink); }
/* THE CONSEQUENCE LEADS AND THE VERDICT WORD FOLLOWS IT. A reader who came to find out whether
   their resource admits this agent reads a sentence, not a machine identifier pair. */
.lvb-decision-plain { margin: 0 0 var(--s3); font-size: var(--t-h3); line-height: var(--t-h3-line); font-weight: 600; color: var(--ink); }
.lvb-decision-type { margin: 2px 0 0; font-size: var(--t-label); line-height: var(--t-label-line); color: var(--slate); overflow-wrap: anywhere; }
.lvb-decision-line { margin: var(--s3) 0 0; font-size: var(--t-label); line-height: var(--t-label-line); color: var(--ink-2); }
.lvb-decision[data-state="ok"] .lvb-decision-word { color: var(--ok); }
.lvb-decision[data-state="ok"] .mark { color: var(--ok); }
.lvb-decision[data-state="no"] .lvb-decision-word { color: var(--no); }
.lvb-decision[data-state="no"] .mark { color: var(--no); }
.lvb-decision[data-state="att"] .lvb-decision-word { color: var(--att); }
.lvb-decision[data-state="att"] .mark { color: var(--att); }
.lvb-other { display: flex; align-items: center; gap: var(--s2); margin: 6px 0 0; font-size: var(--t-label); line-height: var(--t-label-line); color: var(--slate); flex-wrap: wrap; }
.lvb-other-note { color: var(--ink-2); }

/* ==========================================================================
   6. The progress row and the note beside it
   ==========================================================================
   The reference lays five steps in one wrapping row with an 8px horizontal gap and a 16px vertical
   one, beside a 360px note. At the 14px floor five steps do not fit on one line at 1440, so the row
   is designed to run onto two lines: each step is a block that does not break, and the arrow after
   the last one is left out. */
.lvb-progress-grid { display: grid; grid-template-columns: 1fr; gap: var(--s5); padding-top: var(--s5); }
.lvb-progress {
  display: flex; flex-wrap: wrap; align-items: center; column-gap: var(--s2); row-gap: var(--s4);
  padding: var(--s5); border: 1px solid var(--hairline); border-radius: 16px; background: var(--paper-alt);
}
.lvb-progress-label { margin: 0 var(--s2) 0 0; font-size: var(--t-label); line-height: var(--t-label-line); font-weight: 600; color: var(--ink-2); }
.lvb-step { display: flex; align-items: center; gap: var(--s2); }
.lvb-step-chip {
  display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; flex: none;
  border: 1px solid var(--rule); border-radius: var(--pill);
  font-size: var(--t-label); line-height: 1; font-weight: 700; color: var(--ink-2);
}
.lvb-step-chip .mark { width: 16px; height: 16px; }
.lvb-step-chip[data-state="ok"] { border-color: var(--ok); background: var(--wash-ok); color: var(--ok); }
.lvb-step-chip[data-state="no"] { border-color: color-mix(in srgb, var(--no) 60%, transparent); background: var(--wash-no); color: var(--no); }
.lvb-step-title { display: block; font-size: var(--t-label); line-height: var(--t-label-line); font-weight: 600; color: var(--ink); }
.lvb-step-src { display: block; font-size: var(--t-label); line-height: var(--t-label-line); color: var(--ink-2); }
.lvb-arrow { color: var(--rule); margin-left: var(--s1); flex: none; }
/* ==========================================================================
   7. The bottom row
   ==========================================================================
   The log of reads sits beside the sequence, in the column the reference gave its note panel.
   The action cards and the change list that ran here were cut on 29 September 2026. */
.lvb-card { padding: var(--s5); border: 1px solid var(--hairline); border-radius: 16px; background: var(--paper-alt); }
.lvb-card-title { margin: 0; font-size: var(--t-label); line-height: var(--t-label-line); font-weight: 700; color: var(--ink); }
.lvb-card-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); }
/* 24px MINIMUM. This link sits alone at the end of a panel head with no sentence around it, so
   neither exemption in WCAG 2.2 clause 2.5.8 applies. Measured at 768 and at 390: 84 by 20. */
.lvb-more { display: inline-flex; align-items: center; gap: 6px; min-height: 24px; font-size: var(--t-label); line-height: var(--t-label-line); font-weight: 600; color: var(--brand-strong); text-decoration: none; }
.lvb-log { display: grid; gap: var(--s2); margin-top: var(--s3); }
.lvb-log-row { display: flex; align-items: center; column-gap: 10px; row-gap: 2px; font-size: var(--t-label); line-height: var(--t-label-line); flex-wrap: wrap; }
.lvb-time { font-family: var(--mono); font-size: var(--t-label); color: var(--ink-2); flex: none; }
.lvb-log-label { flex: 1 1 8rem; min-width: 0; color: var(--ink-nav); }
.lvb-log-meta { color: var(--ink-2); flex: none; margin-left: auto; }
.lvb-close {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s5); flex-wrap: wrap;
  margin-top: var(--s7); padding-top: var(--s6); border-top: 1px solid var(--hairline);
}
.lvb-closing {
  margin: 0; flex: 1 1 22rem; font-family: var(--display); font-size: clamp(22px, 2vw, 26px);
  line-height: 1.2; letter-spacing: -0.02em; font-weight: 700; color: var(--ink); text-wrap: balance;
}
.lvb-closing .lvb-accent { color: var(--teal-dark); }
/* THE PAIR IS ONE GESTURE, so the two sit side by side rather than stacked, which is the rule
   CLAUDE.md sets after Ralph measured the copy column against the target's. */
.lvb-close-actions { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; }

/* ==========================================================================
   8. The widths
   ==========================================================================
   One breakpoint does the reference's work, at 1024, and this route adds a second at 1500 for the
   two places where the 14px floor needs more room than the reference's own grid gives. */
@media (min-width: 64rem) {
  .lvb-aside { display: flex; flex-direction: column; align-items: flex-end; gap: var(--s3); flex: none; padding-top: 4px; }
  .lvb-hero-row { grid-template-columns: minmax(0, 1fr) minmax(0, 34rem); gap: var(--s6); }
  .lvb-bar { flex-direction: row; align-items: flex-end; }
  .lvb-panels { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .lvb-progress-grid { grid-template-columns: minmax(0, 1fr) 420px; align-items: start; }
}
@media (min-width: 93.75rem) {
  .lvb-showcase { grid-template-columns: 1fr 1fr; }
  .lvb-agents { grid-template-columns: 1fr; }
}
/* THE FIGURE HAS A NARROW STATE RATHER THAN A STACKED ONE. Below 1024 it goes above the copy, keeps
   its full width and loses the side padding, so nine nodes and their arcs stay legible on a phone
   instead of being squeezed into half a column. */
@media (max-width: 64rem) {
  .lvb-hero-row { grid-template-areas: "fig" "copy"; }
  .lvb-copy { grid-area: copy; }
  .lvb-fig-hold { grid-area: fig; }
  .lvb-glow { width: 700px; height: 420px; top: -160px; }
}
@media (max-width: 30rem) {
  .lvb-close-actions { width: 100%; }
  .lvb-close-actions .btn { flex: 1 1 100%; justify-content: center; }
}
/* On a phone the two up list of agents leaves about 110px for a name, which breaks "Records
   Assistant" across two lines in every row. One column below 640. */
@media (max-width: 40rem) {
  .lvb-agents { grid-template-columns: 1fr; }
}

/* THE FRAGMENT TARGET CLEARS THE STICKY MASTHEAD.
 *
 * mast.css holds the masthead at `position: sticky; top: 0` and declares its height as
 * --masthead-h. A fragment jump puts the target's top edge at y 0, so the first 63px of the target
 * go behind the bar. On /live-demo/boundary that swallowed the whole first row of the picker,
 * including the Run button. Measured before this rule, at 1920 by 1080: target top 0, masthead
 * bottom 63. Only this view uses .lvb-wrap, so no other page changes. */
.lvb-wrap[id] { scroll-margin-top: calc(var(--masthead-h, 63px) + 12px); }

/* ---- src/parts/lv.css ---- */
/*
 * /live, rebuilt as a browsable list of the estate with a working compatibility check.
 *
 * WHAT IT REPLACED AND WHY. The page carried 2029 visible words inside `main` over 9444 px at 1440,
 * and every one of them was in front of the reader at once: a hero, five read cards with their
 * controls, a four step figure, a ceiling figure, four open prose layers, four scenario cards and a
 * closing. A reader had to finish the argument before they could do anything. The mechanism here is
 * a question with an answer, so the question is drawn once, the answer arrives when somebody asks
 * it, and everything else moves behind a drawer. Nothing is deleted.
 *
 * WHAT WAS MEASURED FROM docs/redesign/refs5/three-screens.png, RIGHT panel of three, medians over
 * thousands of pixels in the raw crop rather than picked by eye:
 *
 *     page ground, hero    #01101f      built as --paper       #001721
 *     page ground, gutter  #011528
 *     card interior        #011020      built as --white       #0B2531
 *     primary button fill  #50abfc      built as --teal-dark   #15D4D8
 *     headline ink         #f5f5fa      built as --ink         #E6F1F3
 *
 * The grounds are close enough that nothing moves. THE ACCENT IS A DIFFERENT HUE AND IS NOT TAKEN.
 * The reference is one render of one page and the accent is a token decision across nineteen
 * routes, so the site's own accent stays and the difference is recorded here rather than applied.
 *
 * NOT MEASURED AND NOT USED: spacing, type size, radius and stroke weight. The reference panel is
 * 511 px wide against a 1440 design, so every metric in it is below what that resolution kept.
 * Each of those comes from the system's own scale.
 *
 * THE REFERENCE'S FOUR SATURATED TILE COLOURS ARE NOT TAKEN EITHER, and that one is about meaning
 * rather than resolution. It paints each card's icon tile purple, green, orange or blue. Green
 * means Observed here and amber and red mean in progress and refused, so three of those four are
 * spent, and a colour on a card would be read as a treatment by a reader who has just come off any
 * other page of this site. Every tile is the accent wash instead, and the glyph inside it says what
 * the declaration says: where the agent runs.
 *
 * GREEN IS THE WHOLE POINT OF THIS FILE, so it is written once and gated in CSS rather than in a
 * browser script. A step of the check is green only under `.ev[data-ev="observed"]`, which is the
 * selector packages/ui/tests/stylesheet.test.ts permits for var(--ok) and which
 * packages/ui/partials/ev.ejs refuses to render without a link to the artefact. The artefact is the
 * url that was read. A step whose answer came out of the estate declaration carries no evidence
 * mark at all and takes the muted ink, because a declared answer drawn as a live one is the single
 * claim this page exists to refuse.
 *
 * THE CLASS PREFIX IS lv-, WHICH packages/ui/src/parts/uc-live-bands.css ALREADY USES, and the
 * parts are concatenated in sorted file name order, so `lv.css` is read BEFORE `uc-live-bands.css`
 * and would lose to it at equal specificity. Every class below is therefore a name that file does
 * not carry. Those it does carry, and which nothing here may restate: lv-hero, lv-hero-body,
 * lv-hero-figure, lv-headline, lv-headline-accent, lv-stack and its children, lv-reads, lv-read and
 * its children, lv-ceiling and its children, lv-amount, lv-says, lv-scenarios, lv-scenario.
 */

/* ---- Level one: the hero ----------------------------------------------------------------------
   Centred, which most of this site is not. /how-it-works took the same deviation for the same
   reason and the reference centres both: the page has one job above the fold, and a left aligned
   headline over a full width band starts the reader's eye in the wrong place. */
.lv-top { text-align: center; display: grid; justify-items: center; gap: var(--s3); padding-bottom: var(--s4); }
.lv-top .t-display { margin: 0; max-width: 20ch; text-wrap: balance; }
.lv-top-line { margin: 0; max-width: 40ch; color: var(--ink); text-wrap: balance; }
.lv-top-lead { margin: 0; max-width: 70ch; color: var(--ink-2); }

/* ---- The section strip ----------------------------------------------------------
   The reference draws four tabs that switch one panel. These are four links to four bands, because
   a tab set needs script to work and four bands need none: a reader with no JavaScript gets the
   whole page and the links still go somewhere. */
.lv-jump { display: flex; flex-wrap: wrap; gap: var(--s2); border-bottom: 1px solid var(--rule); }
.lv-jump a {
  padding: var(--s3) var(--s5);
  border: 1px solid transparent;
  border-bottom: 0;
  border-radius: var(--r-2) var(--r-2) 0 0;
  color: var(--ink-2);
  text-decoration: none;
  font-weight: 600;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}
.lv-jump a:hover { color: var(--teal-dark); background: var(--paper-alt); }
/* The current one, set by apps/site/src/public/live.js as the reader scrolls. It is a reading aid
   and nothing depends on it, so with no script every tab simply looks the same. */
.lv-jump a[aria-current="true"] { color: var(--ink); background: var(--white); border-color: var(--rule); box-shadow: inset 0 -3px 0 var(--teal-dark); }

/* ---- The cards ----------------------------------------------------------------------------------
   THREE ACROSS, AND THE COMMENT HERE SAID FOUR. The reference draws four; this draws three, because
   a card carries a tile, a name, an organisation, a source chip, its detail types, three fact chips
   and an action, and four of those in a 1344 px content width leaves each one narrower than its own
   mono detail types. The number below is the rule; whoever changes the breakpoints reads this line,
   so it has to say what the rule does rather than what the reference did. */
.lv-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s4); }
.lv-card {
  /* Flex rather than grid, so the action can take `margin-top: auto` and sit on one line across a
     row of cards whose bodies are different lengths. A grid with `align-content: start` packs its
     tracks at the top and leaves the auto margin nothing to consume, which is how the scenario card
     row came out 886 px against 879 px. */
  display: flex;
  flex-direction: column;
  gap: var(--s3);
  padding: var(--s5);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
  background: var(--white);
  box-shadow: var(--shadow-lift);
  min-width: 0;
}
.lv-card[hidden] { display: none; }
.lv-card-top { display: grid; grid-template-columns: 44px 1fr; gap: var(--s3); align-items: center; }
.lv-tile {
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border-radius: var(--r-2);
  border: 1px solid var(--teal-dark);
  background: var(--wash-teal);
  color: var(--teal-dark);
}
.lv-tile svg { width: 24px; height: 24px; }
.lv-card-name { margin: 0; color: var(--ink); }
.lv-card-org { margin: 0; font-size: var(--t-small); color: var(--ink-2); }
.lv-card-line { margin: 0; font-size: var(--t-small); color: var(--ink-2); }

/* The source chip. It says which half of this site can answer for the card, and it is deliberately
   NOT a state: `live` means the capability matrix declares reads for this agent, so the check can
   walk its chain; `declared` means it does not, and the answer will come from the estate
   declaration. The accent for one, the muted ink for the other, and no state colour on either. */
.lv-src {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 10px;
  border-radius: var(--pill);
  font-size: var(--t-label);
  font-weight: 600;
  line-height: var(--t-label-line);
  border: 1px solid var(--rule);
  color: var(--ink-2);
}
.lv-src::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: currentColor; flex: none; }
.lv-src[data-src="live"] { color: var(--teal-dark); border-color: var(--teal-dark); background: var(--wash-teal); }
.lv-src[data-src="derived"] { color: var(--ink); }

.lv-chips { display: flex; flex-wrap: wrap; gap: var(--s2); margin: 0; padding: 0; list-style: none; }
.lv-chips li {
  font-size: var(--t-label);
  padding: 3px 10px;
  border-radius: var(--pill);
  border: 1px solid var(--rule);
  color: var(--ink-2);
}
/* A chip that reports the ABSENCE of a claim rather than a value of it. The estate's assurance
   `none` is the case: a token issued to an identity on its own key carries no assurance claim, so
   the chip must not sit beside "Attested copy" and "Asserted copy" looking like a third state. A
   dashed edge, which is the treatment uc-live-bands.css already gives the half of the reads figure
   this page does not reach. Not a state colour: nothing is refused and nothing is pending. */
.lv-chips li[data-absent="yes"] { border-style: dashed; }
/* An agent's declared detail types, as they are spelled on the wire. Mono, because they are values
   rather than words, and the check compares these exact strings against the envelope. */
.lv-types { display: flex; flex-wrap: wrap; gap: var(--s2); margin: 0; padding: 0; list-style: none; }
.lv-types li {
  font-family: var(--mono);
  font-size: var(--t-mono);
  padding: 3px 10px;
  border-radius: var(--r-1);
  border: 1px solid var(--rule);
  color: var(--teal-dark);
  overflow-wrap: anywhere;
}
.lv-facts { margin: 0; display: grid; grid-template-columns: auto 1fr; gap: 6px var(--s3); font-size: var(--t-small); }
.lv-facts dt { color: var(--ink-2); }
.lv-facts dd { margin: 0; color: var(--ink); min-width: 0; overflow-wrap: anywhere; }
.lv-card-act { margin-top: auto; padding-top: var(--s2); }

/* The tools a resource offers. Each names the detail type it needs, which is the value the check
   compares against the envelope, so the reader sees the thing being compared rather than a word. */
.lv-tools { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.lv-tools li {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: var(--s3);
  padding: 7px 10px;
  border: 1px solid var(--rule);
  border-radius: var(--r-1);
  font-size: var(--t-small);
}
.lv-tool-type { font-family: var(--mono); font-size: var(--t-mono); color: var(--teal-dark); overflow-wrap: anywhere; }
.lv-tool-write { font-size: var(--t-label); font-weight: 600; color: var(--ink-2); white-space: nowrap; }

/* ---- Integrations: the declared pairs, as a matrix -----------------------------------------------
   Agents down the side, resources across, and in each cell the authorization detail types that pair
   requires. It replaced a flat list of thirteen rows that repeated each agent's name and
   organisation four times and spent 181 visible words on what this says in about seventy.

   `.table-scroll` comes from apps/site/src/public/site.css, which loads AFTER this file, so it is
   reused for the overflow rather than restated: a rule here with the same selector would lose. The
   table itself deliberately does NOT take `.site-table`, whose rules also live in that later sheet
   and would beat anything written here. */
.lv-matrix-scroll { border: 1px solid var(--rule); border-radius: var(--r-3); background: var(--white); }
/* THE TABLE IS ALLOWED TO BE WIDER THAN THE SCREEN AND THE CONTAINER SCROLLS. Without the floor
   below, the three resource columns squeeze at 390 and every detail type breaks mid token:
   "records.annota / te" is not a value anybody can read or copy. The floor is safe here and nowhere
   else on the page, because tools/redesign/responsive.mjs exempts an element inside an ancestor that
   scrolls, and `.table-scroll` is one. Measured clean at all five widths with the floor in place. */
.lv-matrix { width: 100%; min-width: 640px; border-collapse: collapse; font-size: var(--t-small); }
.lv-matrix th, .lv-matrix td {
  text-align: left;
  vertical-align: top;
  padding: var(--s3) var(--s4);
  border-bottom: 1px solid var(--rule);
}
.lv-matrix tbody tr:last-child th, .lv-matrix tbody tr:last-child td { border-bottom: 0; }
.lv-matrix thead th { font-size: var(--t-label); font-weight: 600; color: var(--ink-2); white-space: nowrap; }
.lv-matrix tbody th { font-weight: 400; }
.lv-matrix-name { display: block; font-weight: 600; color: var(--ink); }
.lv-matrix-org { display: block; font-size: var(--t-label); color: var(--ink-2); }
/* A pair the estate does not declare. A full stop rather than a dash, because the dash rule reaches
   rendered text, and a visually hidden phrase beside it so the cell is not silent to a reader who
   cannot see the mark. */
.lv-matrix-none { color: var(--ink-2); }
.lv-matrix-types { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.lv-matrix-types li { display: grid; gap: 2px; justify-items: start; }
.lv-pair-tool { font-family: var(--mono); font-size: var(--t-mono); color: var(--teal-dark); white-space: nowrap; }
/* A task the declaration marks as needing a person. Amber is the in progress colour and this is not
   a state of anything, so it takes a plain outline and says the whole word. */
.lv-pair-who {
  font-size: var(--t-label);
  font-weight: 600;
  color: var(--ink);
  border: 1px solid var(--bound);
  border-radius: var(--pill);
  padding: 2px 10px;
}

/* ---- The check ---------------------------------------------------------------------------------- */
.lv-check {
  display: grid;
  gap: var(--s5);
  padding: var(--s6);
  border: 1px solid var(--teal-dark);
  border-radius: var(--r-3);
  background: var(--white);
}
.lv-pick { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr) auto; gap: var(--s4); align-items: end; }
.lv-field { display: grid; gap: 6px; min-width: 0; }
.lv-field label { font-size: var(--t-label); font-weight: 600; color: var(--ink-2); }
.lv-field select {
  font: inherit;
  color: var(--ink);
  background: var(--white);
  min-height: 48px;
  padding: 10px 12px;
  border: 1.5px solid var(--bound);
  border-radius: var(--r-1);
  width: 100%;
}
.lv-to { align-self: center; width: 26px; height: 2px; background: var(--teal-dark); position: relative; margin-bottom: 22px; }
.lv-to::after {
  content: "";
  position: absolute; right: 0; top: 50%;
  width: 8px; height: 8px;
  border-top: 2px solid var(--teal-dark);
  border-right: 2px solid var(--teal-dark);
  transform: translateY(-50%) rotate(45deg);
}
.lv-check-note { margin: 0; font-size: var(--t-small); color: var(--ink-2); max-width: var(--measure-notes); }

/* The answer. Hidden until there is one, and the whole region is a live region so a reader using a
   screen reader is told the verdict arrived rather than left to find it. */
.lv-answer { display: grid; gap: var(--s4); border-top: 1px solid var(--rule); padding-top: var(--s5); }
.lv-verdict { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s3) var(--s4); margin: 0; }
.lv-verdict-word { font: var(--t-h2-weight) var(--t-h2) / 1.2 var(--sans); color: var(--ink); }
.lv-verdict-pair { font-size: var(--t-small); color: var(--ink-2); }
/* The verdict takes no colour of its own. "Compatible" is not Observed and "incompatible" is not a
   refusal by anybody: both are computed from what the walk read, and the colour on this page belongs
   to the evidence mark on the step that was actually read. */

.lv-steps { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s3); counter-reset: lv-step; }
.lv-step {
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr);
  align-items: start;
  gap: var(--s3);
  padding: var(--s4);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--rule);
  border-radius: var(--r-2);
  background: var(--paper-alt);
}
.lv-step[data-src="live"] { border-left-color: var(--teal-dark); }
.lv-step[data-state="absent"] { border-left-color: var(--no); }
/* A LIVE STEP THAT READ THE ANSWER A PREVIOUS STEP FETCHED. Three rows saying `live` is a reader
   counting three requests, and the hero walk makes two: the envelope is read out of the statement
   the chain step fetched. The payload carries `reusesRead`; this is it on the screen, because
   honesty in the payload and not on the screen is honesty the reader never gets. It keeps its
   Observed mark, since the artefact is real and the link goes to the bytes the claim rests on. */
.lv-step[data-reuses] { border-left-style: dashed; }
.lv-src[data-reuses] { border-style: dashed; }
.lv-step-n {
  width: 34px; height: 34px;
  display: grid; place-items: center;
  border-radius: 50%;
  border: 1px solid var(--rule);
  color: var(--ink-2);
  font-size: var(--t-label);
  font-weight: 600;
}
.lv-step[data-src="live"] .lv-step-n { border-color: var(--teal-dark); color: var(--teal-dark); }
.lv-step-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2) var(--s3); }
.lv-step-name { margin: 0; font-size: var(--t-body); font-weight: 600; color: var(--ink); }
.lv-step-body { display: grid; gap: 6px; min-width: 0; }
.lv-step-detail { margin: 0; font-size: var(--t-small); color: var(--ink-2); }
/* What was fetched, printed as text that wraps rather than as a command block. A block that scrolls
   sideways needs a focus stop to be reachable by keyboard, and the raw artefact drawer at the foot
   of this page already carries a copyable command for every declared read. */
.lv-step-url { margin: 0; font-family: var(--mono); font-size: var(--t-mono); color: var(--ink-2); overflow-wrap: anywhere; }

.lv-result-tools { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s2); }
.lv-result-tool {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) minmax(0, 1.4fr);
  align-items: center;
  gap: var(--s3);
  padding: var(--s3) var(--s4);
  border: 1px solid var(--rule);
  border-radius: var(--r-2);
  font-size: var(--t-small);
}
.lv-result-tool .lv-tool-type { white-space: nowrap; }
.lv-result-note { color: var(--ink-2); min-width: 0; }
/* Inside the envelope and outside it. Neither is a state colour: what the walk read is carried by
   the evidence mark on the step that read it, and these two rows are the comparison, not the read.
   The permitted row takes the accent edge, the refused row takes the muted one. */
.lv-in { font-weight: 600; color: var(--teal-dark); white-space: nowrap; }
.lv-out { font-weight: 600; color: var(--ink-2); white-space: nowrap; }
.lv-result-tool[data-in="no"] { border-style: dashed; }

.lv-envelope { margin: 0; display: grid; gap: 6px; }
.lv-envelope-cap { font-size: var(--t-label); font-weight: 600; color: var(--ink-2); }
.lv-envelope-list { display: flex; flex-wrap: wrap; gap: var(--s2); margin: 0; padding: 0; list-style: none; }
/* The second trust domain, named under the envelope rather than left to the drawer. It is a note
   about where this answer came from, not a state, so it takes the muted ink and no colour. */
.lv-envelope-note { margin: 0; font-size: var(--t-small); color: var(--ink-2); max-width: var(--measure-notes); }
.lv-envelope-list li {
  font-family: var(--mono);
  font-size: var(--t-mono);
  padding: 3px 10px;
  border: 1px solid var(--rule);
  border-radius: var(--pill);
  color: var(--ink);
}

/* A check that could not be answered. Two kinds, drawn apart: an unknown pair is the reader's
   mistake and the page offers them another, and a read that did not answer is not their mistake and
   the page says so. NEITHER TAKES THE REFUSAL COLOUR. Red means refused or gone on this site, and
   nothing here refused anything: one pair does not exist and one host did not reply. */
.lv-trouble {
  display: grid;
  gap: 6px;
  padding: var(--s4);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--ink-2);
  border-radius: var(--r-2);
  background: var(--paper-alt);
}
.lv-trouble[data-error="read-failed"] { border-left-style: dashed; }
.lv-trouble[data-error="ambiguous-request"] { border-left-style: dotted; }
.lv-trouble-say { margin: 0; color: var(--ink); }
.lv-trouble-then { margin: 0; font-size: var(--t-small); color: var(--ink-2); }
/* Which name this estate does not carry, or which parameter was doubled. It repeats the reader's own
   input and nothing of ours: the raw exception that used to sit here named the tenant host and the
   failing url. The id is mono because it is a value they typed, not a word. */
.lv-trouble-which { margin: 0; font-size: var(--t-small); color: var(--ink-2); }
.lv-trouble-id { font-family: var(--mono); font-size: var(--t-mono); color: var(--ink); overflow-wrap: anywhere; }

/* ---- Build with confidence ---------------------------------------------------------------------- */
/* The payoff line, at the comp's scale: the second largest thing on the page after the headline,
   centred over the row of four. It is the one sentence a reader leaves with. */
.lv-payoff {
  margin: 0 auto var(--s7);
  max-width: 34ch;
  text-align: center;
  font-family: var(--display);
  font-size: var(--t-h2);
  line-height: 1.2;
  font-weight: 600;
  color: var(--ink);
}
.lv-build { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s5); }
.lv-build-cell { display: grid; justify-items: center; text-align: center; gap: var(--s2); padding-left: var(--s5); border-left: 1px solid var(--rule); }
.lv-build-cell:first-child { padding-left: 0; border-left: 0; }
.lv-build-i {
  width: 48px; height: 48px;
  display: grid; place-items: center;
  border-radius: 50%;
  border: 1px solid var(--teal-dark);
  color: var(--teal-dark);
}
.lv-build-i svg { width: 24px; height: 24px; }
.lv-build-name { margin: 0; font-size: var(--t-body); font-weight: 600; color: var(--ink); }
.lv-build-line { margin: 0; font-size: var(--t-small); color: var(--ink-2); }
/* The two ways onward, under the strip. The first is filled and the second is quiet, as every other
   page of this site has it. A class of its own rather than /how-it-works's, because a partial that
   borrows another page's class breaks when that page is next rebuilt. */
.lv-actions { display: flex; flex-wrap: wrap; gap: var(--s4); justify-content: center; margin-top: var(--s7); }

/* ---- The access decision is simulated, and the key to the three source words --------------------
   packages/ui/partials/lv-simulated.ejs. The panel beside the check.

   IT IS DRAWN AS A STATEMENT, NOT AS A WARNING. No amber edge, no icon, no exclamation. A page that
   dresses its own honesty as an alert invites a reader to dismiss it; this one is the same card
   treatment as everything else on the band, with its sentence at body scale rather than in the note
   ink. The one signal it takes is a solid accent edge on the left, which is the treatment this
   stylesheet already gives a live step.

   THE ROW CHIPS ARE `.lv-src`, THE SAME COMPONENT THE ANSWER PRINTS ON EVERY STEP, rather than a
   second chip that looks like it. A legend drawn in a different component from the thing it explains
   is the shape that drifts. */
.lvsm {
  display: grid; gap: var(--s3);
  padding: var(--s5);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--teal-dark);
  border-radius: var(--r-2);
  background: var(--white);
}
.lvsm-h { margin: 0; font-family: var(--display); font-size: var(--t-h3); font-weight: 600; color: var(--ink); }
.lvsm-say { margin: 0; font-size: var(--t-body); color: var(--ink); }
.lvsm-rows { list-style: none; margin: var(--s2) 0 0; padding: 0; display: grid; gap: var(--s3); }
.lvsm-row { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--s3); align-items: start; }
.lvsm-line { font-size: 14px; color: var(--ink-2); }
.lvsm-foot { margin: var(--s2) 0 0; font-size: 14px; color: var(--ink-2); }

/* ---- What the answer can say --------------------------------------------------------------------
   packages/ui/partials/lv-verdicts.ejs.

   NO COLOUR, AND THE RANK MARK IS WHY IT STILL READS AS A SCALE. The three outcome words on
   /use-cases/when-something-changes take the state colours because those three ARE the state
   vocabulary. These three are not: a compatible verdict is a comparison this page worked out, and
   green here would say it was seen on the wire. Three pips, filled three, two and one, carry the
   order without claiming anything, and `.lv-verdict` above already takes no colour for the same
   reason. */
.lvv {
  /* One track that can be narrower than its content. See the note on .lvp-more in lv-page.css:
     this panel sits inside that band and grew the same way. */
  display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s4);
  padding: var(--s5);
  border: 1px solid var(--rule);
  border-radius: var(--r-2);
  background: var(--white);
}
.lvv-h {
  margin: 0; font-size: var(--t-label); font-weight: 600;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-2);
}
/* Three across where there is room for three, one where there is not. `auto-fit` rather than a
   column count and a media query, because this partial is drawn full width under the check on /live
   and in a narrow cell in the gallery, and one rule has to hold for both. */
.lvv-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s4) var(--s6); grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); }
.lvv-item { display: grid; gap: 4px; }
.lvv-top { margin: 0; display: flex; align-items: center; gap: var(--s3); }
.lvv-rank { display: inline-flex; gap: 3px; flex: none; }
.lvv-rank span { width: 7px; height: 7px; border-radius: 50%; border: 1px solid var(--ink-2); }
.lvv-rank span[data-on="yes"] { background: var(--ink-2); }
.lvv-word { font-weight: 600; font-size: var(--t-small); color: var(--ink); }
.lvv-line { margin: 0; font-size: 14px; color: var(--ink-2); }

/* ---- How it works: four steps and the card beside them -------------------------------------------
   packages/ui/partials/lv-steps.ejs, laid out as Ralph's comp has it: a numbered row inside one
   panel, and a narrower card beside it carrying the figure that bounds the sequence.

   THE CHEVRON BETWEEN STEPS IS A PSEUDO ELEMENT WITH NO CONTENT TEXT, drawn from two borders, so no
   screen reader announces a character between two list items. It is dropped at the width where the
   row stops being a row, because a chevron pointing down a column points at nothing. */
.lvst { display: grid; gap: var(--s4); }
.lvst-kicker {
  margin: 0; font-size: var(--t-label); font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--teal-dark);
}
.lvst-row { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 1fr); gap: var(--s5); align-items: stretch; }
.lvst-steps {
  list-style: none; margin: 0; padding: var(--s5);
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s5);
  border: 1px solid var(--rule); border-radius: var(--r-2); background: var(--white);
}
.lvst-step { position: relative; display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--s3); align-items: start; }
.lvst-step + .lvst-step::before {
  content: "";
  position: absolute; left: calc(var(--s5) / -2 - 3px); top: 13px;
  width: 7px; height: 7px;
  border-top: 1.5px solid var(--teal-dark);
  border-right: 1.5px solid var(--teal-dark);
  transform: rotate(45deg);
  opacity: 0.7;
}
.lvst-n {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--teal-dark) 50%, transparent);
  background: var(--wash-teal); color: var(--teal-dark);
  font-size: 14px; font-weight: 700;
}
.lvst-b { display: grid; gap: 2px; min-width: 0; }
.lvst-t { font-weight: 600; font-size: var(--t-small); color: var(--ink); }
.lvst-l { font-size: 14px; color: var(--ink-2); }
.lvst-aside {
  display: grid; gap: var(--s2); align-content: center;
  padding: var(--s5); border: 1px solid var(--rule); border-radius: var(--r-2); background: var(--white);
}
.lvst-aside-t { margin: 0; font-weight: 600; font-size: var(--t-small); color: var(--ink); }
/* The bound, in mono because it is a value the resource publishes rather than a word this page
   chose. It reads through resourceLimits('transfers') in the view. */
.lvst-aside-v { margin: 0; font-family: var(--mono); font-size: var(--t-mono); color: var(--ink); }
.lvst-aside-l { margin: 0; font-size: 14px; color: var(--ink-2); }

/* ---- Level three: the evidence, and the drawers it lives in ------------------------------------- */
.lv-depth { display: grid; gap: 0; }
.lv-depth .drawer { margin: 0; }
.lv-depth .drawer > summary { font-size: var(--t-h3); }

/*
 * THE ONE ANIMATION, AND IT IS THE STEPS ONLY. They arrive in order, once, when the answer does.
 * Nothing loops and nothing moves afterwards.
 *
 * THE RESULT APPEARS UNDER prefers-reduced-motion, WITHOUT THE ARRIVAL. The animation is declared
 * only inside the no-preference query, so a reader who has asked for less motion gets the steps in
 * their final state at full opacity rather than a page that never finishes revealing them. That
 * failure mode is the reason the rule is written this way round: an `animation` declared outside
 * the query and cancelled inside it leaves `opacity: 0` behind on any browser that applied the
 * both fill before the query was evaluated.
 */
@media (prefers-reduced-motion: no-preference) {
  .lv-answer[data-arrived="yes"] .lv-step { animation: lv-step-in 360ms ease-out both; }
  .lv-answer[data-arrived="yes"] .lv-step:nth-child(1) { animation-delay: 0ms; }
  .lv-answer[data-arrived="yes"] .lv-step:nth-child(2) { animation-delay: 140ms; }
  .lv-answer[data-arrived="yes"] .lv-step:nth-child(3) { animation-delay: 280ms; }
  .lv-answer[data-arrived="yes"] .lv-step:nth-child(4) { animation-delay: 420ms; }
  .lv-answer[data-arrived="yes"] .lv-step:nth-child(5) { animation-delay: 560ms; }
  .lv-answer[data-arrived="yes"] .lv-verdict { animation: lv-step-in 360ms ease-out 700ms both; }
}

@keyframes lv-step-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

/* ---- Narrower ------------------------------------------------------------------------------------
   Three measured breaks rather than one. The card grid loses a column before the check's four
   column row can fit, and the check's row has to become two rows before the build strip stacks. */
@media (max-width: 1100px) {
  .lv-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .lv-build { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: var(--s6); }
  .lv-build-cell:nth-child(3) { padding-left: 0; border-left: 0; }
  /* The card beside the four steps goes under them, and the row keeps its four columns until the
     next break. */
  .lvst-row { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 900px) {
  .lv-pick { grid-template-columns: minmax(0, 1fr); align-items: stretch; }
  .lv-to { display: none; }
  .lvst-steps { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: var(--s6); }
  /* Two columns means the chevron would point from the end of one row into the start of the next,
     which is the wrong direction. Only the pairs that stay side by side keep one. */
  .lvst-step:nth-child(3)::before { display: none; }
}
@media (max-width: 640px) {
  .lv-grid { grid-template-columns: minmax(0, 1fr); }
  .lv-build { grid-template-columns: minmax(0, 1fr); }
  .lv-build-cell { padding-left: 0; border-left: 0; }
  .lv-check { padding: var(--s4); }
  .lv-result-tool { grid-template-columns: minmax(0, 1fr); }
  .lvst-steps { grid-template-columns: minmax(0, 1fr); padding: var(--s4); }
  /* A column of steps, so every chevron points across nothing. */
  .lvst-step + .lvst-step::before { display: none; }
  .lvsm, .lvv, .lvst-aside { padding: var(--s4); }
}

/* THE READS THAT DID NOT ANSWER, on the trouble block. live-compat.ts computed which step failed
   and threw the detail away, so a whole check that read nothing said only that the tenant did not
   answer. A read that failed is marked rather than dropped, and a whole check is no exception. The
   label and the status are facts about the reader's own check; the url and the host stay out. */
.lv-trouble-reads { list-style: none; margin: var(--s3) 0 0; padding: 0; display: grid; gap: var(--s2); }
.lv-trouble-reads li {
  display: flex; flex-wrap: wrap; gap: var(--s3); align-items: baseline;
  font-size: var(--t-small); color: var(--ink-2);
}
.lv-trouble-step { color: var(--ink); }
.lv-trouble-status { font-family: var(--mono); font-size: var(--t-mono); }

/* ---- src/parts/mast.css ---- */
/* THE MASTHEAD, first row: the drawn wordmark, the section navigation, the search control and one
 * call to action. The second row is packages/ui/src/parts/uc-nav.css and nothing here styles it.
 *
 * WHAT IT REFUSES TO DRAW.
 * 1. A bar under the current navigation item. The target marks the current item with the brand
 *    colour and weight 600 on this row. The bar belongs to the second row, where it is the only
 *    mark. Two marks for one state read as two different states.
 * 2. A translucent bar. packages/ui/tests/stylesheet.test.ts refuses a colour-mix in a flat
 *    background and it is right to: contrast.mjs gates token pairs by name and cannot see a mix, so
 *    navigation labels over a bright hero would be gated by nothing.
 *    A PREVIOUS VERSION OF THIS COMMENT SAID THE TARGET RUNS A BLURRED HEADER AND THAT WAS WRONG.
 *    components/site-header.tsx is `relative z-20 border-b border-line/70`: no ground, no opacity,
 *    no backdrop filter. The claim was carried over from an older reference and described nothing
 *    in the build this site is now matched against.
 * 3. A filled call to action. The target outlines it.
 *
 * TWO DEPARTURES FROM THE TARGET, BOTH DELIBERATE AND BOTH ABSENT FROM IT.
 * The target's header is not sticky and carries no scrolled shadow. Its page is one screen of one
 * use case. This site has eighteen routes, several of them long, and the navigation is how a reader
 * leaves one. The bar stays sticky and keeps its shadow.
 * The target has a search control. This site has no search and no handler for one, so the control
 * is not drawn. A control that cannot be operated is worse than an absent one.
 */

/* 5. Masthead */
/* THE BAR SITS ON THE PAGE GROUND, and it was the card colour, which read as a panel floating over
   the page rather than as the page's own top edge. It now matches the ground the hero fades into.

   THE BOTTOM EDGE IS --hairline AND NOT --rule. --rule is a real boundary, the edge of a card or of
   anything a person operates, and at #4d6a89 it drew a bright band across the top of every page.
   The target's header edge is almost invisible. --hairline is the token for a decorative divider. */
/* THE HEIGHT IS DECLARED, BECAUSE SOMETHING ELSE HAS TO SIT UNDER IT. The use cases strip sticks
   directly below this bar and had the number written into its own file, where it went stale the
   moment the row changed from 64px to 62px. 62px of row plus a 1px bottom border. */
:root { --masthead-h: 63px; }
.masthead {
  position: sticky; top: 0; z-index: 50;
  background: var(--paper); border-bottom: 1px solid var(--hairline);
  box-shadow: none; transition: box-shadow 200ms ease;
}
.masthead.is-scrolled { box-shadow: var(--shadow-masthead-scrolled); }
/* 62px, measured off the target, and the gap between the wordmark and the first navigation item is
   40px. The row was 64px and the navigation carried margin-left: auto, which pushed the six items
   to the far right and left half the bar empty. */
.masthead-row { display: flex; align-items: center; gap: 40px; min-height: 62px; }
.masthead-brand { display: inline-flex; align-items: center; gap: var(--s3); text-decoration: none; color: var(--ink); }
.masthead-brand .title { font-size: var(--t-label); font-weight: 600; line-height: 1.2; white-space: nowrap; }

/* THE WORDMARK IS THE RAIDIAM ASSET. The target draws the word itself and replaces the letter I
   with a ring over a dot; that is a comp device and not this company's logo. It was built here and
   taken out again. The asset is 131 by 24 and takes the height the target gives its own mark. */
.masthead-mark { height: 24px; width: auto; display: block; }

/* The navigation starts beside the wordmark. 15px labels, 36px apart, in the navigation ink. */
.masthead-nav { display: flex; gap: 36px; flex-wrap: wrap; }
/* THE TWO GAPS CLOSE BELOW THE TARGET'S OWN WIDTH, BECAUSE THE BAR CARRIES EIGHT ITEMS NOW.
   Films and Expo story joined the list on 27 September 2026. Measured before these rules: the eight
   labels want 612 pixels of text, seven gaps of 36 make 864, and at 1200 the space between the
   wordmark and the call to action is 708. The row wrapped, and How it works and Why Raidiam sat on a
   second line 81 pixels below the first, which reads as a broken masthead rather than a wide one.
   36px AND 40px ARE THE TARGET'S NUMBERS AND THEY ARE KEPT WHERE THE TARGET IS MEASURED. The
   reference build is read at 1440 and above, where the row fits with 100 pixels to spare, so nothing
   here changes what a screenshot of the target is compared against. */
@media (max-width: 1439px) {
  .masthead-nav { gap: 20px; }
  /* The row gap falls between the wordmark and the navigation AND between the navigation and the
     action, so 16 pixels off it hands 32 to the navigation. */
  .masthead-row { gap: 24px; }
}
/* WEIGHT 400 AT REST. The target gives an inactive link no weight class at all, so it renders at
   400 and the current item's 600 is a step a reader can see. Setting every link to 500 made the
   current one one step from its neighbours instead of two. */
.masthead-nav a { position: relative; color: var(--ink-nav); text-decoration: none; font-size: var(--t-small); font-weight: 400; padding: 11px 0; transition: color 150ms ease; }
/* HOVER LIFTS THE COLOUR AND DOES NOT UNDERLINE. An underline on hover and a mark on the current
   item are two different marks for two different things. */
.masthead-nav a:hover { color: var(--ink); }
/* THE CURRENT ITEM IS THE BRAND COLOUR AT WEIGHT 600, AND IT CARRIES NOTHING ELSE. It used to draw
   a 2px glowing bar on the masthead's bottom edge. The bar is the second row's mark. */
.masthead-nav a[aria-current="page"] { color: var(--teal-dark); font-weight: 600; }
/* An application masthead has no right hand group, so its navigation keeps the auto margin that
   used to sit on every masthead. */
.masthead-app .masthead-nav { margin-left: auto; }

/* The right hand group, at the hard right. The target puts a search control here beside the action.
   This site has no search, no index and no handler, so the group holds one thing. */
.masthead-right { display: flex; align-items: center; gap: var(--s5); margin-left: auto; }

/* THE CALL TO ACTION IS OUTLINED, and this file is the only place it is declared. It used to be
   declared here AND in apps/site/src/public/site.css as a filled pill, and because that sheet loads
   second it won: the rules here carried an extra class purely to outrank it. The site.css block is
   deleted, so one class is enough and the phone drawer state below belongs to this file too. */
.masthead-cta {
  display: inline-flex; align-items: center; gap: var(--s2);
  margin-left: 0; padding: 10px 20px; border-radius: var(--pill);
  border: 1px solid color-mix(in srgb, var(--teal-dark) 70%, transparent);
  background: transparent; color: var(--brand-strong);
  font-size: var(--t-label); font-weight: 600; line-height: 1.2;
  text-decoration: none; white-space: nowrap;
  transition: background-color 150ms ease, border-color 150ms ease;
}
/* The hover ground is --wash-teal rather than the brand at 10 percent. The stylesheet test refuses
   a colour-mix in a flat background because the contrast gate cannot name one. The label sits on
   this ground, so it is a flat token. */
.masthead-cta:hover {
  background: var(--wash-teal); color: var(--brand-strong);
  border-color: var(--teal-dark);
}
.masthead-cta .masthead-arrow { width: 16px; height: 16px; flex: none; transition: transform 150ms ease; }
.masthead-cta:hover .masthead-arrow { transform: translateX(2px); }

.masthead-menu { display: none; }
.masthead-note { font-size: var(--t-small); color: var(--ink-2); padding: var(--s2) 0; border-top: 1px solid var(--hairline); }

/* THE ARROW HOLDS STILL when a reader asks for less movement. This block sits after the rules it
   cancels and matches their specificity, so it wins without !important. */
@media (prefers-reduced-motion: reduce) {
  .masthead-cta .masthead-arrow { transition: none; }
  .masthead-cta:hover .masthead-arrow { transform: none; }
}

/* THE ROW BECOMES A MENU BUTTON AT 1239 AND IT USED TO BE 1199.
   The 40 pixels are the two items added on 27 September 2026, after the gaps above gave back all
   they could. With those gaps, eight labels need 752 pixels: measured at 1260 the navigation box is
   777 and holds them on one row, and at 1200 it is 717 and wraps. A bar that wraps to two rows is
   worse than a menu, because a reader reads the second row as a different navigation.
   MEASURE IT RATHER THAN TRUSTING THIS SUM. Add or rename an item, find the widest width that still
   wraps, and set this number above it. */
@media (max-width: 1239px) {
  .masthead-menu { display: inline-flex; margin-left: auto; }
  .masthead-nav { display: none; width: 100%; flex-direction: column; gap: 0; padding-bottom: var(--s3); }
  .masthead-nav a { padding: 12px 0; border-top: 1px solid var(--hairline); }
  .masthead.is-open .masthead-nav { display: flex; }
  .masthead-row { flex-wrap: wrap; gap: var(--s3); }
  .masthead.is-open .masthead-menu { margin-left: auto; }
  /* The menu button carries the auto margin here. Two auto margins in one row split the free space
     between them and would park the menu button in the middle of the bar, so the right hand group
     drops its own and follows the button, which is where the action sat before. */
  .masthead-right { margin-left: 0; gap: var(--s4); }
}
@media (max-width: 860px) {
  /* Two auto margins in one row split the free space between them, so the group gives its up and
     follows the menu button. */
  .masthead-right { margin-left: 0; }
}
@media (max-width: 480px) {
  .masthead-row { gap: var(--s2); }
  .masthead-brand .title { white-space: normal; max-width: 12ch; }
  /* ON A PHONE THE ACTION GOES INTO THE DRAWER. At 390 the wordmark takes 120px and the menu button
     94, which leaves 136 for a label reading "Book a working session", so the row wrapped and the
     bar became two right aligned buttons staggered down the corner.
     THE WIDTH IS ON THE GROUP, NOT ON THE ACTION. The rule this replaces set `width: 100%` on the
     action while it was a direct child of the row. The action is inside .masthead-right now, so the
     same declaration would resolve against a content sized flex item and do nothing. */
  .masthead-right { display: none; }
  .masthead.is-open .masthead-right { display: flex; width: 100%; margin-left: 0; }
  .masthead.is-open .masthead-cta {
    flex: 1 1 auto; justify-content: center;
    border-left: 0; border-right: 0; border-radius: 0;
    border-top: 1px solid var(--hairline);
  }
}
/* Customer side application mastheads carry their own name and a chip, no wordmark. The name sets
   its own size, weight and tracking, so the wordmark's 26px at weight 800 does not reach it. */
.masthead-app .masthead-brand .title { font-size: var(--t-h3); font-weight: 600; }

/* ---- src/parts/oa.css ---- */
/* /use-cases/your-own-assistant: the page and its one instrument, packages/ui/partials/oa-pairing.ejs.
 *
 * THE TREATMENTS ARE components/diagram-section.tsx's. No artefact in the reference build draws a
 * pairing, so the composition is ours and every surface on it is one of the reference's: the lit
 * card, the pedestal, the glowing bezier with a filled arrowhead, the ambient pool and the ringed
 * step row. The shared parts come from rw.css by class; this file places them and draws the two
 * devices.
 *
 * FOUR IDENTITY HUES AND NO STATE COLOUR. Each party carries its hue in `--hue` on its own element:
 * the customer blue (--d-blue), the assistant green (--d-magenta), the connector violet (--d-violet)
 * and the bank amber (--d-sand). Nothing on this
 * page is Observed, so --ok, --att and --no appear nowhere in this file.
 */

/* ---- THE PAGE ---- */
.oa-page { --page-max: 1472px; }
.oa-top {
  position: relative;
  padding-block: 3.5rem var(--s6);
  display: grid;
  gap: var(--s6);
}
/* ABOVE 1500 THE COPY SITS BESIDE THE INSTRUMENT, which is how the reference draws its hero. Below
   that the copy goes on top and the instrument takes the full measure, which is CLAUDE.md rule 5:
   match the proportion, not the absolute pixels. */
@media (min-width: 1500px) {
  .oa-top { grid-template-columns: minmax(0, 520px) minmax(0, 1fr); gap: var(--s6); align-items: start; }
  .oa-top-copy { padding-top: var(--s6); }
}
.oa-top-copy > * { margin: 0; }
.oa-top-copy .sc-eyebrow { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s3); letter-spacing: 0.22em; color: var(--slate); }
.oa-top-copy .sc-eyebrow .ev { letter-spacing: normal; text-transform: none; }
.oa-top-copy .sc-headline { margin-top: var(--s4); line-height: 1.02; letter-spacing: -0.035em; max-width: 22ch; }
/* BETWEEN 1100 AND 1500 THE COPY TAKES TWO COLUMNS OVER THE INSTRUMENT: the headline on the left,
   the lead and the actions on the right. One narrow column left the right half of the band empty
   above the figure. */
@media (min-width: 1100px) and (max-width: 1499px) {
  .oa-top-copy { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); column-gap: var(--s7, 4rem); grid-template-areas: "eyebrow eyebrow" "head lead" "head actions"; align-items: start; }
  .oa-top-copy .sc-eyebrow { grid-area: eyebrow; }
  .oa-top-copy .sc-headline { grid-area: head; align-self: start; }
  .oa-top-copy .sc-lead { grid-area: lead; align-self: start; }
  .oa-top-copy .sc-actions { grid-area: actions; }
}
.oa-top-copy .sc-headline .accent { display: block; }
.oa-top-copy .sc-lead { margin-top: 1.25rem; max-width: 34rem; font-size: 17px; line-height: 1.55; color: var(--ink-lead); }
.oa-top-copy .sc-actions { margin-top: var(--s6); display: flex; flex-wrap: wrap; gap: var(--s4); }
@media (min-width: 1500px) {
  .oa-top-copy .sc-lead { max-width: 30rem; }
}

/* THE ACTION THAT IS WAITING FOR ITS LINK. The launch kit has no address yet. An anchor with no
   href would still read as a link to a screen reader and do nothing when pressed, so this is a span
   with the outline pill's shape, a dashed edge, and the words "Link to follow" inside it. */
.oa-pending {
  display: inline-flex; align-items: center; gap: var(--s3);
  min-height: 44px; padding: 0 var(--s5);
  border: 1px dashed var(--rule); border-radius: 999px;
  color: var(--ink-2); font-size: 15px; font-weight: 600; cursor: default;
}
.oa-pending-note {
  white-space: nowrap;
  padding: 2px var(--s2); border-radius: 999px;
  border: 1px solid var(--hairline); background: var(--white);
  font-size: 14px; font-weight: 500; color: var(--ink-2);
}

/* ---- THE OUTCOME ROW, the reference's benefits row: ringed 52px glyphs, hairlines between ---- */
/* The band's own rule sits above this row, so the row draws none of its own. */
.oa-payoff { padding-block: var(--s6); }
.oa-outcomes {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
}
.oa-outcomes li { display: flex; flex-direction: column; align-items: center; text-align: center; padding: 0 var(--s4); }
.oa-outcomes li + li { border-left: 1px solid var(--hairline); }
.oa-outcome-i { width: 52px; height: 52px; }
.oa-outcome-i svg { width: 26px; height: 26px; }
.oa-outcome-t { margin: var(--s4) 0 0; font-size: 18px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.oa-outcome-l { margin: var(--s2) 0 0; max-width: 19rem; text-wrap: balance; font-size: 15px; line-height: 1.5; color: var(--ink-2); }
@media (max-width: 900px) {
  .oa-outcomes { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: var(--s6); }
  .oa-outcomes li + li { border-left: 0; }
  .oa-outcomes li:nth-child(even) { border-left: 1px solid var(--hairline); }
}
@media (max-width: 480px) {
  .oa-outcomes { grid-template-columns: minmax(0, 1fr); }
  .oa-outcomes li:nth-child(even) { border-left: 0; }
}

/* ---- THE INSTRUMENT ---- */
.oa { position: relative; margin: 0; display: grid; gap: 0; min-width: 0; }
.oa-glow { top: 40px; }
.oa-sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; border: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; }

/* THE STAGE: the Mac, the bridge, the phone. The column fractions are what the wire geometry in the
   partial is drawn against: the Mac's centre falls at 24 per cent and the phone's at 84. */
.oa-stage {
  position: relative;
  display: grid;
  grid-template-columns: 48fr 20fr 32fr;
  /* THE DEVICES STAND ON ONE LINE, because the wires leave from their bottom edges. Centred, the
     shorter Mac left the phone's wire starting 26px under the phone, in the air. */
  align-items: end;
}
.oa-stage > .oa-bridge { align-self: center; }

/* THE MAC WINDOW, in the assistant's hue. A lit card with a title bar. It is a size container, so
   the code inside it is sized to the window rather than to the viewport: the window is 160px wide at
   320 and 660 at 1440, and one viewport rule cannot fit both. */
.oa-mac {
  container-type: inline-size;
  position: relative; border-radius: 14px; overflow: hidden;
  border: 1px solid color-mix(in srgb, var(--hue) 30%, transparent);
  background: linear-gradient(180deg, var(--white) 0%, var(--paper-alt) 100%);
  box-shadow: 0 0 48px color-mix(in srgb, var(--hue) 14%, transparent),
              inset 0 1px 0 color-mix(in srgb, var(--hue) 45%, transparent);
}
.oa-mac-bar {
  display: flex; gap: 7px; align-items: center; height: 34px; padding: 0 var(--s4);
  border-bottom: 1px solid var(--hairline);
  background: linear-gradient(180deg, color-mix(in srgb, var(--hue) 10%, transparent) 0%, color-mix(in srgb, var(--hue) 4%, transparent) 100%);
}
.oa-mac-bar i { width: 11px; height: 11px; border-radius: 50%; background: var(--hairline); }
.oa-mac-body { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s4); padding: var(--s5); }
.oa-who { display: flex; align-items: center; gap: var(--s3); }
.oa-who-i, .oa-conn-i, .oa-app-i, .oa-face-i, .oa-signed-i, .oa-row-i { display: inline-flex; flex: none; color: var(--hue); }
.oa-who-i svg { width: 28px; height: 28px; filter: drop-shadow(0 0 8px var(--hue)); }
.oa-who > span:last-child, .oa-conn-h > span:last-child { display: grid; min-width: 0; overflow-wrap: anywhere; }
.oa-who-t { font-size: 16px; font-weight: 700; color: var(--ink); }
.oa-who-l { font-size: 14px; color: var(--ink-2); }

/* THE CONNECTOR, inside the assistant's window, in its own hue. It is the governed identity, so it
   is drawn as the reference's environment card: lit from above in its hue. */
.oa-conn {
  border-radius: 10px; padding: var(--s4) var(--s5) var(--s5);
  border: 1px solid var(--hairline);
  border-top-color: color-mix(in srgb, var(--hue) 55%, transparent);
  background: linear-gradient(180deg, color-mix(in srgb, var(--hue) 7%, transparent) 0%, transparent 100%);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--hue) 40%, transparent);
}
.oa-conn-h { margin: 0; display: flex; align-items: center; gap: var(--s3); }
.oa-conn-i .sc-glyph svg, .oa-row-i .sc-glyph svg, .oa-app-i .sc-glyph svg, .oa-signed-i .sc-glyph svg { width: 22px; height: 22px; display: block; }
.oa-conn-t { font-size: 15px; font-weight: 700; color: var(--ink); }
.oa-conn-l { font-size: 14px; color: var(--ink-2); }
.oa-ask { margin: 0; font-size: 14px; color: var(--ink-2); }
/* IT WRAPS. At some widths the code and the QR drawing do not fit on one row, and a row that does
   not wrap was cut off by the window's rounded edge. */
.oa-conn-body { margin-top: var(--s4); display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: var(--s4) var(--s5); }
/* THE QR DRAWING AND THE HANDOVER LINE, the first two steps of pairing, beside the code. */
.oa-scan { display: grid; justify-items: center; gap: var(--s2); flex: none; }
.oa-qr { width: 104px; height: 104px; display: block; }
.oa-qr-ground { fill: var(--ink); }
.oa-qr-ink { fill: var(--paper); }
.oa-scan-l { margin: 0; font-size: 14px; color: var(--ink-2); }
.oa-near { margin: 0; display: inline-flex; align-items: center; gap: var(--s2); font-size: 14px; font-weight: 600; color: var(--ink); }
.oa-near-i { display: inline-flex; color: var(--d-blue); }
.oa-near-i svg { width: 18px; height: 18px; }

/* THE MATCHING CODE, printed on both screens from one value. The groups are spaced rather than
   separated by a character. The partial puts a hidden "Matching code" before them and a real space
   between them, so a screen reader and a copy both read "48 29 15". */
.oa-code { margin: var(--s2) 0 0; display: flex; flex-wrap: nowrap; gap: 0.2em; font-variant-numeric: tabular-nums; font-weight: 700; color: var(--ink); letter-spacing: 0.04em; }
.oa-code-g { border-radius: 8px; padding: 0.08em 0.28em; background: var(--wash-teal); border: 1px solid color-mix(in srgb, var(--teal-dark) 30%, transparent); }
.oa-code-mac { font-size: clamp(16px, 11cqi, 40px); }
.oa-code-phone { font-size: 24px; justify-content: center; }

/* THE BRIDGE between the two screens. */
.oa-bridge { display: flex; align-items: center; gap: var(--s2); padding: 0 var(--s3); }
.oa-bridge-line { flex: 1; height: 0; border-top: 2px dashed color-mix(in srgb, var(--teal-dark) 70%, transparent); }
.oa-bridge-chip {
  flex: none; max-width: 9rem; text-align: center;
  padding: var(--s2) var(--s3); border-radius: 10px;
  border: 1px solid color-mix(in srgb, var(--teal-dark) 45%, transparent);
  background: var(--wash-teal); color: var(--brand-strong);
  font-size: 14px; font-weight: 600; line-height: 1.3;
  box-shadow: 0 0 24px color-mix(in srgb, var(--teal-dark) 18%, transparent);
}

/* THE PHONE, in the customer's hue. The app inside it is the bank's, in the bank's hue. */
.oa-phone {
  justify-self: center; width: 100%; max-width: 270px;
  border-radius: 36px; padding: 9px;
  background: linear-gradient(180deg, color-mix(in srgb, var(--hue) 28%, var(--white)) 0%, var(--white) 100%);
  box-shadow: 0 0 44px color-mix(in srgb, var(--hue) 22%, transparent),
              inset 0 1px 0 color-mix(in srgb, var(--hue) 60%, transparent);
}
.oa-phone-screen {
  position: relative; border-radius: 28px; padding: 38px var(--s4) var(--s5);
  background: linear-gradient(180deg, var(--paper-alt) 0%, var(--paper) 100%);
  border: 1px solid var(--hairline);
  display: grid; gap: var(--s3); justify-items: center; text-align: center;
}
.oa-phone-notch { position: absolute; top: 10px; left: 50%; transform: translateX(-50%); width: 34%; height: 16px; border-radius: 999px; background: var(--paper); border: 1px solid var(--hairline); }
.oa-app { margin: 0; display: inline-flex; align-items: center; gap: var(--s2); font-size: 15px; font-weight: 700; color: var(--ink); padding-bottom: var(--s2); border-bottom: 2px solid var(--hue); }
.oa-phone-ask { margin: 0; font-size: 14px; line-height: 1.35; color: var(--ink-lead); }
.oa-face, .oa-signed { margin: 0; display: inline-flex; align-items: center; gap: var(--s2); font-size: 14px; font-weight: 600; color: var(--ink); }
.oa-face-i svg { width: 34px; height: 34px; filter: drop-shadow(0 0 8px var(--hue)); }
.oa-face { flex-direction: column; gap: var(--s1, 4px); }
.oa-signed { padding: var(--s2) var(--s3); border-radius: 999px; border: 1px solid var(--hairline); background: var(--white); }
.oa-signed-i { color: var(--d-blue); }

/* THE WIRES, two beziers from the connector and the phone down to the bank, drawn at a fixed height
   and stretched across the figure's width. The stroke does not scale, so the line weight holds at
   every width. The arrowhead is a separate element because a stretched svg would stretch it too. */
.oa-wires { position: relative; height: 128px; }
.oa-wires-narrow { display: none; }
.oa-wires svg { position: absolute; inset: 0; width: 100%; height: 120px; overflow: visible; filter: drop-shadow(0 0 5px color-mix(in srgb, var(--teal-dark) 60%, transparent)); }
.oa-wire { fill: none; stroke: var(--hue); stroke-width: 2; stroke-linecap: round; opacity: 0.85; vector-effect: non-scaling-stroke; }
.oa-pulse { fill: none; stroke: var(--brand-strong); stroke-width: 4; stroke-linecap: round; vector-effect: non-scaling-stroke; stroke-dasharray: 6 94; stroke-dashoffset: 6; opacity: 0; }
.oa-wire-head {
  position: absolute; left: 50%; top: 110px; transform: translateX(-50%);
  width: 0; height: 0; border-left: 7px solid transparent; border-right: 7px solid transparent;
  border-top: 12px solid var(--brand-strong);
}
.oa-wire-l {
  position: absolute; top: 44px; transform: translateX(-50%);
  padding: 3px var(--s3); border-radius: 999px; white-space: nowrap;
  border: 1px solid color-mix(in srgb, var(--hue) 45%, transparent);
  background: var(--paper); color: var(--ink);
  font-size: 14px; font-weight: 600;
}
.oa-wire-l::before { content: ""; display: inline-block; width: 8px; height: 8px; margin-right: var(--s2); border-radius: 50%; background: var(--hue); vertical-align: 1px; }
/* THE LABELS SIT BESIDE THE WIRES, NOT ON THEM. On the wire, the opaque label hid the pulse as it
   passed. The connector's label ends left of its wire and the phone's starts right of its wire. */
.oa-wire-l-conn { left: auto; right: 72%; transform: none; }
.oa-wire-l-phone { left: 76%; transform: none; }

/* THE BANK, the reference's environment card on its pedestal, in the bank's hue. */
.oa-bank { justify-self: center; width: min(100%, 440px); margin-top: -8px; }
.oa-bank .rw-ped { margin-bottom: -6px; }
.oa-bank-card { padding: var(--s5) var(--s5) var(--s5); }
.oa-bank-t { margin: 0; font-size: 20px; font-weight: 700; color: var(--ink); }
.oa-bank-l { margin: var(--s1, 4px) 0 0; font-size: 14px; color: var(--ink-2); }
.oa-rows { list-style: none; margin: var(--s4) 0 0; padding: 0; display: grid; gap: var(--s3); }
.oa-rows li { display: flex; align-items: flex-start; gap: var(--s3); }
.oa-rows li > span:last-child { display: grid; }
.oa-row-t { font-size: 14px; font-weight: 600; color: var(--ink-row); }
.oa-row-d { font-size: 14px; color: var(--ink-2); }

/* THE STEP RAIL. Four numbered steps, each ringed in the hue of the party that acts. */
.oa-steps {
  list-style: none; margin: var(--s6) 0 0; padding: var(--s5) 0 0;
  border-top: 1px solid var(--hairline);
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
}
.oa-step { display: flex; gap: var(--s3); align-items: flex-start; padding: 0 var(--s4); }
.oa-step + .oa-step { border-left: 1px solid var(--hairline); }
.oa-step > span:last-child { display: grid; }
.oa-step-n {
  flex: none; display: inline-grid; place-items: center; width: 34px; height: 34px; border-radius: 50%;
  border: 1.5px solid var(--hue); color: var(--ink); font-size: 15px; font-weight: 700;
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--hue) 10%, transparent);
}
.oa-step-t { font-size: 15px; font-weight: 700; color: var(--ink); }
.oa-step-l { font-size: 14px; line-height: 1.4; color: var(--ink-2); }

/* ---- THE LOOP ----
   Twelve seconds, four quarters, one step lit in each. Nothing appears or disappears: every element
   is on screen in every frame, and the loop only moves the light. */
@media (prefers-reduced-motion: no-preference) {
  .oa-code-g { animation: oa-code 12s ease-in-out infinite; }
  .oa-bridge-chip { animation: oa-bridge 12s ease-in-out infinite; }
  .oa-face-i { animation: oa-face 12s ease-in-out infinite; }
  .oa-signed { animation: oa-signed 12s ease-in-out infinite; }
  .oa-pulse-phone { animation: oa-pulse 12s linear infinite; }
  .oa-pulse-conn { animation: oa-pulse-conn 12s linear infinite; }
  .oa-bank-card { animation: oa-bank 12s ease-in-out infinite; }
  .oa-step-n { animation: oa-step 12s ease-in-out infinite; }
  .oa-step[data-step="2"] .oa-step-n { animation-delay: 3s; }
  .oa-step[data-step="3"] .oa-step-n { animation-delay: 6s; }
  .oa-step[data-step="4"] .oa-step-n { animation-delay: 9s; }
}
@keyframes oa-code {
  0%, 25%, 100% { box-shadow: none; }
  6%, 19% { box-shadow: 0 0 18px color-mix(in srgb, var(--teal-dark) 55%, transparent); }
}
@keyframes oa-bridge {
  0%, 25%, 100% { transform: none; }
  8%, 17% { transform: scale(1.06); }
}
@keyframes oa-face {
  0%, 25%, 50%, 100% { transform: none; }
  32%, 43% { transform: scale(1.18); }
}
@keyframes oa-signed {
  0%, 50%, 75%, 100% { box-shadow: none; }
  56%, 70% { box-shadow: 0 0 20px color-mix(in srgb, var(--d-blue) 50%, transparent); }
}
@keyframes oa-pulse {
  0%, 52% { opacity: 0; stroke-dashoffset: 6; }
  54% { opacity: 1; stroke-dashoffset: 6; }
  73% { opacity: 1; stroke-dashoffset: -94; }
  75%, 100% { opacity: 0; stroke-dashoffset: -94; }
}
@keyframes oa-pulse-conn {
  0%, 1% { opacity: 0; stroke-dashoffset: 6; }
  3% { opacity: 1; stroke-dashoffset: 6; }
  22% { opacity: 1; stroke-dashoffset: -94; }
  24%, 100% { opacity: 0; stroke-dashoffset: -94; }
}
@keyframes oa-bank {
  0%, 75%, 100% { box-shadow: inset 0 1px 0 color-mix(in srgb, var(--hue) 33%, transparent); }
  81%, 94% { box-shadow: inset 0 1px 0 color-mix(in srgb, var(--hue) 70%, transparent), 0 0 44px color-mix(in srgb, var(--hue) 28%, transparent); }
}
@keyframes oa-step {
  0%, 25%, 100% { box-shadow: 0 0 0 4px color-mix(in srgb, var(--hue) 10%, transparent); }
  5%, 20% { box-shadow: 0 0 0 4px color-mix(in srgb, var(--hue) 30%, transparent), 0 0 18px color-mix(in srgb, var(--hue) 45%, transparent); }
}

/* ---- THE NARROW STATE ----
   The two screens stay side by side, because the claim is that they agree. The bridge becomes a chip
   above them, the Mac drops its assistant line to a single row, the wire labels
   are left to the bank card, and the step rail goes to two by two. */
@media (max-width: 1100px) {
  /* Between 760 and 1100 a label placed against its wire runs off the figure's edge, as the
     connector's did by 1px at 800. Each label sits against the figure's own edge instead, which is
     still outside its wire. */
  .oa-wire-l-conn { right: auto; left: 0; }
  .oa-wire-l-phone { left: auto; right: 0; }
}
@media (min-width: 1500px) {
  /* Beside the copy the bridge column is narrow, and two dashes either side of the chip read as
     noise rather than as a line. */
  .oa-bridge-line { display: none; }
}
@media (max-width: 760px) {
  .oa-stage { grid-template-columns: 58fr 42fr; column-gap: var(--s3); row-gap: var(--s3); }
  /* THE CHIP GOES ABOVE THE TWO SCREENS, so the wires leave from the devices themselves. */
  .oa-bridge { grid-column: 1 / -1; grid-row: 1; padding: 0; justify-content: center; }
  .oa-bridge-line { display: none; }
  .oa-bridge-chip { max-width: none; }
  .oa-mac { grid-column: 1; grid-row: 2; }
  .oa-phone { grid-column: 2; grid-row: 2; border-radius: 26px; padding: 6px; }
  .oa-wires-wide { display: none; }
  .oa-wires-narrow { display: block; }
  .oa-phone-screen { border-radius: 21px; padding: 28px var(--s2) var(--s3); gap: var(--s2); }
  .oa-phone-notch { top: 8px; height: 12px; }
  .oa-app { font-size: 14px; }
  .oa-app-i { display: none; }
  .oa-code-phone { font-size: 18px; }
  .oa-code-g { padding: 0.06em 0.18em; border-radius: 6px; }
  .oa-face-i svg { width: 26px; height: 26px; }
  .oa-signed { padding: 2px var(--s2); }
  .oa-signed-i { display: none; }
  .oa-mac-bar { height: 24px; padding: 0 var(--s3); gap: 5px; }
  .oa-mac-bar i { width: 8px; height: 8px; }
  .oa-mac-body { padding: var(--s3); gap: var(--s3); }
  .oa-who-l { display: none; }
  .oa-who-i svg { width: 22px; height: 22px; }
  .oa-conn { padding: var(--s3); }
  .oa-conn-l { display: none; }
  .oa-scan { display: none; }
  .oa-conn-body { margin-top: var(--s2); }
  .oa-ask { margin-top: var(--s2); }
  .oa-wires { height: 96px; }
  .oa-wires svg { height: 88px; }
  .oa-wire-head { top: 80px; }
  /* The two wire labels say what the bank card's first and third rows say, and at this width they
     would sit on top of each other. The card carries them. */
  .oa-wire-l { display: none; }
  .oa-steps { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: var(--s5); }
  .oa-step { padding: 0 var(--s3); }
  .oa-step + .oa-step { border-left: 0; }
  .oa-step:nth-child(even) { border-left: 1px solid var(--hairline); }
}

/* THE LABEL ON THE EVIDENCE ROUTE. uc-evidence.ejs draws it under the lead only when a use case
   declares one, which today is this page alone. */
.uce-copy .uce-ev { margin: var(--s3) 0 0; }

/* ---- src/parts/rail.css ---- */
/* The capability flow rail, partials/rail.ejs.
 *
 * WHY THIS IS A PART AND NOT AN EDIT TO src/ui.css. Two components carry the class `rail`. This one
 * is the home page figure, rendered by partials/rail.ejs. The other is the slide diagram built by
 * video/assets/lib/diagrams/rail.mjs, which writes its own markup and prints a paragraph per stage.
 * Those films are rendered and approved. So every rule here is scoped to `.rail-flow`, a class only
 * the partial writes, and the base `.rail` rules in src/ui.css stay exactly as the slide found them.
 * Parts load after the base sheet, so a rule of the same specificity here wins.
 *
 * COLOUR. Five rings take the accent and the sixth, Revoke, takes the refused colour. That follows
 * panel 5 of the visual asset pack. --teal is not used: it fills a Raidiam product marker and
 * nothing else, and these rings are strokes on six stages with four different owners. Red here is
 * the withdrawn state, which is what the token means; the owner is still on the item as
 * data-owner and still printed as the treatment under each stage.
 */

/* Reset what a stage is given elsewhere: a card ground and card padding from the base .rail, and a
   radius, a 1px stroke and a lift from apps/site/src/public/site.css, which loads after this sheet
   and states `.rail .stage` at the same specificity. `.rail.rail-flow` is one class more, so the
   reset lands whichever order the two sheets arrive in. This figure is six items on the page
   ground, as the reference sheet draws it: no card, no rule, no shadow.
   THE OWNER COLOUR THE CARD CARRIED is the 3px top border of .owner-rule, and it goes with the
   card. The owner is still on the item as data-owner, and still shown as the treatment swatch and
   word under each stage. */
.rail-flow { grid-template-columns: repeat(6, minmax(0, 1fr)); grid-template-rows: auto auto auto auto; gap: var(--s5); align-items: start; }
.rail.rail-flow .stage {
  position: relative;
  background: transparent;
  padding: 0;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  /* Four rows, shared with every sibling, so the verbs line up and so do the short lines and the
     owners, whatever length each one runs to. Without this each stage is its own grid and a two
     line short line drops that stage's owner below the rest of the row. */
  grid-row: span 4;
  grid-template-rows: subgrid;
  justify-items: center;
  text-align: center;
  gap: 0;
}
/* The current stage. The base rail states it as a wash behind a card, and this figure has no card,
   so it is stated on the ring and the verb instead. The home page marks none; the component gallery
   and any page that passes `current` do. */
.rail.rail-flow .stage.is-current { background: transparent; }
.rail.rail-flow .stage.is-current .disc {
  border-color: var(--teal-dark);
  box-shadow: 0 0 0 7px color-mix(in srgb, var(--teal-dark) 14%, transparent), 0 0 30px color-mix(in srgb, var(--teal-dark) 34%, transparent);
}
.rail.rail-flow .stage.is-current .verb { color: var(--teal-dark); }

/* The ring. The inner wash lifts the disc off the page ground; the outer glow is what makes a flat
   outline read as a lit object rather than a drawn one. Both are mixed from a token, so no literal
   colour enters the sheet.
 *
 * THE GRADIENT MAKES THIS DISC A NODE AXE CANNOT READ, and the numbers are therefore recorded here
 * rather than left to a tool. axe resolves contrast from background-color; it returns
 * colour-contrast as incomplete over any gradient, so nothing watches the icon on this fill. An
 * inset shadow instead of the gradient would be worse, not better: axe would then read the flat
 * token underneath and return a PASS that ignores the lightening, which is a wrong answer rather
 * than no answer.
 *
 * Measured from the painted pixels at 1440 wide, icons hidden to isolate the fill, on
 * 2026-09-12. The fill runs from rgb(3, 50, 60) at the rim to rgb(6, 68, 77) at the gradient's
 * centre, which is the worst point:
 *   accent icon rgb(21, 212, 216) on rgb(6, 68, 77)   5.89     (7.50 at the rim)
 *   Revoke icon rgb(233, 85, 102) on rgb(68, 31, 42)  4.04     (4.67 at the rim)
 *   accent ring on the page ground                    6.75
 *   Revoke ring on the page ground                    3.65
 * These are graphic strokes, so the floor is the 3 to 1 of WCAG 1.4.11, not 4.5. Anything that
 * lightens the gradient further has to be measured again, because no test will catch it. */
/* THE RING IS GONE AND THE MARK CARRIES ITSELF. This was a 76px disc with a stroked edge, a wash
   ground and two shadows, drawn around a line icon. The Raidiam Agents reference lays its rendered
   mark straight on the page over a soft disc of the accent, with no edge at all, and a ring around
   rendered artwork reads as two frames rather than one.
   The mask is the same one the environment cards need and for the same measured reason: the
   artwork is opaque on a dark ground rather than transparent, so without it each mark draws a
   square. A mask reads alpha and ignores hue, so the token named is arbitrary. */
.rail-flow .disc {
  position: relative;
  width: 72px; height: 72px;
  display: grid; place-items: center;
  transition: transform var(--m-drawer) ease;
}
.rail-flow .disc::before {
  content: ""; position: absolute; inset: 14%; border-radius: 50%;
  background: radial-gradient(circle, color-mix(in srgb, var(--teal-mid) 30%, transparent) 0%, transparent 70%);
  filter: blur(12px);
}
.rail-flow .disc img {
  position: relative; width: 100%; height: 100%; object-fit: contain; display: block;
  -webkit-mask-image: radial-gradient(circle, var(--ink) 56%, transparent 74%);
  mask-image: radial-gradient(circle, var(--ink) 56%, transparent 74%);
}

/* Revoke. The one stage that takes authority away, in the colour this system already uses for
   refused, withdrawn and stopped. */
/* Revoke. The one stage that takes authority away. The ring that used to carry that in the
   withdrawn colour is gone with every other ring, so the disc behind it carries it instead. */
.rail-flow .stage[data-stage="revoke"] .disc::before {
  background: radial-gradient(circle, color-mix(in srgb, var(--no) 30%, transparent) 0%, transparent 70%);
}

/* The step index. It sits at the ring's upper left rather than beside the verb, so the verb reads as
   one word and the sequence is still countable. The reference sheet prints no number and leans on
   the arrows; an ordered list already says the order to a screen reader, and the numeral is what
   lets somebody point at stage four in a room. */
.rail.rail-flow .stage .verb { font-size: var(--t-h3); line-height: var(--t-h3-line); display: block; margin-top: var(--s3); font-variant-numeric: tabular-nums; }
.rail.rail-flow .stage .verb .n {
  position: absolute; top: 2px; left: 50%;
  margin-left: -52px;
  font-size: var(--t-label); line-height: 1;
  color: var(--ink-2);
}
.rail.rail-flow .stage a.verb { text-decoration: none; }
.rail.rail-flow .stage a.verb:hover { text-decoration: underline; }
.rail-flow .short { font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-2); max-width: 19ch; margin-top: var(--s2); }
/* The owner, under the short line. It names who runs the stage, which the reference sheet leaves
   out and this repository requires on every non Raidiam runtime component. The swatch is set inline
   with the first word rather than centred beside a wrapped block, so a two line owner still reads
   as one label. */
.rail-flow .treat, .rail-flow .std { font-size: var(--t-label); color: var(--ink-2); margin-top: var(--s3); }
.rail-flow .treat { display: block; }
.rail-flow .treat .swatch { display: inline-block; vertical-align: -1px; margin-right: 6px; }

/* The arrow between two stages, drawn in the gap rather than inside either box, so it never moves
   when a verb or a line changes length. The gap is one --s5, and so is the arrow's box. */
.rail-flow .stage::after {
  content: "";
  position: absolute; top: 38px; left: 100%;
  width: var(--s5); height: 10px;
  transform: translateY(-50%);
  /* The token flat, softened with opacity rather than a colour-mix: the stylesheet test refuses a
     colour-mix in a background, because the contrast gate enumerates token pairs by name and cannot
     see a mix at all. An earlier version of that rule blamed axe, which was wrong; axe resolves a
     mix fine. */
  background: var(--teal-dark);
  opacity: 0.85;
  -webkit-mask: var(--arrow-right) center / 15px 10px no-repeat;
  mask: var(--arrow-right) center / 15px 10px no-repeat;
}
.rail-flow .stage:last-child::after { content: none; }

/* The hover lift stays and the ring it used to brighten is gone, so the disc behind the mark grows
   instead. Two rules that set border-color and box-shadow on an element that now has neither were
   left behind by the ring's removal and are deleted here rather than left to read as live. */
.rail-flow .stage:hover .disc, .rail-flow .stage:focus-within .disc {
  transform: translateY(-2px);
}
.rail-flow .stage:hover .disc::before, .rail-flow .stage:focus-within .disc::before {
  background: radial-gradient(circle, color-mix(in srgb, var(--teal-mid) 46%, transparent) 0%, transparent 72%);
}
.rail-flow .stage[data-stage="revoke"]:hover .disc::before, .rail-flow .stage[data-stage="revoke"]:focus-within .disc::before {
  background: radial-gradient(circle, color-mix(in srgb, var(--no) 46%, transparent) 0%, transparent 72%);
}

/* SIX IN A ROW IS THE THING THAT BREAKS A NARROW SCREEN, so the row wraps rather than scrolls: a
   scrolling row hides half the figure behind a gesture, and this figure is the page's argument. The
   arrow is removed at the end of each wrapped row, where it would point into the gutter. */
@media (max-width: 1040px) {
  .rail-flow { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s5) var(--s5); row-gap: var(--s7); }
  .rail-flow .stage:nth-child(3n)::after { content: none; }
}
@media (max-width: 560px) {
  .rail-flow { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s4); row-gap: var(--s6); }
  .rail-flow .stage:nth-child(3n)::after { content: ""; }
  .rail-flow .stage:nth-child(2n)::after { content: none; }
  .rail-flow .stage:last-child::after { content: none; }
  .rail-flow .disc { width: 62px; height: 62px; }
  .rail-flow .disc svg { width: 28px; height: 28px; }
  .rail-flow .stage::after { top: 31px; width: var(--s4); }
  .rail-flow .stage .verb .n { margin-left: -44px; }
}

@media (prefers-reduced-motion: reduce) {
  .rail-flow .disc { transition: none; }
  .rail-flow .stage:hover .disc, .rail-flow .stage:focus-within .disc { transform: none; }
}

/* ---- src/parts/raw-view.css ---- */
/* /raw, the HTML form of a declared read. apps/site/src/views/raw.ejs is the only caller.
 *
 * WHAT THIS FILE IS. The four layer viewer: the read drawn as an instrument, the answer resolved
 * into fields, the envelope, and the bytes. It reuses the reference treatments already ported into
 * src/parts/rw.css rather than restating them, so a correction to the pedestal, the panel or the
 * pill lands here too.
 *
 * WHAT IT REFUSES TO DRAW, AND WHY.
 *
 * A STATE COLOUR. --ok, --att and --no are absent from this file. Green means Observed on this
 * site, and the evidence chip in the hero is the only thing on the page entitled to say it. Every
 * colour below is either ink, a rule, brand, or one of the four identity hues, and a hue arrives on
 * the element as --rv-hue rather than being written into a rule.
 *
 * A WIDTH OF ITS OWN. The page takes the interior measure, 1036, which is what /evidence and
 * /artefact take. A byte viewer sitting beside them at a fourth width would be the exact fault the
 * tracker records as F2.
 *
 * A SIZE BELOW THE FLOOR. Nothing here sets under 14px. The bytes block is mono inside a scrolling
 * region, which is the one place the stylesheet test allows 13px, and it does not use it: a reader
 * who opened the bytes wants to read them.
 */

/* THE PAGE. --page-max is the CONTENT width and the gutter sits outside it, so this is the
   reference's 1100px box less its 64px of padding. `.wrap` reads it from this ancestor. */
.rv-page { --page-max: 1036px; position: relative; }

/* ---- layer 1: the claim and the instrument ------------------------------------------------- */

.rv-hero { position: relative; overflow: hidden; }
.rv-hero-grid { display: grid; gap: var(--s6); align-items: center; }
@media (min-width: 900px) {
  /* THE COPY COLUMN IS 460, NOT 380. The reference sets its hero copy at 500 against a 1536 box;
     at the interior 1036 that proportion is 460, and the display breaks over three lines rather
     than four. A 380 column is the exact fault CLAUDE.md records against the same software page. */
  .rv-hero-grid { grid-template-columns: minmax(0, 460px) minmax(0, 1fr); gap: var(--s6); }
}

.rv-eyebrow { color: var(--teal-dark); letter-spacing: 0.22em; }
.rv-hero-copy h1 { margin: var(--s3) 0 0; overflow-wrap: anywhere; }
.rv-lede { margin: var(--s4) 0 0; font-size: var(--t-body); line-height: var(--t-body-line); color: var(--ink-lead); max-width: var(--measure-body); }
.rv-chip { margin: var(--s4) 0 0; }
.rv-actions { margin-top: var(--s5); }

/* The figure. It carries the argument, so it is given the larger half of the row and it keeps its
   aspect at every width rather than being cropped into a strip. */
.rv-fig { margin: 0; min-width: 0; }
.rv-svg { display: block; width: 100%; height: auto; overflow: visible; }

/* The wire. Both arcs are drawn lit, because the page is about one read that completed rather than
   about a route that might be taken. */
.rv-wire { stroke-width: 2; stroke-linecap: round; opacity: 0.9; }
.rv-tick { opacity: 0.85; }

/* The two ends, drawn as the pedestal reduced to a node: a soft pool of the hue, a ring, a core. */
.rv-halo { opacity: 0.18; }
.rv-ring { fill: none; stroke-width: 1.6; opacity: 0.85; }
.rv-core { opacity: 1; }

/* The plates. What came back: the envelope over the statement when the answer is signed, one plate
   when it is not. Filled at low alpha so the hue reads as identity rather than as a block of paint. */
.rv-plate { fill-opacity: 0.14; stroke-width: 1.4; stroke-opacity: 0.8; }
.rv-seal { stroke: var(--teal-dark); stroke-width: 1.6; }
.rv-seal-dot { fill: var(--teal-deep); }

/* The fan. One lead line per resolved field, leaving the statement plate for the list below. */
.rv-lead { fill: none; stroke-width: 1.4; opacity: 0.7; }
.rv-lead-dot { opacity: 0.95; }

.rv-legend { display: flex; flex-wrap: wrap; gap: var(--s3) var(--s5); margin-top: var(--s4); font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-2); }
.rv-legend-item { display: inline-flex; align-items: center; gap: var(--s2); }
.rv-swatch { width: 10px; height: 10px; border-radius: 3px; flex: 0 0 auto; background: var(--rv-hue, var(--teal-dark)); }

/* ---- the three lower layers ------------------------------------------------------------------ */

.rv-band { position: relative; }
.rv-step { display: flex; align-items: center; gap: var(--s3); margin: 0; color: var(--ink-2); }
/* The layer numeral. A ring in the layer's hue, which is the one place the four hues answer
   "which layer of the page is this" rather than "which end of the wire". */
.rv-step-n {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: 50%; flex: 0 0 auto;
  border: 1px solid var(--rv-hue, var(--teal-dark));
  color: var(--rv-hue, var(--teal-dark));
  font-size: var(--t-small); font-weight: 600;
}
.rv-h2 { margin: var(--s4) 0 0; font-size: var(--t-h2); line-height: var(--t-h2-line); font-weight: var(--t-h2-weight); letter-spacing: var(--t-h2-tracking); overflow-wrap: anywhere; }
.rv-note { margin: var(--s4) 0 0; font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-2); }

/* Layer 2: the fields. A row per field, its hue on the left edge, so a reader carries one colour
   from a lead line in the figure into the row that names it. */
.rv-fields { display: grid; gap: var(--s3); margin: var(--s5) 0 0; }
@media (min-width: 760px) {
  .rv-fields { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s4); }
}
.rv-field {
  border-radius: 10px;
  border: 1px solid var(--rule);
  border-left: 3px solid var(--rv-hue, var(--teal-dark));
  border-top-color: var(--rv-hue, var(--rule));
  background: var(--paper);
  padding: var(--s4);
  min-width: 0;
}
.rv-term { font-size: var(--t-label); font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-2); }
.rv-value { display: block; margin: var(--s2) 0 0; font-size: var(--t-body); line-height: var(--t-body-line); color: var(--ink); overflow-wrap: anywhere; }
.rv-fnote { margin: var(--s2) 0 0; font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-2); }

/* Layer 3: the envelope. Three facts about the signature, side by side. */
.rv-env { display: grid; gap: var(--s4); margin: var(--s5) 0 0; }
@media (min-width: 760px) {
  .rv-env { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
.rv-env-item {
  border-radius: 10px;
  border: 1px solid var(--rule);
  border-top: 2px solid var(--rv-hue, var(--teal-dark));
  background: var(--paper);
  padding: var(--s4);
  min-width: 0;
}
.rv-env-item .rv-value { font-size: var(--t-small); line-height: var(--t-small-line); }

/* Layer 4: the URL and the bytes. */
.rv-url { margin: var(--s4) 0 var(--s4); font-size: var(--t-small); line-height: var(--t-small-line); color: var(--ink-2); overflow-wrap: anywhere; }
.rv-pane { margin-top: var(--s4); }
/* The block scrolls sideways, so it is a focus stop and the view gives it tabindex and a label.
   axe calls the alternative scrollable-region-focusable and rates it serious. */
.rv-pre {
  margin: 0; max-height: 420px; overflow: auto;
  border-radius: 10px; border: 1px solid var(--rule);
  background: var(--paper-alt);
  padding: var(--s4);
  font-family: var(--mono); font-size: 14px; line-height: var(--t-mono-line);
  color: var(--ink);
}

/* ---- src/parts/rnr.css ---- */
/* THE EVIDENCE FIGURES FOR RESOLVED, NOT REGISTERED: packages/ui/partials/rnr-chain.ejs and
 * rnr-ceilings.ejs, rendered on /use-cases/resolved-not-registered/evidence.
 *
 * THE TREATMENTS ARE components/diagram-section.tsx's, by class from rw.css: the small pedestal, the
 * hub, the ambient pool. This file places them and draws the lanes and the rings.
 *
 * IDENTITY HUES ONLY. A lane's hue says which authority and a ring's hue says which ceiling. Neither
 * figure is a reading from a run, so --ok, --att and --no appear nowhere here.
 *
 * EVERY SIZE IS 14PX OR MORE, and every ground a word sits on is a plain token, because contrast.mjs
 * gates token pairs by name and cannot read a colour-mix.
 *
 * rw.css SORTS AFTER THIS FILE, so a rule here that restyles an rw- class names its figure as well:
 * .rnr-ch .rnr-ch-result.
 */

/* ================================================================
   rnr-chain: one agent, one lane per authority, the client under them.
   ================================================================ */
.rnr-ch { position: relative; margin: 0; container-type: inline-size; min-width: 0; }
.rnr-ch > * { position: relative; z-index: 1; }
.rnr-ch > .rnr-ch-glow { position: absolute; z-index: 0; top: 80px; }

/* THE TWO PASSES. Over the lanes, aligned to them, so each arrow runs along the lanes it describes. */
.rnr-ch-dirs {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s5);
  margin: 0 0 var(--s4) calc(140px + 40px);
}
.rnr-ch-dir { display: flex; align-items: center; gap: var(--s3); margin: 0; font-size: 14px; line-height: 1.4; color: var(--ink-2); }
/* IN A REVERSED ROW flex-start IS THE RIGHT EDGE, so the verify label packs against the anchors it
   starts from. It read flex-end and packed 133px short of them at 1440. */
.rnr-ch-dir[data-dir="verify"] { justify-content: flex-start; flex-direction: row-reverse; }
.rnr-ch-arrow { display: inline-flex; flex: 0 0 auto; color: var(--teal-dark); }
.rnr-ch-arrow svg { width: 40px; height: 12px; display: block; overflow: visible; }
.rnr-ch-arrow path:first-child { stroke: currentColor; stroke-width: 2; fill: none; }
.rnr-ch-arrow path:last-child { fill: currentColor; }
.rnr-ch-dir[data-dir="verify"] .rnr-ch-arrow svg { transform: scaleX(-1); }

.rnr-ch-grid { display: grid; grid-template-columns: 140px 40px minmax(0, 1fr); align-items: stretch; }

.rnr-ch-agent { display: flex; flex-direction: column; justify-content: center; align-items: center; text-align: center; padding-block: var(--s3); }
.rnr-ch-agent .rw-ped { width: 100%; }

.rnr-ch-fork { display: block; width: 40px; height: 100%; overflow: visible; }
.rnr-ch-fork path { fill: none; stroke-width: 2; opacity: 0.85; }

/* THE LANES SHARE ONE HEIGHT, so the fork's curves, drawn at the centre of each equal share, land on
   the lanes' wires. The gap is padding inside the lane rather than a grid gap for the same reason. */
.rnr-ch-lanes { list-style: none; margin: 0; padding: 0; display: grid; grid-auto-rows: 1fr; min-width: 0; }
.rnr-ch-lane {
  position: relative; display: grid;
  grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.1fr);
  column-gap: var(--s3);
  align-items: center;
  padding-block: var(--s3);
  min-width: 0;
}
/* THE WIRE runs through the centre of every document in the lane, in the lane's hue. */
.rnr-ch-lane::before {
  content: ""; position: absolute; left: 0; right: 0; top: 50%; height: 2px;
  background: var(--hue); opacity: 0.8; box-shadow: 0 0 6px var(--hue);
}
/* THE MARKS LANE IS QUIETER, NOT REFUSED. The platform walks it and reads marks through it; it does
   not admit through it. A dashed wire says "walked, not admitted through" without a state colour. */
.rnr-ch-lane[data-purpose="marks"]::before {
  background: repeating-linear-gradient(90deg, var(--hue) 0 8px, transparent 8px 14px);
  box-shadow: none; opacity: 0.7;
}

.rnr-ch-doc, .rnr-ch-node { position: relative; z-index: 1; min-width: 0; }
.rnr-ch-doc {
  padding: var(--s3); border-radius: 10px;
  border: 1px solid var(--hairline); border-left: 3px solid var(--hue);
  background: var(--paper);
}
.rnr-ch-node {
  padding: var(--s3) var(--s3) var(--s3); border-radius: 12px;
  border: 1px solid var(--hairline); border-top: 2px solid var(--hue);
  background: var(--paper-alt);
  box-shadow: 0 0 24px color-mix(in srgb, var(--hue) 18%, transparent);
}
.rnr-ch-i { display: inline-flex; color: var(--hue); filter: drop-shadow(0 0 8px var(--hue)); }
.rnr-ch-i svg { width: 26px; height: 26px; }
.rnr-ch-t { margin: 0; font-size: 15px; line-height: 1.35; font-weight: 700; color: var(--ink); overflow-wrap: anywhere; }
.rnr-ch-s { margin: 2px 0 0; font-size: 14px; line-height: 1.4; color: var(--ink-2); }
.rnr-ch-a { color: var(--ink); text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--hue, var(--teal-dark)) 70%, transparent); text-underline-offset: 3px; text-decoration-thickness: 1px; }
.rnr-ch-a:hover { text-decoration-color: var(--brand-strong); }
.rnr-ch-agent .rnr-ch-a { text-decoration-color: color-mix(in srgb, var(--d-blue) 70%, transparent); }

.rnr-ch-types { list-style: none; margin: var(--s2) 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.rnr-ch-type {
  font-family: var(--mono); font-size: 14px; line-height: 1.3; color: var(--ink);
  padding: 2px 8px; border-radius: 6px;
  border: 1px solid color-mix(in srgb, var(--hue) 55%, transparent);
  background: var(--paper-alt);
}
/* A TAG, NOT A PILL. A pill that wraps to two lines reads as a rounded box with a broken label. */
.rnr-ch-pin {
  display: inline-block; margin: var(--s2) 0 0; padding: 2px 8px; border-radius: 6px;
  font-size: 14px; line-height: 1.4; font-weight: 600; color: var(--ink);
  border: 1px solid var(--hue);
}
.rnr-ch-pin[data-purpose="marks"] { border-style: dashed; font-weight: 400; color: var(--ink-2); }

/* THE CLIENT. The hub, set left, with the folded values as chips beside their parameter. */
.rnr-ch .rnr-ch-result {
  display: grid; grid-template-columns: auto minmax(0, 14rem) minmax(0, 1fr); align-items: center;
  gap: var(--s3) var(--s5); text-align: left;
  margin: var(--s5) 0 0; padding: var(--s4) var(--s5);
}
.rnr-ch-result-i { display: inline-flex; color: var(--teal-dark); filter: drop-shadow(0 0 10px var(--teal-dark)); }
.rnr-ch-result-i svg { width: 34px; height: 34px; }
.rnr-ch-result-w p { margin: 0; }
.rnr-ch-result-t { font-size: 18px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.rnr-ch-result-l { font-size: 14px; line-height: 1.45; color: var(--ink-2); }
.rnr-ch-rows { margin: 0; display: grid; gap: var(--s2); min-width: 0; }
.rnr-ch-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px var(--s3); min-width: 0; }
.rnr-ch-row dt { margin: 0; }
.rnr-ch-row dt code { font-family: var(--mono); font-size: 14px; color: var(--ink-2); background: none; padding: 0; }
.rnr-ch-row dd { margin: 0; display: flex; flex-wrap: wrap; gap: 6px; min-width: 0; }
.rnr-ch-v { font-family: var(--mono); font-size: 14px; line-height: 1.3; color: var(--ink); padding: 2px 8px; border-radius: 6px; border: 1px solid var(--hairline); background: var(--paper); }

/* THE NARROW STATE: EACH LANE RUNS DOWN. The agent sits over the lanes, each lane is one rail in its
   hue with its four documents under one another, and the two arrows turn to point down and up. */
@container (max-width: 900px) {
  .rnr-ch-dirs { margin-left: 0; grid-template-columns: 1fr; gap: var(--s2); }
  .rnr-ch-dir[data-dir="verify"] { justify-content: flex-start; flex-direction: row; }
  .rnr-ch-dir .rnr-ch-arrow svg { width: 28px; transform: rotate(90deg); }
  .rnr-ch-dir[data-dir="verify"] .rnr-ch-arrow svg { transform: rotate(-90deg); }
  .rnr-ch-grid { grid-template-columns: minmax(0, 1fr); }
  .rnr-ch-fork { display: none; }
  .rnr-ch-agent { flex-direction: row; justify-content: flex-start; align-items: center; gap: var(--s3); text-align: left; padding: 0 0 var(--s3); }
  .rnr-ch-agent-w { min-width: 0; }
  .rnr-ch-agent .rw-ped { width: 84px; flex: 0 0 auto; }
  .rnr-ch-lanes { grid-auto-rows: auto; gap: var(--s5); }
  .rnr-ch-lane { grid-template-columns: minmax(0, 1fr); row-gap: var(--s3); padding: 0 0 0 28px; align-content: start; }
  .rnr-ch-lane > * { max-width: 100%; }
  .rnr-ch-lane::before { left: 10px; right: auto; top: 0; bottom: 0; width: 2px; height: auto; }
  .rnr-ch-lane[data-purpose="marks"]::before { background: repeating-linear-gradient(180deg, var(--hue) 0 8px, transparent 8px 14px); }
  .rnr-ch .rnr-ch-result { grid-template-columns: auto minmax(0, 1fr); padding: var(--s4); }
  .rnr-ch-rows { grid-column: 1 / -1; }
}

/* BETWEEN THE TWO, THE LANES STAND SIDE BY SIDE, each still running down, so the two authorities
   are compared across the row the way the wide figure compares them down the column. */
/* THE LANES SHARE THEIR ROWS (subgrid), so the authority in one lane sits level with the authority
   in the other however many chips the statement above it carries. Measured before: 60px apart at
   800. */
@container (min-width: 560px) and (max-width: 900px) {
  .rnr-ch-lanes { grid-template-columns: repeat(var(--lanes), minmax(0, 1fr)); grid-template-rows: repeat(4, auto); column-gap: var(--s4); row-gap: 0; }
  .rnr-ch-lane { grid-row: span 4; grid-template-rows: subgrid; }
}

/* ================================================================
   rnr-ceilings: three rings, one inside the other, with the tasks each decides.
   ================================================================ */
.rnr-cl { position: relative; margin: 0; container-type: inline-size; min-width: 0; }
.rnr-cl > .rnr-cl-glow { position: absolute; z-index: 0; top: 60px; }
.rnr-cl-rings { position: relative; z-index: 1; }
.rnr-cl-ring {
  position: relative; margin-top: var(--s4);
  padding: var(--s4) var(--s5) var(--s5);
  border-radius: 18px;
  border: 1.5px solid color-mix(in srgb, var(--hue) 60%, transparent);
  background: linear-gradient(180deg, var(--paper-alt) 0%, var(--paper) 100%);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--hue) 40%, transparent), 0 0 32px color-mix(in srgb, var(--hue) 10%, transparent);
}
.rnr-cl-rings > .rnr-cl-ring { margin-top: 0; }
/* A RING THAT COPIES THE ONE OUTSIDE IT IS DASHED AND CARRIES NO GLOW. It is still drawn, because
   the platform still tests against it and finds nothing more to narrow. */
.rnr-cl-ring[data-copy="true"] { border-style: dashed; box-shadow: none; }

.rnr-cl-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px var(--s3); }
.rnr-cl-head p { margin: 0; }
.rnr-cl-n {
  display: inline-flex; align-items: center; justify-content: center; align-self: center;
  width: 28px; height: 28px; border-radius: 50%;
  border: 2px solid var(--hue); box-shadow: 0 0 8px var(--hue);
  font-size: 14px; font-weight: 700; color: var(--ink); background: var(--paper);
}
.rnr-cl-t { font-size: 18px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.rnr-cl-who { font-size: 14px; line-height: 1.4; color: var(--ink-2); }

.rnr-cl-types { list-style: none; margin: var(--s3) 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.rnr-cl-type {
  font-family: var(--mono); font-size: 14px; line-height: 1.3; color: var(--ink);
  padding: 2px 8px; border-radius: 6px;
  border: 1px solid color-mix(in srgb, var(--hue) 55%, transparent);
  background: var(--paper);
}
.rnr-cl-tasks { list-style: none; margin: var(--s4) 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--s3); }
.rnr-cl-task {
  display: flex; flex-direction: column; gap: 2px;
  flex: 1 1 14rem; max-width: 22rem; min-width: 0;
  padding: var(--s2) var(--s3); border-radius: 10px;
  border: 1px solid var(--hairline); border-left: 3px solid var(--hue);
  background: var(--paper);
}
.rnr-cl-task-l { font-size: 15px; line-height: 1.35; font-weight: 600; color: var(--ink); }
.rnr-cl-amt { font-weight: 700; white-space: nowrap; }
.rnr-cl-task-t { font-family: var(--mono); font-size: 14px; line-height: 1.3; color: var(--ink-2); background: none; padding: 0; }
.rnr-cl-task-w { font-size: 14px; line-height: 1.4; color: var(--ink-2); }

@container (max-width: 560px) {
  .rnr-cl-ring { padding: var(--s3) var(--s3) var(--s4); border-radius: 14px; }
  .rnr-cl-task { flex-basis: 100%; max-width: none; }
}

/* ================================================================
   The claim page hero: packages/ui/partials/rnh-hero.ejs and the copy over it.
   The layout is the standard page's (/use-cases/your-own-assistant): the headline on the left, the
   lead and the actions on the right, and the instrument under them at the full measure, where it
   is the largest thing on the first screen. The rules are this page's own copies, under rnh-, so
   a change to that page cannot move this one.
   ================================================================ */
.wrap.rnh-page { --page-max: 1376px; }
.wrap.rnh-page > .rnh-top { position: relative; padding-block: 2.5rem 0; display: grid; gap: var(--s3); }
.rnh-top-copy > * { margin: 0; }
.rnh-top-copy .sc-eyebrow { letter-spacing: 0.22em; color: var(--slate); }
.rnh-top-copy .sc-headline { margin-top: var(--s4); line-height: 1.02; letter-spacing: -0.035em; max-width: 22ch; }
.rnh-top-copy .sc-headline .accent { display: block; }
.rnh-top-copy .sc-lead { margin-top: 1.25rem; max-width: 34rem; font-size: 17px; line-height: 1.55; color: var(--ink-lead); }
.rnh-top-copy .sc-actions { margin-top: var(--s5); display: flex; flex-wrap: wrap; gap: var(--s4); }
@media (min-width: 1100px) {
  .rnh-top-copy { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); column-gap: 4rem; grid-template-areas: "eyebrow eyebrow" "head lead" "head actions"; align-items: start; }
  .rnh-top-copy .sc-eyebrow { grid-area: eyebrow; }
  .rnh-top-copy .sc-headline { grid-area: head; }
  .rnh-top-copy .sc-lead { grid-area: lead; }
  .rnh-top-copy .sc-actions { grid-area: actions; }
}

/* THE INSTRUMENT. Five columns and four rows: the authority over the platform, the resolve wires
   between them, the agent, the call and the token, the platform and the resource along the main
   row, and under it the wire along which the agent presents the token. Every wire is its own cell,
   so a wire can never point past the object it meets. The markup runs in step order and the grid
   places it. */
.rnh { position: relative; margin: 0; container-type: inline-size; min-width: 0; }
.rnh > .rnh-glow { position: absolute; z-index: 0; top: 180px; width: 1100px; height: 460px; }
.rnh-stage {
  position: relative; z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 118px minmax(0, 2.1fr) 118px minmax(0, 1fr);
  grid-template-areas:
    ".       .       auth    .       .      "
    ".       .       resolve .       .      "
    "agent   link    plat    .       res    "
    "present present present present present";
  align-items: end;
}
.rnh-auth { grid-area: auth; justify-self: center; width: min(100%, 24rem); }
.rnh-auth .rnh-card { padding: var(--s3) var(--s4); }
.rnh-resolve { grid-area: resolve; position: relative; height: 56px; }
.rnh-agent { grid-area: agent; }
.rnh-first, .rnh-back { grid-area: link; align-self: center; }
.rnh-first { margin-bottom: 110px; }
.rnh-back { margin-top: 110px; }
.rnh-plat { grid-area: plat; }
.rnh-res { grid-area: res; }
.rnh-present { grid-area: present; }

.rnh-party { display: flex; flex-direction: column; align-items: stretch; min-width: 0; }
.rnh-party .rw-ped { margin-bottom: -6px; }
.rnh .rnh-card { padding: var(--s4); text-align: center; }
.rnh-kind { margin: 0; font-size: 14px; line-height: 1.3; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-2); }
.rnh-name { margin: 4px 0 0; font-size: 18px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.rnh-line { margin: 4px 0 0; font-size: 15px; line-height: 1.45; color: var(--ink-2); }

.rnh-n {
  display: inline-flex; flex: 0 0 auto; align-items: center; justify-content: center;
  width: 24px; height: 24px; border-radius: 50%;
  border: 1.5px solid var(--hue, var(--teal-dark)); background: var(--paper);
  box-shadow: 0 0 8px var(--hue, var(--teal-dark));
  font-size: 14px; font-weight: 700; color: var(--ink);
}
.rnh-wl { display: flex; align-items: center; gap: var(--s2); margin: 0; font-size: 14px; line-height: 1.35; color: var(--ink-2); }

/* THE CALL AND THE TOKEN, one channel between the agent and the platform: the call runs right in the
   agent's hue, the token runs back left in the platform's. */
.rnh-hw { display: flex; flex-direction: column; align-items: center; gap: 6px; padding-inline: 6px; color: var(--hue); }
.rnh-wire { display: block; width: 100%; height: 12px; overflow: visible; filter: drop-shadow(0 0 5px var(--hue)); }
.rnh-wire path { stroke: currentColor; stroke-width: 2; fill: none; }
.rnh-wire .rnh-head { fill: currentColor; stroke: none; }
.rnh-back .rnh-wire { transform: scaleX(-1); }
.rnh-hw .rnh-wl { flex-direction: column; text-align: center; gap: 4px; }

/* THE RESOLVE: up from the platform in its hue, dashed, and the statements down in the authority's.
   The tips are CSS triangles, because the wires' svg stretches with the cell and a drawn triangle
   would stretch with it. */
.rnh-vwires { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.rnh-vwires path { fill: none; stroke-width: 2; }
.rnh-up { stroke: var(--d-magenta); stroke-dasharray: 6 6; filter: drop-shadow(0 0 4px var(--d-magenta)); }
.rnh-down { stroke: var(--d-violet); filter: drop-shadow(0 0 4px var(--d-violet)); }
.rnh-tip { position: absolute; width: 0; height: 0; border-left: 6px solid transparent; border-right: 6px solid transparent; }
.rnh-tip-up { left: 38%; top: -2px; transform: translateX(-50%); border-bottom: 9px solid var(--d-magenta); }
.rnh-tip-down { left: 62%; bottom: -2px; transform: translateX(-50%); border-top: 9px solid var(--d-violet); }
.rnh-wl-up { position: absolute; right: 64%; top: 50%; transform: translateY(-50%); --hue: var(--d-magenta); white-space: nowrap; }
.rnh-wl-down { position: absolute; left: 64%; top: 50%; transform: translateY(-50%); white-space: nowrap; }
@media (prefers-reduced-motion: no-preference) {
  .rnh-up { animation: rnh-flow 1.6s linear infinite; }
}
@keyframes rnh-flow { to { stroke-dashoffset: -24; } }

/* THE PRESENTATION. It shares the stage's columns (subgrid), so the line drops from the centre of the
   agent's column, runs under the platform and rises into the centre of the resource's column, with
   the tip pointing up into the resource. */
.rnh-present { display: grid; grid-template-columns: subgrid; grid-template-rows: 44px; position: relative; }
.rnh-p-l, .rnh-p-m, .rnh-p-r { position: relative; grid-row: 1; }
.rnh-p-l { grid-column: 1; }
.rnh-p-m { grid-column: 2 / span 3; border-bottom: 2px solid var(--hue); height: 50%; align-self: start; }
.rnh-p-r { grid-column: 5; }
.rnh-p-l::before, .rnh-p-r::before { content: ""; position: absolute; top: 0; height: 50%; border-bottom: 2px solid var(--hue); }
.rnh-p-l::before { left: 50%; right: 0; border-left: 2px solid var(--hue); border-bottom-left-radius: 12px; }
.rnh-p-r::before { left: 0; right: 50%; border-right: 2px solid var(--hue); border-bottom-right-radius: 12px; }
.rnh-p-r::after { content: ""; position: absolute; left: 50%; top: -6px; transform: translateX(-50%); border-left: 6px solid transparent; border-right: 6px solid transparent; border-bottom: 9px solid var(--hue); }
.rnh-present > span { filter: drop-shadow(0 0 4px var(--hue)); }
/* THE WORDS SIT ON THE LINE, on a ground of their own, so the wire takes no extra row. */
.rnh-p-w { grid-row: 1; grid-column: 1 / -1; justify-self: center; align-self: end; transform: translateY(50%); padding: 2px var(--s3); background: var(--paper); border-radius: 999px; }

/* THE PLATFORM: a lit window, larger than every party round it. */
.rnh-plat {
  position: relative; min-width: 0;
  border-radius: 16px;
  border: 1px solid color-mix(in srgb, var(--hue) 45%, transparent);
  background: linear-gradient(180deg, var(--paper-alt) 0%, var(--paper) 100%);
  box-shadow: 0 0 48px color-mix(in srgb, var(--hue) 16%, transparent), inset 0 1px 0 color-mix(in srgb, var(--hue) 40%, transparent);
  padding: 0 var(--s5) var(--s4);
}
.rnh-plat-bar { display: flex; gap: 6px; padding: 10px 0 0; }
.rnh-plat-bar span { width: 9px; height: 9px; border-radius: 50%; background: var(--hairline); }
.rnh-plat-head { display: flex; align-items: center; gap: var(--s3); margin-top: var(--s2); }
.rnh-plat-head .rnh-name { margin: 0; font-size: 20px; }
.rnh-treat { margin-left: auto; }
.rnh-plat-i { display: inline-flex; color: var(--hue); filter: drop-shadow(0 0 8px var(--hue)); }
.rnh-plat-i svg { width: 28px; height: 28px; }
.rnh-sub { display: flex; align-items: center; gap: var(--s2); margin: 0; font-size: 14px; line-height: 1.35; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-2); }
.rnh-body { display: grid; grid-template-columns: minmax(0, 0.72fr) minmax(0, 1.28fr); gap: var(--s3); margin-top: var(--s4); }
.rnh-records { margin-top: 0; padding: var(--s3); border-radius: 10px; border: 1px solid var(--hairline); background: var(--paper); }
.rnh-slots { list-style: none; margin: var(--s2) 0 0; padding: 0; display: grid; gap: 6px; }
.rnh-slots li { height: 10px; border-radius: 4px; border: 1px dashed color-mix(in srgb, var(--ink-2) 45%, transparent); }
.rnh-holds { display: flex; align-items: center; gap: var(--s2); margin: var(--s3) 0 0; font-size: 15px; line-height: 1.4; font-weight: 600; color: var(--ink); }
.rnh-holds svg { width: 16px; height: 16px; flex: 0 0 auto; stroke: var(--ink-2); stroke-width: 2; fill: none; stroke-linecap: round; }
.rnh-built { --hue: var(--teal-dark); margin-top: 0; padding: var(--s3); border-radius: 10px; border: 1px solid color-mix(in srgb, var(--teal-dark) 50%, transparent); background: var(--paper); box-shadow: 0 0 24px color-mix(in srgb, var(--teal-dark) 14%, transparent); }
.rnh-client { margin: var(--s3) 0 0; display: grid; gap: var(--s2); }
.rnh-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px var(--s2); min-width: 0; }
.rnh-row dt { margin: 0; flex: 0 0 100%; }
.rnh-row dt code { font-family: var(--mono); font-size: 14px; color: var(--ink-2); background: none; padding: 0; }
.rnh-row dd { margin: 0; display: flex; flex-wrap: wrap; gap: 6px; min-width: 0; }
.rnh-v { font-family: var(--mono); font-size: 14px; line-height: 1.3; color: var(--ink); padding: 2px 8px; border-radius: 6px; border: 1px solid color-mix(in srgb, var(--teal-dark) 45%, transparent); background: var(--paper-alt); }
.rnh-anchor { display: flex; align-items: center; gap: var(--s2); margin: var(--s3) 0 0; font-size: 14px; line-height: 1.4; color: var(--ink-2); }
.rnh-anchor-i { display: inline-flex; color: var(--hue); }
.rnh-anchor-i svg { width: 18px; height: 18px; }

/* THE NARROW STATE, UNDER 1150PX OF FIGURE: the authority over the platform as on the wide figure,
   and the agent and the resource side by side under it. The call and the token run up and down
   between the agent's column and the platform, and the presentation runs under both cards. At 1024
   five columns left the agent and the resource too narrow to hold their names, which is why this
   state starts at 1150 rather than at 900. */
@container (max-width: 1150px) {
  .rnh-stage {
    max-width: 44rem; margin-inline: auto;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-areas: "auth auth" "resolve resolve" "plat plat" "link ." "agent res" "present present";
    column-gap: var(--s3);
    align-items: end;
  }
  .rnh-body { grid-template-columns: minmax(0, 1fr); }
  /* BOTH WIRES STAND IN THE AGENT'S COLUMN, each half of it wide, because both join the agent to
     the platform: the call runs up, the token runs down. */
  .rnh-first, .rnh-back { width: 50%; margin: 0; padding-block: var(--s2) var(--s3); align-self: stretch; justify-content: flex-start; }
  .rnh-first { justify-self: start; }
  .rnh-back { justify-self: end; }
  .rnh-hw .rnh-wire { width: 56px; flex: 0 0 auto; margin-block: 22px; }
  .rnh-first .rnh-wire { transform: rotate(-90deg); }
  .rnh-back .rnh-wire { transform: rotate(90deg); }
  .rnh-hw .rnh-wl { flex-direction: column; text-align: center; align-items: center; }
  .rnh-p-l { grid-column: 1; }
  .rnh-p-l::before { right: calc(-1 * var(--s3)); }
  .rnh-p-m { display: none; }
  .rnh-present { grid-template-rows: 44px auto; }
  .rnh-p-w { grid-row: 2; transform: none; margin-top: var(--s2); }
  .rnh-p-r { grid-column: 2; }
  .rnh .rnh-card { padding: var(--s3); }
  .rnh-name { font-size: 16px; }
  .rnh-wl-up { right: 66%; white-space: normal; max-width: 34%; }
  .rnh-wl-down { left: 66%; white-space: normal; max-width: 34%; }
}

/* ---- src/parts/rw.css ---- */
/* THE TARGET BUILD'S TREATMENTS, ported rather than approximated.
 *
 * THE BRAND IS NAMED --teal-dark AND --teal-deep HERE, NOT --teal, and that is a rule rather than a
 * preference. packages/ui/tests/stylesheet.test.ts reserves `var(--teal)` for a selector carrying
 * data-treat="product": brand teal fills a Raidiam product marker and nothing else. darkCss maps
 * --teal, --teal-deep and --teal-dark to the same value, so a stroke or a control takes one of the
 * latter two and the one colour rule keeps its meaning.
 *
 * Source: /Users/ralphbragg/Downloads/raidiam-webpage-build.zip, `components/diagram-section.tsx`,
 * read and run rather than taken from a screenshot. CLAUDE.md names the eight treatments that make
 * that design look like itself; this file is where the six drawn ones live, so a partial asks for a
 * pedestal or a hub rather than inventing one.
 *
 * WHY THEY ARE HERE AND NOT IN EACH PAGE'S OWN PART FILE. Three pages had already grown their own
 * glow, their own plinth and their own connector, each slightly different, and the differences were
 * accidents rather than decisions. One place means the next page gets the treatment right by asking
 * for it, and means a correction lands everywhere at once.
 *
 * THE HUE IS PASSED IN, ALWAYS, as `--hue` on the element. The four environment hues mean nothing on
 * their own, which is exactly what lets them carry identity here: the state vocabulary is spoken
 * for, and green means Observed on every surface of this site.
 */

/* 1. THE PEDESTAL. An icon standing on light: a wide soft pool of the hue, a tighter brighter pool
      over it, a hard near white contact ellipse, and the icon lit in the same hue. Four layers, no
      image. This is the single treatment that most makes the target look like the target. */
.rw-ped { position: relative; display: flex; height: 92px; align-items: flex-end; justify-content: center; }
.rw-ped::before,
.rw-ped::after {
  content: ""; position: absolute; left: 50%; transform: translateX(-50%);
  border-radius: 50%; pointer-events: none;
}
.rw-ped::before { bottom: 4px; width: 112px; height: 64px; background: var(--hue, var(--teal-dark)); opacity: 0.45; filter: blur(32px); }
.rw-ped::after { bottom: 10px; width: 104px; height: 14px; background: var(--hue, var(--teal-dark)); opacity: 0.6; filter: blur(3px); }
.rw-ped-contact {
  position: absolute; left: 50%; bottom: 13px; transform: translateX(-50%);
  width: 86px; height: 7px; border-radius: 50%;
  background: var(--ink); opacity: 0.85; pointer-events: none;
}
.rw-ped-i { position: relative; margin-bottom: 16px; color: var(--hue, var(--teal-dark)); filter: drop-shadow(0 0 10px var(--hue, var(--teal-dark))); }
.rw-ped-i svg { width: 44px; height: 44px; display: block; }
/* The label under a pedestal, when the figure has no line of its own to carry it. */
.rw-ped-l { margin: var(--s2) 0 0; text-align: center; font-size: var(--t-label); font-weight: 600; color: var(--ink); }

/* TWO SMALLER STEPS, because the pedestal now stands inside a card as well as under a hero figure.
   Every layer scales together: a pool that keeps its 112px width under a 30px glyph reads as a
   smudge rather than as light on a surface. */
.rw-ped-sm { height: 68px; }
.rw-ped-sm::before { bottom: 3px; width: 84px; height: 48px; filter: blur(24px); }
.rw-ped-sm::after { bottom: 8px; width: 78px; height: 11px; }
.rw-ped-sm .rw-ped-contact { bottom: 10px; width: 64px; height: 6px; }
.rw-ped-sm .rw-ped-i { margin-bottom: 13px; }
.rw-ped-sm .rw-ped-i svg { width: 32px; height: 32px; }

/* 2. THE ENVIRONMENT CARD. A vertical gradient panel lit from above by its own hue: the inset top
      highlight and the tinted top border are what stop it reading as a flat rectangle. */
.rw-card {
  position: relative; border-radius: 10px;
  border: 1px solid color-mix(in srgb, var(--ink) 10%, transparent);
  border-top-color: color-mix(in srgb, var(--hue, var(--teal-dark)) 40%, transparent);
  background: linear-gradient(180deg, color-mix(in srgb, var(--paper-alt) 90%, transparent) 0%, color-mix(in srgb, var(--paper) 90%, transparent) 100%);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--hue, var(--teal-dark)) 33%, transparent);
  padding: var(--s4) var(--s4) var(--s5);
}

/* 3. THE HUB. The object every connector leaves. A radial gradient from the top, a brand edge, an
      outer glow and an inset highlight. */
.rw-hub {
  position: relative; border-radius: 14px;
  border: 1px solid color-mix(in srgb, var(--teal-dark) 35%, transparent);
  background: radial-gradient(120% 80% at 50% 0%, color-mix(in srgb, var(--teal-mid) 40%, transparent) 0%, color-mix(in srgb, var(--white) 92%, transparent) 60%);
  box-shadow: 0 0 40px color-mix(in srgb, var(--teal-dark) 12%, transparent),
              inset 0 1px 0 color-mix(in srgb, var(--brand-strong) 35%, transparent);
  padding: var(--s5) var(--s6) var(--s5);
  text-align: center;
}

/* 4. THE CONNECTORS. One svg, beziers from the hub to each card, arrowheads as filled triangles, the
      whole group glowing. The target draws every connector lit rather than only the selected one:
      the figure is about one release reaching all four, so all four are lit. */
.rw-wires { display: block; width: 100%; filter: drop-shadow(0 0 5px color-mix(in srgb, var(--teal-dark) 70%, transparent)); }
.rw-wire { stroke: var(--teal-dark); stroke-width: 2; stroke-linecap: round; fill: none; opacity: 0.85; }
.rw-wire-head { fill: var(--brand-strong); }

/* 5. THE AMBIENT GLOW. A very large, very soft pool behind a section. It is what stops the ground
      reading as flat, and it is the cheapest thing on this list. */
.rw-glow {
  position: absolute; left: 50%; top: 96px; transform: translateX(-50%);
  width: 820px; height: 420px; max-width: 90%;
  border-radius: 50%; pointer-events: none;
  /* A FLAT TOKEN AT AN OPACITY, NOT A COLOUR-MIX. contrast.mjs gates a pair of tokens by name and
     can read nothing through a mix, so the stylesheet test refuses one in a background. This pool
     carries no text and is blurred to 120px, so the opacity does the work the mix would have. */
  background: var(--teal-mid); opacity: 0.3;
  filter: blur(120px);
}

/* 6. THE SIDE PANEL. A vertical gradient, a brand edge at low alpha, an uppercase tracked title. */
.rw-panel {
  border-radius: 12px;
  border: 1px solid color-mix(in srgb, var(--teal-dark) 20%, transparent);
  background: linear-gradient(180deg, color-mix(in srgb, var(--paper-alt) 75%, transparent) 0%, color-mix(in srgb, var(--paper) 75%, transparent) 100%);
  padding: var(--s5);
}
.rw-panel-h {
  margin: 0 0 var(--s4); font-size: var(--t-label); font-weight: 600;
  letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink-2);
}

/* 7. THE RINGED ICON, from the benefits row: a circle of brand at low alpha with the glyph inside. */
.rw-ring {
  display: inline-flex; align-items: center; justify-content: center;
  width: 52px; height: 52px; border-radius: 50%; flex: 0 0 auto;
  border: 1px solid color-mix(in srgb, var(--teal-dark) 40%, transparent);
  color: var(--teal-dark);
}
.rw-ring svg { width: 24px; height: 24px; }

/* 8. THE PILLS. The target's two controls, and the filled one carries dark text on purpose because
      the brand is bright. site.css states `.btn` for the whole site; these are the target's exact
      measurements for the places a page wants them literally. */
.rw-btn {
  display: inline-flex; align-items: center; gap: var(--s2);
  border-radius: var(--pill); padding: 12px var(--s5);
  font-size: 15px; font-weight: 600; text-decoration: none;
  background: var(--teal-deep); color: var(--on-brand);
  border: 1px solid var(--teal-deep);
  transition: background 160ms ease;
}
.rw-btn:hover { background: var(--brand-strong); }
.rw-btn-quiet {
  background: transparent; color: var(--brand-strong);
  border-color: color-mix(in srgb, var(--teal-dark) 60%, transparent);
}
/* The hover ground is a flat token because the label sits on it and has to be gated. */
.rw-btn-quiet:hover { background: var(--wash-teal); }

@media (prefers-reduced-motion: reduce) {
  .rw-btn { transition: none; }
}

/* ---- src/parts/scenario.css ---- */
/* The scenario page bands, from the third reference set. Partials:
   packages/ui/partials/uc-hero.ejs, uc-cards.ejs, uc-example.ejs, uc-closing.ejs, uc-glyph.ejs,
   and the two figures /use-cases/find-and-trust draws, uc-approve-govern-trust.ejs and
   uc-two-decisions.ejs.

   The class prefix is sc, not uc. packages/ui/src/parts/use-cases.css already owns .uc-card,
   .uc-cards, .uc-icon, .uc-head and .uc-lead for the scenario index at /use-cases, and two parts
   are concatenated into one sheet, so a second .uc-card here would silently win or lose by file
   order. The PARTIAL names keep the uc prefix, which is what the brief asked for; the CSS classes
   do not.

   The comp's filled button measures a true blue near #177EFE. The dark system has one accent,
   #15D4D8, on purpose, and a second accent is a token decision across nineteen routes. So the
   actions here are the site's .btn and .btn-quiet and the deviation is recorded rather than taken.

   The accent is written --teal-dark throughout. On dark, --teal, --teal-deep, --teal-dark and
   --cyan all resolve to the same accent, and packages/ui/tests/stylesheet.test.ts reserves
   var(--teal) for a product marker. */

/* ---- The eyebrow, shared by the hero and the worked example panel ---- */
.sc-eyebrow {
  display: flex; align-items: baseline; gap: var(--s2);
  font-size: var(--t-label); line-height: var(--t-label-line);
  text-transform: uppercase; letter-spacing: 0.12em;
  color: var(--teal-dark); margin: 0;
}
/* ONE LINE, ONE SIZE, ONE COLOUR: the target sets USE CASE 03 at 13px, uppercase, tracked, all in
   the brand. Ours printed the number at 20px in white beside a 14px brand word, which reads as two
   things that happen to be adjacent rather than as one label. */
.sc-eyebrow-word { font-weight: 600; }
.sc-eyebrow-n { font-size: inherit; font-weight: 600; letter-spacing: inherit; color: inherit; }

/* The lifecycle stages this scenario shows, under the eyebrow. It is the excerpt form of the mini
   rail: a group with no links. It sits here because the strip between the masthead and the page is
   now the use cases menu, and the stages are a property of the scenario rather than a way to move
   between scenarios. Negative margins pull it against the eyebrow, because the hero body is a grid
   with a gap and this line belongs to the eyebrow rather than to the headline. */
/* THE STAGES ARE A SUMMARY AT THE FOOT, NOT A STRIP IN THE HERO. They sat under the use case
   number with the use cases menu directly above them, and Ralph read that as two menus on one page,
   twice. Here they close the scenario. */
.sc-stages { opacity: 0.85; }
/* .sc-stages-foot is gone with the strip it framed. The six lifecycle verbs were drawn on every
   scenario page, first under the use case number in the hero and then above the closing band. Ralph
   read them as a menu twice in the hero and as clutter once at the foot, which is three reports of
   the same thing: a row of six words with rules under them, on a page whose argument is elsewhere.
   The lifecycle is still drawn where it is the subject, on the home page and on a film card. */
/* Level three on a scenario page. */
.sc-deep.drawer { margin-block: var(--s6); }
.sc-deep.drawer > summary { font-size: var(--t-small); }
.sc-deep.drawer > .body { padding-top: var(--s5); display: grid; gap: var(--s6); }
.sc-stages .rail-mini { flex-wrap: wrap; }

/* ---- Band 2, the hero ---- */
.sc-hero { display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); gap: var(--s7); align-items: start; }
.sc-hero-body { display: grid; gap: var(--s4); }
.sc-hero-body > * { margin: 0; }
.sc-headline { margin-top: var(--s2); }
/* Spacing comes from `flow` on the wrapper, like every other rendered section on this page.
   This used to carry its own `p + p` rule, which is a second mechanism doing one job and the one
   the figure band then failed to copy. */
.sc-lead { color: var(--ink-2); }
.sc-actions { display: flex; flex-wrap: wrap; gap: var(--s3); margin-top: var(--s2); }
.sc-hero-aside { color: var(--ink-2); max-width: var(--measure-body); }
.sc-hero-figure { display: grid; }
/* 1040, the same width .cols-3 in the base sheet turns at. Measured at 1024 with the breakpoint at
   900: the headline broke to four lines, the two actions stacked, and the figure column was wider
   than the words beside it. */
@media (max-width: 1040px) {
  .sc-hero { grid-template-columns: minmax(0, 1fr); gap: var(--s6); }
  .sc-hero-figure { max-width: 560px; }
}

/* ---- The hero figure on find and trust: the three step chain ---- */
.sc-chain { padding: var(--s5); background: var(--white); display: grid; gap: var(--s4); }
.sc-chain-cap { color: var(--ink-2); text-transform: none; letter-spacing: normal; }
.sc-chain-steps { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s3); }
.sc-chain-step { display: grid; gap: var(--s2); justify-items: stretch; }
/* The connector between two steps. A short vertical stroke rather than an arrow head, because the
   step order is already carried by the ordered list and by the verb above each node. It sits under
   the centre of the glyph in the node above it: the node's left padding plus half the glyph. */
.sc-chain-flow { width: 2px; height: 20px; margin-left: calc(var(--s4) + 18px); background: var(--rule); border-radius: 1px; }
.sc-chain-verb {
  font-size: var(--t-label); line-height: var(--t-label-line); font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.1em; color: var(--ink-2);
}
.sc-chain-node {
  display: flex; align-items: center; gap: var(--s3); width: 100%;
  padding: var(--s3) var(--s4);
  border: 1px solid var(--rule); border-radius: var(--r-2); background: var(--paper);
}
.sc-chain-node[data-treat="product"] { border-color: var(--teal-dark); }
.sc-chain-name { font-weight: 600; }
.sc-chain-node .sc-glyph { color: var(--teal-dark); }

/* ---- Band 3, the three cards ---- */
.sc-cards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s6); }
/* align-content: start, because the row stretches every card to the tallest and a grid with
   auto rows then distributes that extra space BETWEEN the rows, which pushed one card's heading
   seven pixels below its two neighbours. */
.sc-card { display: grid; align-content: start; gap: var(--s3); justify-items: center; text-align: center; }
.sc-card > * { margin: 0; }
.sc-card .sc-glyph { color: var(--teal-dark); }
.sc-card-title { max-width: 22ch; }
.sc-card-line { color: var(--ink-2); max-width: 34ch; }
@media (max-width: 900px) { .sc-cards { grid-template-columns: minmax(0, 1fr); gap: var(--s5); } }

/* ---- Band 4, the worked example panel ---- */
.sc-example { display: grid; gap: var(--s5); padding: var(--s6); }
.sc-example-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s4); flex-wrap: wrap; }
/* The party name and the treatment chip sit together. They wrap onto their own line at a narrow
   width rather than crowding the eyebrow, which was measured at 390 rather than decided by eye. */
.sc-example-label { color: var(--ink-2); margin: 0; display: inline-flex; align-items: center; gap: var(--s3); flex-wrap: wrap; }
.sc-example-body { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); gap: var(--s6); align-items: start; }
.sc-example-text > :first-child { margin-top: 0; }
.sc-example-text ul { list-style: none; display: grid; gap: var(--s3); padding: 0; }
.sc-example-text li { padding-left: var(--s4); border-left: 2px solid var(--teal-dark); }
@media (max-width: 900px) { .sc-example-body { grid-template-columns: minmax(0, 1fr); } }

/* The small figure inside the panel: two decisions, two owners. */
.sc-split { padding: var(--s4); background: var(--paper); display: grid; gap: var(--s3); }
.sc-split-cap { color: var(--ink-2); text-transform: none; letter-spacing: normal; }
.sc-split-pair { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s3); }
.sc-split-box {
  display: grid; gap: var(--s2); align-content: start; justify-items: start;
  padding: var(--s3); border: 1px solid var(--rule); border-radius: var(--r-2); background: var(--white);
}
.sc-split-box[data-treat="product"] { border-color: var(--teal-dark); }
.sc-split-box > * { margin: 0; }
.sc-split-decision { font-weight: 600; }
.sc-split-owner { font-size: var(--t-small); line-height: var(--t-small-line); }
.sc-split-line { color: var(--ink-2); }
@media (max-width: 560px) { .sc-split-pair { grid-template-columns: minmax(0, 1fr); } }

/* ---- Band 5, the closing panel ---- */
.sc-closing { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--s5); align-items: start; padding: var(--s6); }
.sc-closing-mark {
  display: grid; place-items: center; width: 72px; height: 72px; flex: none;
  border-radius: var(--r-2); background: var(--wash-teal); color: var(--teal-dark);
}
.sc-closing-body > :first-child { margin-top: 0; }
.sc-closing-links { display: flex; flex-wrap: wrap; gap: var(--s4); align-items: baseline; }
.sc-closing-sep { width: 4px; height: 4px; border-radius: 50%; background: var(--rule); }
@media (max-width: 700px) { .sc-closing { grid-template-columns: minmax(0, 1fr); } }

/* ---- The glyph ---- */
.sc-glyph { display: inline-grid; place-items: center; flex: none; width: 36px; height: 36px; }
.sc-card .sc-glyph { width: 44px; height: 44px; }
.sc-glyph svg { width: 100%; height: 100%; }
.sc-glyph-large { width: 40px; height: 40px; }

/* A CAPABILITY CLAIM, ONE LINE, WITH ITS ARTEFACTS INSIDE IT. These were full panels stacked open,
   which took the Technical evidence drawer on two scenario pages past 850 words of unbroken text.
   The statement and the evidence mark are what a reader scans; the artefacts are what they open. */
.claim-row { border-bottom: 1px solid var(--rule); }
.claim-row > summary {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  gap: var(--s3); align-items: baseline;
  padding: var(--s3) 0; cursor: pointer; list-style: none;
}
.claim-row > summary::-webkit-details-marker { display: none; }
.claim-row-say { font-size: var(--t-small); color: var(--ink); }
.claim-row-mark { white-space: nowrap; }
.claim-row > .body { padding: 0 0 var(--s4) var(--s5); display: grid; gap: var(--s2); }
@media (max-width: 760px) {
  .claim-row > summary { grid-template-columns: auto minmax(0, 1fr); }
  .claim-row-mark { grid-column: 2; }
}

/* ---- src/parts/sec.css ---- */
/*
 * /architecture/security. `sec-` is the whole page and nothing else on the site uses the prefix, so
 * this part cannot reach another component and another component cannot reach it.
 *
 * MEASURED FROM docs/redesign/refs7/three-pages.png, right panel of three. The panel is 512 of 1536
 * pixels wide, so spacing, type size, radius and stroke weight do not survive the downscale and none
 * of them is taken from it. Every one comes from the system's own scale. What is taken is the
 * COMPOSITION: a four tab strip under the subhead, a figure on the left of the first panel and a
 * heading, a short list and a small configuration table on its right, a four item principle strip
 * under the instrument.
 *
 * THE REFERENCE'S GREEN TICKS ARE NOT TAKEN, and this is the one deviation worth stating twice.
 * Green means Observed on this site and an Observed mark links its artefact. The reference paints
 * every line of its custody list green, and not one of those lines is a reading from this tenant.
 * The tick glyph stays and takes the accent, which carries no state meaning.
 *
 * CONTRAST, computed from the dark token values with the WCAG 2.x arithmetic of
 * packages/ui/tools/contrast.mjs on 14 September 2026, pair by pair rather than assumed. Every text
 * pair is at or above 4.5 and every graphic pair is at or above the 3 to 1 of WCAG 1.4.11:
 *   ink       on paper      15.94  a tier label, a step line, a principle label
 *   ink-2     on paper       6.33  a tier line, a principle line, a caption
 *   teal-dark on paper      10.00  a tick glyph, a step number, a plate stroke
 *   ink       on white      13.79  a panel heading, a configuration value, a model step
 *   ink-2     on white       5.48  a term name, a panel note
 *   teal-dark on white       8.65  a heading accent and the selected model
 *   ink-2     on paper-alt    5.95  an unselected tab
 *   ink       on wash-teal  12.11  the selected tab
 *   teal-dark on wash-teal    7.60  the bar under the selected tab
 *   ink       on paper-alt   14.97  a custody sentence under the sequence
 *   ink-2     on paper-alt    5.95  the model count on an unselected switch, a comparison heading
 *   teal-dark on paper-alt    9.39  the model count on the selected switch
 *   rule      on paper        3.56  a panel edge and a row edge
 *   rule      on white        3.08  a configuration row edge
 *   rule      on paper-alt    3.34  a step edge inside a custody sentence
 *   teal-mid  on paper        3.78  a plate stroke and the connector between two tiers
 *   teal-mid  on paper-alt    3.55  the ring around a principle glyph on an alternate band
 */

/* The instrument. A container query rather than a media query: the same component answers for its
   own width wherever it is drawn, and the viewport says nothing about that. */
.sec { container-type: inline-size; display: grid; gap: var(--s5); }

/* The tab strip. One rounded box with hairline dividers, as the reference draws it. The shape is
   the one wr.css already ships for the same job on /use-cases/wherever-it-runs; it is restated here
   rather than shared because a part may not edit another part, and a rule reaching across the two
   prefixes is the coupling the split exists to prevent. */
.sec-tabs {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  border: 1px solid var(--rule);
  border-radius: var(--r-2);
  background: var(--paper-alt);
  overflow: hidden;
}

.sec-tab {
  position: relative;
  margin: 0;
  padding: var(--s4) var(--s3);
  min-height: 48px;
  border: 0;
  border-left: 1px solid var(--rule);
  background: transparent;
  color: var(--ink-2);
  font: 600 var(--t-small) / var(--t-small-line) var(--sans);
  cursor: pointer;
  text-align: center;
}

.sec-tab:first-child { border-left: 0; }
.sec-tab:hover { color: var(--ink); }
.sec-tab[aria-selected="true"] { background: var(--wash-teal); color: var(--ink); }

/* The lit bar under the selected tab. A pseudo element rather than a border, so selecting a tab
   never changes its height and the strip never reflows. */
.sec-tab[aria-selected="true"]::after {
  content: "";
  position: absolute;
  left: var(--s3);
  right: var(--s3);
  bottom: 0;
  height: 2px;
  border-radius: 2px;
  background: var(--teal-dark);
}

/* No local `display` is written for a hidden panel. packages/ui/src/ui.css carries
   `[hidden] { display: none !important }`, which beats an author rule here whatever it says, and
   wr.css records the same measurement for the same reason. This note exists so the next reader does
   not add one and then wonder why it does nothing. */
.sec-panel { display: grid; gap: var(--s5); }
.sec-panel:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 4px; }

/* ---- the key custody panel ---------------------------------------------------------------- */

.sec-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  align-items: start;
  gap: var(--s5);
}

/* The figure. Three tiers down the page: the platform that pins, Connect that publishes, and the
   parties that issue. The reference draws them as isometric plates; a plate here is one svg per
   tier, and the words sit in the markup beside it rather than inside it, so a reader who cannot see
   the drawing reads the same three sentences. */
.sec-fig { margin: 0; display: grid; gap: var(--s3); }
.sec-tiers { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s5); }

.sec-tier {
  position: relative;
  display: grid;
  justify-items: center;
  gap: 2px;
  text-align: center;
}

/* The connector between two tiers. A pseudo element on the tier below, so the last tier grows no
   tail of its own. */
.sec-tier + .sec-tier::before {
  content: "";
  position: absolute;
  top: calc(var(--s5) * -1);
  left: 50%;
  width: 1px;
  height: var(--s5);
  background: var(--teal-mid);
}

.sec-plate { display: block; width: 100%; max-width: 260px; }
.sec-plate svg { display: block; width: 100%; height: auto; }
.sec-plate .sec-plate-face { fill: var(--paper-alt); stroke: var(--teal-mid); stroke-width: 1.5; }
.sec-plate .sec-plate-edge { fill: var(--paper); stroke: var(--teal-mid); stroke-width: 1.5; }
.sec-plate .sec-plate-glyph { fill: none; stroke: var(--teal-dark); stroke-width: 1.5; }

/* The one product tier. Only a Raidiam product is filled teal, which is the glance test the
   treatment vocabulary rests on. */
.sec-tier[data-treat="product"] .sec-plate .sec-plate-face { fill: var(--teal); fill-opacity: .18; }
.sec-tier[data-treat="product"] .sec-plate .sec-plate-glyph { stroke: var(--teal); }

.sec-tier-label { font: var(--t-h3-weight) var(--t-h3) / var(--t-h3-line) var(--sans); color: var(--ink); }
.sec-tier-line { font-size: var(--t-small); color: var(--ink-2); max-width: 30ch; }

/* The bottom tier holds three parties rather than one, as the reference has it. */
.sec-parties { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s2); }

.sec-party {
  display: grid;
  justify-items: center;
  gap: 2px;
  padding: var(--s3) var(--s2);
  border: 1px solid var(--rule);
  border-radius: var(--r-1);
  background: var(--paper);
  text-align: center;
}

.sec-party-i { display: inline-grid; place-items: center; color: var(--teal-dark); }
.sec-party-i svg { width: 20px; height: 20px; }
.sec-party-label { font-size: var(--t-small); color: var(--ink); }

.sec-fig figcaption { font-size: var(--t-small); color: var(--ink-2); }

/* The column beside the figure: a heading, one line, the custody list, the configuration panel. */
.sec-side { display: grid; align-content: start; gap: var(--s4); min-width: 0; }
.sec-side-h { margin: 0; font: var(--t-h2-weight) var(--t-h2) / var(--t-h2-line) var(--sans); color: var(--ink); }
.sec-side-lead { margin: 0; font-size: var(--t-body); color: var(--ink-2); }

.sec-holds { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s2); }

.sec-holds li {
  display: grid;
  grid-template-columns: 20px minmax(0, 1fr);
  align-items: start;
  gap: var(--s3);
  font-size: var(--t-small);
  color: var(--ink);
}

/* The tick. It takes the accent and NOT the observed green: this list states how a model works, and
   a green mark on this site is a reading with an artefact behind it. */
.sec-holds-i { display: inline-grid; place-items: center; color: var(--teal-dark); padding-top: 2px; }
.sec-holds-i svg { width: 18px; height: 18px; }
.sec-holds .sec-holds-note { display: block; color: var(--ink-2); }

/* The configuration panel. A description list, because every row is a term and its value. */
.sec-config {
  display: grid;
  gap: 0;
  padding: var(--s4);
  border: 1px solid var(--rule);
  border-radius: var(--r-2);
  background: var(--white);
}

.sec-config-h { margin: 0 0 var(--s3); font: var(--t-h3-weight) var(--t-h3) / var(--t-h3-line) var(--sans); color: var(--ink); }
.sec-config-rows { margin: 0; display: grid; gap: 0; }

.sec-config-rows > div {
  display: grid;
  grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
  align-items: baseline;
  gap: var(--s3);
  padding: var(--s3) 0;
  border-top: 1px solid var(--rule);
}

.sec-config-rows > div:first-child { border-top: 0; padding-top: 0; }
.sec-config-rows dt { font-size: var(--t-small); color: var(--ink-2); }
.sec-config-rows dd { margin: 0; font-size: var(--t-small); color: var(--ink); }

/* ---- the certificates panel ---------------------------------------------------------------- */

.sec-models { display: grid; gap: var(--s4); }

/* The model switch. A second tab strip inside the first panel, because the sequence below it is
   the same five positions in four different models, and four sequences drawn side by side would
   say they are four mechanisms. */
.sec-switch {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--s2);
}

.sec-model-tab {
  margin: 0;
  padding: var(--s3);
  border: 1px solid var(--rule);
  border-radius: var(--r-1);
  background: var(--paper-alt);
  color: var(--ink-2);
  font: 600 var(--t-small) / var(--t-small-line) var(--sans);
  cursor: pointer;
  text-align: left;
}

.sec-model-tab:hover { color: var(--ink); }
.sec-model-tab[aria-selected="true"] { background: var(--wash-teal); color: var(--ink); border-color: var(--teal-dark); }
.sec-model-count { display: block; color: var(--ink-2); }
.sec-model-tab[aria-selected="true"] .sec-model-count { color: var(--teal-dark); }

.sec-model-panel:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 4px; }
.sec-model-body { display: grid; gap: var(--s4); }

/* The sequence. Five positions in a row on a wide screen, stacked on a narrow one, with the number
   carrying the order rather than an arrow, so nothing has to be redrawn when a model has fewer. */
.sec-steps { list-style: none; margin: 0; padding: 0; display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: var(--s2); }

.sec-step {
  display: grid;
  align-content: start;
  gap: var(--s2);
  padding: var(--s4) var(--s3);
  border: 1px solid var(--rule);
  border-radius: var(--r-1);
  background: var(--white);
  font-size: var(--t-small);
  color: var(--ink);
}

.sec-step-n {
  display: inline-grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border: 1px solid var(--teal-dark);
  border-radius: var(--pill);
  color: var(--teal-dark);
  font-size: var(--t-small);
}

/* A position a model does not have. It keeps its place in the row, so a reader comparing two models
   sees which step is absent rather than a shorter row. */
.sec-step[data-absent="yes"] { background: var(--paper); color: var(--ink-2); border-style: dashed; }
.sec-step[data-absent="yes"] .sec-step-n { border-style: dashed; color: var(--ink-2); border-color: var(--rule); }

.sec-custody-line {
  display: grid;
  gap: var(--s2);
  padding: var(--s4);
  border: 1px solid var(--rule);
  border-radius: var(--r-2);
  background: var(--paper-alt);
  font-size: var(--t-small);
  color: var(--ink);
}

.sec-custody-line b { color: var(--ink); }
.sec-custody-where { color: var(--ink-2); }

/* ---- the deployment panel ------------------------------------------------------------------ */

/* Two value columns against one term column. The left value is what Raidiam Connect can do and the
   right is what this showcase deployment does, and the page is wrong the moment those two are drawn
   as one.

   IT IS A REAL TABLE AND IT IS NOT `.site-table`. The site's table rules live in
   apps/site/src/public/site.css, which the page loads AFTER this bundle, so every rule there beats
   a rule here at equal specificity whatever either file looks like to a reader. Taking that class
   and then adjusting it from this part would be a fight this part loses. The class is its own, and
   only `.table-scroll`, which sets overflow alone, is shared. */
.sec-compare { width: 100%; border-collapse: collapse; background: var(--white); border: 1px solid var(--rule); border-radius: var(--r-2); overflow: hidden; }

.sec-compare th,
.sec-compare td {
  text-align: left;
  vertical-align: top;
  padding: var(--s3) var(--s4);
  border-bottom: 1px solid var(--rule);
  font-size: var(--t-small);
  font-weight: 400;
}

.sec-compare thead th { background: var(--paper-alt); color: var(--ink-2); }
.sec-compare tbody th { color: var(--ink-2); width: 22%; }
.sec-compare tbody td { color: var(--ink); }
.sec-compare tbody tr:last-child th,
.sec-compare tbody tr:last-child td { border-bottom: 0; }
.sec-compare-mark { display: block; margin-top: 2px; }

/* ---- the crypto agility panel -------------------------------------------------------------- */

.sec-alg { display: grid; gap: var(--s3); grid-template-columns: repeat(3, minmax(0, 1fr)); }

.sec-alg-card {
  display: grid;
  align-content: start;
  gap: var(--s2);
  padding: var(--s4);
  border: 1px solid var(--rule);
  border-radius: var(--r-2);
  background: var(--white);
}

.sec-alg-name { margin: 0; font: var(--t-h3-weight) var(--t-h3) / var(--t-h3-line) var(--sans); color: var(--ink); }
.sec-alg-name code { font-family: var(--mono); font-size: var(--t-small); color: var(--teal-dark); }
.sec-alg-line { margin: 0; font-size: var(--t-small); color: var(--ink); }
.sec-alg-where { margin: 0; font-size: var(--t-small); color: var(--ink-2); }

/* ---- the principle strip -------------------------------------------------------------------- */

.sec-principles { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s4); }

.sec-principle {
  display: grid;
  justify-items: center;
  gap: var(--s2);
  padding: 0 var(--s3);
  border-left: 1px solid var(--rule);
  text-align: center;
}

.sec-principle:first-child { border-left: 0; }
.sec-principle-i { display: inline-grid; place-items: center; width: 44px; height: 44px; border: 1px solid var(--teal-mid); border-radius: var(--pill); color: var(--teal-dark); }
.sec-principle-i svg { width: 22px; height: 22px; }
.sec-principle-label { font-size: var(--t-body); color: var(--ink); }
.sec-principle-line { font-size: var(--t-small); color: var(--ink-2); }

/* ---- narrow widths -------------------------------------------------------------------------- */

/* Container queries, on the instrument's own width. The order is the reading order: the figure and
   its column stack first, then the five step sequence turns into a list, then the two comparison
   columns fall under their term. */
@container (max-width: 900px) {
  .sec-split { grid-template-columns: minmax(0, 1fr); }
  .sec-steps { grid-auto-flow: row; grid-auto-columns: auto; }
  .sec-alg { grid-template-columns: minmax(0, 1fr); }
  .sec-switch { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@container (max-width: 640px) {
  .sec-parties { grid-template-columns: minmax(0, 1fr); }
}

/* The tab strip and the principle strip are page furniture rather than instrument content, so they
   answer to the viewport the way every other strip on this site does. */
@media (max-width: 900px) {
  .sec-tabs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .sec-tab:nth-child(odd) { border-left: 0; }
  .sec-tab:nth-child(n + 3) { border-top: 1px solid var(--rule); }
  .sec-principles { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s5); }
  .sec-principle:nth-child(odd) { border-left: 0; }
}

@media (max-width: 560px) {
  .sec-principles { grid-template-columns: minmax(0, 1fr); }
  .sec-principle { border-left: 0; }
}

/* ---- src/parts/sprawl.css ---- */
/* ---------------------------------------------------------------------------------------------
 * The sprawl figure: two panels, one mesh and one bar.
 *
 * The partial is packages/ui/partials/wires.ejs. It keeps the class .wires on its root because
 * three behaviours are attached to that name and none of them belongs to this file: ui.js draws
 * the after lines from an IntersectionObserver on .wires[data-animate], ui.css section 31 stops
 * that draw under prefers-reduced-motion with !important, and the overflow rule in section 5 gives
 * .wires > * a min-width of 0 so a wide figure cannot push the page sideways. .sprawl is the second
 * class, and it carries the treatment below.
 *
 * WHY THE SIDE COLOUR IS A LOCAL CUSTOM PROPERTY. Each panel sets --side once, and the kicker, the
 * total, the list marker, the top hairline and the head glow all read it. One declaration per
 * panel rather than five pairs of rules, and adding a third panel later is one line.
 *
 * THE PANEL GLOW IS OPACITY ON A PSEUDO ELEMENT, not a translucent colour. The tokens are opaque
 * hexes, so tinting them needs either color-mix or a layer with its own opacity. The layer is used
 * here because it also gives the top hairline somewhere to live and costs no colour arithmetic.
 *
 * TEXT SIZE INSIDE THE DRAWING IS BUMPED ON A PHONE. The art scales with its viewBox, so a 12 unit
 * label drawn at 460 units wide renders at about 9 pixels once the panel is 350 pixels wide. The
 * media query below raises the units so the rendered size stays near the desktop one. Each rule
 * names `svg text`, which is also what the stylesheet gate requires of any size under 14.
 * ------------------------------------------------------------------------------------------- */

.wires.sprawl { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s5); }

.sprawl .sprawl-panel {
  position: relative;
  overflow: hidden;
  display: grid;
  gap: var(--s4);
  align-content: start;
  padding: var(--s5);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
  background: var(--white);
}
.sprawl .sprawl-panel[data-side="before"] { --side: var(--no); }
.sprawl .sprawl-panel[data-side="after"] { --side: var(--cyan); }

/* The head glow and the top hairline, one layer each, both decorative. */
.sprawl .sprawl-panel::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 180px;
  background: radial-gradient(60% 100% at 50% 0, var(--side), transparent 72%);
  opacity: 0.13;
  pointer-events: none;
}
.sprawl .sprawl-panel::after {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--side), transparent);
  opacity: 0.75;
  pointer-events: none;
}

.sprawl .sprawl-head { display: grid; gap: var(--s1); position: relative; }
.sprawl .sprawl-kicker { color: var(--side); }
.sprawl .sprawl-sub { font-size: var(--t-body); color: var(--ink); }

/* The drawing */
/* The art fills the panel, and the viewBox is drawn WIDE for that reason. It scales with its own
   viewBox, so a narrow drawing stretched to a 610 pixel panel magnifies everything in it: at 460
   units the agent numeral rendered at 17 pixels and out shouted the arithmetic under it. 560 units
   across a 610 pixel panel is a scale of 1.09, and the drawing keeps the panel's own left and right
   edges rather than floating in the middle of it. */
.sprawl .sprawl-art { display: block; width: 100%; height: auto; overflow: visible; }
.sprawl .sprawl-plot { display: grid; gap: var(--s2); }
.sprawl .rowlab { margin: 0; font-size: var(--t-label); line-height: 1; color: var(--ink-2); text-transform: uppercase; letter-spacing: 0.12em; }
.sprawl svg text { font-family: var(--sans); fill: var(--ink); }
.sprawl svg text.agent-n { font-size: 13px; font-family: var(--mono); font-weight: 600; }
.sprawl svg text.bar-label { font-size: 14px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; fill: var(--on-brand); }

.sprawl .node.agent { fill: var(--white); stroke-width: 1.6; }
.sprawl .a-glow { opacity: 0.5; }
.sprawl .node[data-treat="reference"] { stroke-width: 1.4; }
.sprawl .p-glyph { fill: none; stroke: var(--ink-2); stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round; }
.sprawl .bar-glow { fill: var(--cyan); opacity: 0.45; }

/* The mesh. Thin, straight and crossing, which is the whole argument of the left panel.
 *
 * THESE TWO WIDTHS WERE SET BY ACCIDENT AND ARE NOW SET ON PURPOSE. A stray closing brace left the
 * narrow panel's widths, 1.8 and 3.4, sitting at the top level, so every desktop render was drawn
 * with the phone's weights and the values below reached nothing. Removing the brace made the curves
 * spindly against the bar, which is how the accident was worth reading: 1 and 2 are too light at a
 * scale of 1.09. These are the accidental figures walked back, with the drawn result looked at. */
.sprawl .wire { stroke-width: 1.3; opacity: 0.6; }
/* Both halves of the after panel answer to .wire-after: the six that lean in and the four that fan
   out. They were .wire-up and .wire-after, and the split cost somebody a wrong reading, because
   querying the obvious name returned four of the ten and the six looked absent. One name for the
   ten, one modifier for the half that carries an agent's colour. */
.sprawl .wire-after { fill: none; stroke-width: 2.8; stroke-linecap: round; }

/* The draw on. Each line carries its own length in --len, so the wipe takes the whole duration
   whatever the line measures. The shared rule in ui.css assumes 1000 user units, which on a 43 unit
   leg would hold the line invisible for 95 percent of the animation and then flick it on. */
.wires.sprawl .draw { stroke-dasharray: var(--len, 1000); stroke-dashoffset: var(--len, 1000); }
.wires.sprawl.is-drawn .draw, .wires.sprawl:not([data-animate]) .draw { stroke-dashoffset: 0; }

/* The arithmetic */
/* The number and its unit are one word. Left as two children of the wrapping row, a narrow panel
   broke between them and left the 24 on a line by itself. */
.sprawl .sprawl-sum { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s3); margin: 0; }
.sprawl .sprawl-value { display: flex; align-items: baseline; gap: var(--s3); }
.sprawl .sprawl-eq { font-size: var(--t-small); color: var(--ink-2); }
.sprawl .sprawl-total { color: var(--side); }
.sprawl .sprawl-unit { font-size: var(--t-body); color: var(--ink); }

/* What changes */
.sprawl .sprawl-facts { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s2); }
.sprawl .sprawl-facts li { display: grid; grid-template-columns: 16px minmax(0, 1fr); gap: var(--s3); align-items: start; font-size: var(--t-small); color: var(--ink); }
.sprawl .sprawl-facts .ic { width: 16px; height: 16px; margin-top: 3px; color: var(--side); }

.sprawl .sprawl-note { margin: 0; padding-top: var(--s4); border-top: 1px solid var(--rule); font-size: var(--t-small); color: var(--ink-2); }
.sprawl .sprawl-note p { margin: 0; }
.sprawl .sprawl-note p + p { margin-top: var(--s3); }

@media (max-width: 820px) {
  .wires.sprawl { grid-template-columns: minmax(0, 1fr); }
}

/* THE DRAWING IS SIZED AGAINST ITS PANEL, NOT AGAINST THE VIEWPORT.
 *
 * The art fills the panel and scales with its own 560 unit viewBox, so everything inside it, text,
 * rings and line widths, is multiplied by whatever that panel happens to be. The panel is 610 pixels
 * wide on a 1440 desktop, 334 at 821 where the two columns have not yet stacked, and about 295 on a
 * 390 phone. That is a scale of 1.09, then 0.60, then 0.53, and at the bottom of it the 13 unit
 * agent numeral lands at 7 pixels. It is not a small numeral there, it is an unreadable one.
 *
 * A viewport media query is the wrong instrument for this, and measuring said so: the narrowest
 * panel on the whole page is not the phone, it is a 900 pixel window, where two columns each leave
 * about 340 pixels. A query keyed to the viewport would have made the phone legible and left that
 * one as it was. The panel's own width is the thing that decides, so the panel is the container and
 * the two steps below read it.
 *
 * The ring grows less than its numeral does, on purpose: a digit has to clear a floor that a circle
 * does not, and taking both up together would run the rings into each other.
 *
 * `r` and `stroke-width` are geometry and presentation properties. A browser that does not apply
 * them from CSS falls back to the attribute in the markup, which is the widest step. */
.sprawl .sprawl-panel { container-type: inline-size; }

@container (max-width: 520px) {
  .sprawl svg text.agent-n { font-size: 18px; }
  .sprawl svg text.bar-label { font-size: 19px; letter-spacing: 0.1em; }
  .sprawl svg .node.agent, .sprawl svg .a-glow { r: 19px; }
  .sprawl svg .platform-node .node-scale { transform: scale(1.2); }
  .sprawl .wire { stroke-width: 1.5; }
  .sprawl .wire-after { stroke-width: 3; }
  .sprawl .p-glyph { stroke-width: 1.9; }
}

@container (max-width: 380px) {
  .sprawl svg text.agent-n { font-size: 26px; }
  .sprawl svg text.bar-label { font-size: 25px; letter-spacing: 0.08em; }
  .sprawl svg .node.agent, .sprawl svg .a-glow { r: 20px; }
  .sprawl svg .platform-node .node-scale { transform: scale(1.4); }
  .sprawl .wire { stroke-width: 1.8; }
  .sprawl .wire-after { stroke-width: 3.4; }
  .sprawl .p-glyph { stroke-width: 2.4; }
}

/* Padding is the panel's own size, so it stays on a viewport query. Changing it inside a container
   query on the same panel would be asking the container to resize itself from its own answer. */
@media (max-width: 560px) {
  .sprawl .sprawl-panel { padding: var(--s4); }
}

/* ---- src/parts/srl.css ---- */
/* /use-cases/same-software: the page and its instrument, packages/ui/partials/srl-release.ejs.

   THE PAGE RHYTHM is the standard page's, /use-cases/your-own-assistant: the copy on top with the
   headline left and the lead right, the instrument across the full measure under it, the outcome
   row, then the close. The instrument never shares a row with the copy. CLAUDE.md rule 5 records
   what happened when it did: the cards fell to 155px and broke their titles mid word. */
.srp { --page-max: 1472px; }
.srp-top { position: relative; padding-block: 3.5rem var(--s6); display: grid; gap: var(--s7, 4rem); }
.srp-copy > * { margin: 0; }
.srp-copy .sc-eyebrow { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s3); letter-spacing: 0.22em; color: var(--slate); }
.srp-copy .sc-eyebrow .ev { letter-spacing: normal; text-transform: none; }
.srp-copy .sc-headline { margin-top: var(--s4); line-height: 1.02; letter-spacing: -0.035em; }
.srp-copy .sc-lead { margin-top: 1.25rem; max-width: 36rem; font-size: 17px; line-height: 1.55; color: var(--ink-lead); }
.srp-copy .sc-lead > p { margin: 0; }
.srp-copy .sc-actions { margin-top: var(--s5); display: flex; flex-wrap: wrap; gap: var(--s4); }
@media (min-width: 1100px) {
  .srp-copy { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: var(--s7, 4rem); grid-template-areas: "eyebrow eyebrow" "head lead" "head actions"; align-items: start; }
  .srp-copy .sc-eyebrow { grid-area: eyebrow; }
  .srp-copy .sc-headline { grid-area: head; }
  .srp-copy .sc-lead { grid-area: lead; margin-top: var(--s4); }
  .srp-copy .sc-actions { grid-area: actions; }
}
.srp-figure { min-width: 0; }

.srp-payoff { padding-block: var(--s6); }
.srp-outcomes { list-style: none; margin: 0; padding: var(--s6) 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); }
.srp-outcomes li { display: flex; flex-direction: column; align-items: center; text-align: center; padding: 0 var(--s4); }
.srp-outcomes li + li { border-left: 1px solid var(--hairline); }
.srp-outcome-i { width: 52px; height: 52px; }
.srp-outcome-i svg { width: 26px; height: 26px; }
.srp-outcome-t { margin: var(--s4) 0 0; font-size: 18px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.srp-outcome-l { margin: var(--s2) 0 0; max-width: 19rem; text-wrap: balance; font-size: 15px; line-height: 1.5; color: var(--ink-2); }
@media (max-width: 900px) {
  .srp-outcomes { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: var(--s6); }
  .srp-outcomes li + li { border-left: 0; }
  .srp-outcomes li:nth-child(even) { border-left: 1px solid var(--hairline); }
}
@media (max-width: 480px) {
  .srp-outcomes { grid-template-columns: minmax(0, 1fr); }
  .srp-outcomes li:nth-child(even) { border-left: 0; }
}

/* THE INSTRUMENT. Two columns at full width: the release and its two environments, then the two
   reading panels at 320px, which is the reference's panel width. The figure is a size container so
   its narrow state follows its own width rather than the viewport's. */
.srl { position: relative; margin: 0; container-type: inline-size; min-width: 0; }
.srl-in { position: relative; z-index: 1; display: grid; gap: var(--s6); }
.srl-in > * { min-width: 0; }
.srl > .srl-glow { position: absolute; z-index: 0; top: 200px; width: 980px; height: 480px; }

.srl-hub { max-width: 580px; margin: 0 auto; padding: var(--s5) var(--s5) var(--s4); }
.srl-hub-i { display: inline-flex; color: var(--teal-dark); filter: drop-shadow(0 0 10px var(--teal-dark)); }
.srl-hub-i svg { width: 44px; height: 44px; }
.srl-hub-e { margin: var(--s2) 0 0; font-size: 14px; line-height: 1.3; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink-2); }
.srl-hub-t { margin: 6px 0 0; font-size: 24px; line-height: 1.2; font-weight: 700; color: var(--ink); }
.srl-hub-l { margin: 4px 0 0; font-size: 15px; line-height: 1.5; color: var(--ink-2); }
.srl-chips { list-style: none; margin: var(--s4) 0 0; padding: 0; display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: var(--s2); }
.srl-chip { padding: 5px 10px; border-radius: 6px; border: 1px solid var(--hairline); font-size: 14px; line-height: 1.4; font-weight: 500; color: var(--ink); }
.srl-chip-brand { border-color: var(--teal-dark); color: var(--brand-strong); }
.srl-digest-w { font-family: var(--sans); font-weight: 600; }
.srl-digest { padding: 0 4px; font-family: var(--mono); font-size: 14px; line-height: 1.4; color: var(--ink-2); white-space: nowrap; }

.srl-fan { display: block; width: 100%; height: 72px; filter: drop-shadow(0 0 5px var(--teal-dark)); }
.srl-wire { fill: none; stroke: var(--teal-dark); stroke-width: 2; stroke-linecap: round; vector-effect: non-scaling-stroke; opacity: 0.85; }

/* THE TWO ENVIRONMENTS share their rows through subgrid, so both cards end on one line and both
   envelopes start on one line whatever wraps. No gap between the tracks, so each column centre sits
   exactly where its wire ends; each column pads itself instead. */
.srl-envs { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-rows: repeat(3, auto); }
.srl-env { display: grid; grid-row: span 3; grid-template-rows: subgrid; min-width: 0; padding-inline: calc(var(--s5) / 2); }
.srl-head { justify-self: center; width: 0; height: 0; border-left: 7px solid transparent; border-right: 7px solid transparent; border-top: 11px solid var(--brand-strong); }
.srl-ped { height: 84px; }
.srl-card { display: flex; flex-direction: column; padding: var(--s5); }
.srl-t { margin: 0; font-size: 19px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.srl-s { margin: 4px 0 0; font-size: 15px; line-height: 1.45; color: var(--ink-2); }
.srl-rows { margin: var(--s4) 0 0; display: grid; gap: var(--s4); }
/* THE ICON IS INSIDE THE TERM, because a description list's group may hold only terms and
   descriptions. The description is indented to the text of the term beside the icon. */
.srl-row dt { display: flex; align-items: center; gap: var(--s3); font-size: 15px; line-height: 1.35; font-weight: 600; color: var(--ink); }
.srl-row-i { display: inline-flex; flex: 0 0 20px; color: var(--hue); }
.srl-row-i svg { width: 20px; height: 20px; display: block; }
.srl-row dd { margin: 2px 0 0 calc(20px + var(--s3)); font-size: 15px; line-height: 1.45; color: var(--ink-2); }

.srl-env-box { margin-top: auto; padding-top: var(--s4); }
.srl-env-box::before { content: ""; display: block; height: 1px; margin-bottom: var(--s4); background: var(--hairline); }
.srl-env-h { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s2); margin: 0 0 var(--s3); font-size: 14px; line-height: 1.3; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-2); }
.srl-op { letter-spacing: normal; text-transform: none; font-family: var(--mono); font-size: 14px; font-weight: 600; color: var(--hue); }
.srl-types { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.srl-type { padding: 2px 8px; border-radius: 6px; border: 1px solid var(--hue); font-family: var(--mono); font-size: 14px; line-height: 1.5; color: var(--ink); }
/* THE ONE STATE ON THE FIGURE. A dashed edge and a strike on the type, and the word beside it in the
   refusal colour, because the resolved answer leaves the claimed type out. */
.srl-type[data-state="dropped"] { border-style: dashed; border-color: var(--rule); color: var(--ink-2); }
.srl-type[data-state="dropped"] .srl-type-n { text-decoration: line-through; }
/* AN ADDED TYPE is part of the envelope, so it keeps the kept edge, and says in muted ink that the
   policy put it there. No state colour: adding is what a value row does, not a verdict. */
.srl-type-a { font-family: var(--sans); font-size: 14px; font-weight: 600; color: var(--ink-2); white-space: nowrap; }
.srl-type-w { font-family: var(--sans); font-size: 14px; font-weight: 600; color: var(--no); white-space: nowrap; }

.srl-side { display: grid; gap: var(--s4); align-content: start; }
.srl-panel .rw-panel-h { margin-bottom: var(--s3); }
.srl-same, .srl-differ { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.srl-same li, .srl-differ li { display: flex; align-items: center; gap: var(--s3); font-size: 15px; line-height: 1.4; color: var(--ink); }
.srl-tick { display: inline-flex; color: var(--teal-dark); }
.srl-tick svg { width: 18px; height: 18px; }
.srl-differ-i { display: inline-flex; color: var(--brand-strong); }
.srl-differ-i svg { width: 19px; height: 19px; }

@container (min-width: 1180px) {
  .srl-in { grid-template-columns: minmax(0, 1fr) 320px; align-items: start; }
  .srl-side { padding-top: var(--s2); }
}
@container (min-width: 700px) and (max-width: 1179px) {
  .srl-side { grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; }
}

/* THE NARROW STATE. The two cards run down one lit rail, each pedestal a ringed icon on it, so the
   branch from one release still reads while the cards take the full width. */
@container (max-width: 699px) {
  .srl > .srl-glow { top: 160px; }
  .srl-fan, .srl-head { display: none; }
  .srl-hub { max-width: none; }
  .srl-envs { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; gap: var(--s4); padding: var(--s5) 0 0 44px; position: relative; }
  .srl-envs::before { content: ""; position: absolute; left: 17px; top: 0; bottom: 0; width: 2px; background: var(--teal-dark); opacity: 0.7; box-shadow: 0 0 6px var(--teal-dark); }
  .srl-env { display: block; grid-row: auto; padding-inline: 0; position: relative; }
  .srl-ped { position: absolute; left: -44px; top: 16px; width: 36px; height: 36px; border-radius: 50%; background: var(--paper); border: 1.5px solid var(--hue); align-items: center; }
  .srl-ped::before, .srl-ped::after, .srl-ped .rw-ped-contact { display: none; }
  .srl-ped .rw-ped-i { margin: 0; }
  .srl-ped .rw-ped-i svg { width: 20px; height: 20px; }
  .srl-card { padding: var(--s4); }
}

/* ---- src/parts/sse.css ---- */
/* The two figures /use-cases/same-software/evidence draws itself: packages/ui/partials/sse-hop.ejs
   and packages/ui/partials/sse-once.ejs. The comparison figure on the same route is evf-matrix and
   is styled in evf.css.

   Both figures are size containers, so their narrow state follows the width the evidence band gives
   them rather than the viewport. */
.sse-hop, .sse-once { position: relative; margin: 0; container-type: inline-size; min-width: 0; }
.sse-hop > *, .sse-once > * { position: relative; z-index: 1; }
.sse-hop > .sse-glow, .sse-once > .sse-glow { position: absolute; z-index: 0; top: 60px; width: 900px; height: 380px; }

/* WHERE THE CEILING SITS. Seven tracks, node, statement, node, statement, node, statement, node. A
   node track is 1fr and a statement track 1.4fr, so a policy card under one statement has room for
   two types side by side. */
.sse-hop { display: grid; gap: var(--s5); --sse-cols: minmax(0, 1fr) minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 1.4fr) minmax(0, 1fr); }

.sse-lane { border-radius: 12px; border: 1px solid var(--hairline); border-top-color: var(--hue); background: var(--paper); padding: var(--s4) var(--s4) var(--s5); }
.sse-lane-t { display: flex; align-items: center; gap: var(--s2); margin: 0 0 var(--s4); font-size: 16px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.sse-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--hue); box-shadow: 0 0 8px var(--hue); }
.sse-chain { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: var(--sse-cols); align-items: start; }
.sse-lane[data-policy-at="leaf"] .sse-e-long { grid-column: 2 / 5; grid-row: 1; }

.sse-n { display: flex; align-items: center; justify-content: center; min-height: 48px; padding: 6px 10px; border-radius: 10px; border: 1px solid var(--hairline); background: var(--paper-alt); text-align: center; font-size: 15px; line-height: 1.3; font-weight: 600; color: var(--ink); }
.sse-n[data-n="leaf"] { border-color: var(--hue); box-shadow: inset 0 1px 0 var(--hue); }
.sse-n[data-n="root"] { border-color: var(--hue); }

/* A STATEMENT is a line level with the middle of the nodes, its label on the line, and the policy
   card, when it carries one, under it. The hop is drawn heavier in the lane's hue. */
.sse-e { position: relative; display: flex; flex-direction: column; align-items: center; padding: 0 var(--s2); min-height: 48px; }
.sse-e::before { content: ""; position: absolute; left: 0; right: 0; top: 23px; height: 2px; background: var(--rule); }
.sse-e-hop::before, .sse-e-long::before { background: var(--hue); height: 3px; top: 22px; box-shadow: 0 0 6px var(--hue); }
.sse-e-l { position: relative; margin-top: 12px; padding: 0 8px; background: var(--paper); font-size: 14px; line-height: 1.5; font-weight: 600; color: var(--ink); white-space: nowrap; }
/* THE POLICY CARD SITS IN A SECOND ROW, under the statement that carries it and spanning the node on
   each side, so it has room for its types and lies over nothing. A first version hung it inside the
   statement's own track and let it overhang, and at 1024 it covered the authority's name. */
.sse-pol-slot { grid-row: 2; display: flex; justify-content: center; padding-top: var(--s3); }
.sse-pol-slot[data-under="authority-leaf"] { grid-column: 2 / 5; }
.sse-pol-slot[data-under="authority-root"] { grid-column: 3 / 6; }
.sse-pol { width: 100%; max-width: 300px; border-radius: 8px; border: 1px solid var(--hue); background: var(--paper-alt); padding: var(--s2) var(--s3); }
.sse-pol-h { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px; margin: 0 0 6px; font-size: 14px; line-height: 1.4; color: var(--ink-2); }
.sse-pol-t { font-weight: 600; color: var(--ink); }
.sse-op { font-family: var(--mono); font-size: 14px; font-weight: 600; color: var(--hue); }
.sse-types { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.sse-type { padding: 2px 8px; border-radius: 6px; border: 1px solid var(--rule); font-family: var(--mono); font-size: 14px; line-height: 1.5; color: var(--ink); }
.sse-type[data-state="kept"] { border-color: var(--hue); }
.sse-type[data-state="dropped"] { border-style: dashed; color: var(--ink-2); }
.sse-type-n { text-decoration: line-through; }
.sse-type-w { font-family: var(--sans); font-weight: 600; color: var(--no); white-space: nowrap; }

/* THE FOLD. Three sets and two operators on one line: what the instance claims, intersected with the
   ceiling, equals what the resolve keeps. */
.sse-fold { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr) auto minmax(0, 1fr); align-items: stretch; gap: var(--s3); }
.sse-fold-c { border-radius: 10px; border: 1px solid var(--hairline); background: var(--paper); padding: var(--s3) var(--s4); }
.sse-fold-r { border-color: var(--hue); box-shadow: inset 0 1px 0 var(--hue); }
.sse-fold-h { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px; margin: 0 0 var(--s2); font-size: 14px; line-height: 1.35; font-weight: 600; color: var(--ink-2); }
.sse-fold-op { align-self: center; font-size: 24px; line-height: 1; font-weight: 600; color: var(--hue); }

@container (max-width: 759px) {
  .sse-chain { display: flex; flex-direction: column; align-items: stretch; }
  .sse-n { justify-content: flex-start; text-align: left; }
  .sse-e { align-items: flex-start; min-height: 0; padding: var(--s2) 0 var(--s2) var(--s5); }
  .sse-e::before { left: 18px; right: auto; top: 0; bottom: 0; width: 2px; height: auto; }
  .sse-e-hop::before, .sse-e-long::before { width: 3px; height: auto; top: 0; }
  .sse-e-l { margin-top: 0; padding: 0; background: none; white-space: normal; }
  .sse-e { min-height: 20px; }
  .sse-pol-slot { display: block; padding: 0 0 var(--s2) var(--s5); }
  .sse-pol { max-width: none; }
  .sse-fold { grid-template-columns: minmax(0, 1fr); }
  .sse-fold-op { justify-self: center; }
}

/* WHAT EACH PARTY DOES ONCE. Two lanes of numbered steps on rails in the party's hue, dropping into
   one result card. */
.sse-once { display: grid; gap: 0; justify-items: stretch; }
.sse-once-lanes { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s5); }
.sse-once-lane { display: flex; flex-direction: column; border-radius: 12px; border: 1px solid var(--hairline); border-top-color: var(--hue); background: var(--paper); padding: var(--s4) var(--s5) 0; }
.sse-once-t { margin: 0 0 var(--s4); font-size: 17px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.sse-once-s { font-weight: 500; color: var(--ink-2); }
.sse-once-steps { list-style: none; margin: 0 0 var(--s4); padding: 0; display: grid; gap: var(--s3); position: relative; }
.sse-once-steps::before { content: ""; position: absolute; left: 13px; top: 14px; bottom: 14px; width: 2px; background: var(--hue); opacity: 0.6; }
.sse-once-steps li { position: relative; display: flex; align-items: center; gap: var(--s3); font-size: 15px; line-height: 1.4; color: var(--ink); }
.sse-once-n { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 28px; width: 28px; height: 28px; border-radius: 50%; border: 1.5px solid var(--hue); background: var(--paper); font-size: 14px; font-weight: 600; color: var(--ink); }
.sse-once-drop { align-self: center; width: 2px; height: 28px; margin-top: auto; background: var(--hue); box-shadow: 0 0 6px var(--hue); }
.sse-once-r { width: 100%; margin-top: 0; padding: var(--s4) var(--s5); }
.sse-once-rt { margin: 0; font-size: 18px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.sse-once-rl { margin: 4px 0 0; font-size: 15px; line-height: 1.5; color: var(--ink-2); }

@container (max-width: 640px) {
  .sse-once-lanes { grid-template-columns: minmax(0, 1fr); gap: var(--s4); }
  .sse-once-lane:first-child .sse-once-drop { display: none; }
}

/* ---- src/parts/st-page.css ---- */
/* /start: apps/site/src/views/start.ejs.
 *
 * WHAT THIS FILE IS. The hero only. The cards are the home page card through
 * packages/ui/partials/uc-tile.ejs, the film band and the closing band are the home page's, so this
 * file lays out one thing: the headline beside the fastest answer on the site.
 *
 * WHAT IT REFUSES. A new card, a new colour and a panel around the copy. The page is a choice
 * between doors, and every door is the object the home page already taught the reader.
 */
.st-top { display: grid; gap: var(--s6); padding-bottom: var(--s5); }
@media (min-width: 1100px) {
  .st-top { grid-template-columns: minmax(0, 1fr) minmax(0, 520px); gap: var(--s7, 4rem); align-items: end; }
}
.st-top-copy { display: grid; align-content: start; }
.st-top-copy > * { margin: 0; }
.st-headline { margin-top: var(--s4); line-height: 1.02; letter-spacing: -0.035em; max-width: 16ch; text-wrap: balance; }
.st-lead { margin-top: 1.25rem; max-width: 34rem; font-size: 17px; line-height: 1.55; color: var(--ink-lead); }
.st-note { margin-top: var(--s4); max-width: 34rem; font-size: 14px; line-height: 1.5; color: var(--ink-2); }
.st-fast { min-width: 0; }
.st-fast .hme-uc { height: 100%; }
/* The six doors belong to the headline above them, so no rule divides the two. */
.st-roles { padding-top: var(--s5); border-top: 0; }
/* FOUR ROLE CARDS IN ONE ROW at the home grid's three column step, so the four read as one choice
   rather than three and a leftover. Below it they keep the home grid's two and one columns. */
@media (min-width: 1190px) { .st-page .st-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.st-more { margin: var(--s5) 0 0; font-size: 16px; line-height: 1.5; color: var(--ink-2); }

/* ---- src/parts/uc-changes.css ---- */
/* The window figure on /use-cases/when-something-changes, which the rebuild moved into a drawer.
 *
 * uc-changes-reach and uc-changes-scopes stood here too and their rules have gone with them. The
 * page draws one instrument now, packages/ui/partials/ch-change.ejs, styled in ch.css, and the
 * reach figure and the scope rail were two more accounts of the same mechanism.
 *
 * OWNERSHIP. Every selector in this part begins .ucx. The scenario structure that surrounds these
 * two figures is .sc and belongs to another part, so the two cannot collide and neither has to
 * raise specificity against the other.
 *
 * THE ONE DELIBERATE DEVIATION FROM THE COMP, recorded here so nobody restores it from the picture.
 * docs/redesign/refs3/two-more.png fills its primary button with a true blue. Measured as a median
 * over 1400 pixels of the "See it in action" fill: rgb(2, 122, 254). That colour is in no token and
 * the dark site has ONE accent on purpose: packages/ui/tools/build.mjs resolves teal, teal-deep,
 * teal-dark and cyan to a single value on dark. Adding a second accent is a token decision across
 * nineteen routes and it is Ralph's, not a figure's. Nothing here paints a blue.
 *
 * MEASURED FROM THE COMP AND MATCHED BY TOKEN, so the next reader can check rather than trust:
 *   ground       rgb(0, 17, 29)     against --paper      rgb(0, 23, 33)
 *   card fill    rgb(3, 23, 40)     against --white      rgb(11, 37, 49)
 *   panel fill   rgb(1, 26, 44)     against --paper-alt  rgb(3, 30, 39)
 *   headline ink rgb(245, 248, 251) against --ink        rgb(230, 241, 243)
 *   accent       rgb(41, 222, 244)  against --teal-dark  rgb(21, 212, 216)
 *   red mark     rgb(200, 79, 79)   against --no         rgb(233, 85, 102)
 * Each pair sits in the same family, so no token moves.
 */

/* ---- The window figure, band 4 --------------------------------- */

/* The comp draws two empty cards peeking out behind this one. They are decoration and they carry no
   content, so they are drawn here rather than in the markup and are hidden from the accessibility
   tree by being pseudo elements with no text. */
.ucx-window {
  position: relative;
  margin: 0 0 0 var(--s2);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
  background: var(--white);
  padding: var(--s5);
  display: grid;
  gap: var(--s4);
}

.ucx-window::before {
  content: "";
  position: absolute;
  inset: calc(var(--s2) * -1) auto auto calc(var(--s2) * -1);
  width: 100%;
  height: 100%;
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
  opacity: 0.45;
  z-index: -1;
}

.ucx-window-head {
  display: grid;
  gap: var(--s1);
}

.ucx-window-title {
  font-size: var(--t-h3);
  line-height: var(--t-h3-line);
  font-weight: var(--t-h3-weight);
  letter-spacing: var(--t-h3-tracking);
  color: var(--ink);
}

.ucx-window-line {
  color: var(--ink-2);
}

.ucx-window-rows {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--s3);
}

/* Label, then the window, then the evidence label. The evidence label is a site cell rendered by
   _evcell, so its colour comes from the base sheet: green under Observed and nowhere else. This
   part declares no colour for it at all, which is how it stays that way. */
.ucx-window-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: baseline;
  gap: var(--s1) var(--s4);
  padding-bottom: var(--s3);
  border-bottom: 1px solid var(--rule);
}

.ucx-window-rows > .ucx-window-row:last-child {
  padding-bottom: 0;
  border-bottom: 0;
}

.ucx-window-row-label {
  color: var(--ink);
}

.ucx-window-row-bound {
  color: var(--ink);
  white-space: nowrap;
}

/* The evidence label ends the line, which is where the comp's tick sits and where a reader who is
   scanning for the labels expects them. A row whose bound is absent leaves the middle column empty
   and the label still lands in the same place, so the labels read as a column. It moves under the
   label at the narrow end, where three things on one line stop fitting. */
.ucx-window-row-ev {
  grid-column: 3;
  justify-self: start;
}

.ucx-window-caption {
  color: var(--ink-2);
}

/* ---- Narrow ---------------------------------------------------- */

/* One column below the point where the three part flow stops fitting. The subject, the act and the
   rows keep the order they read in above it. */
@media (max-width: 640px) {
  .ucx-window {
    margin-left: 0;
    padding: var(--s4);
  }

  .ucx-window::before {
    display: none;
  }

  /* Label and bound on one line, the evidence label under them. Three things on one line stop
     fitting here: "Not observed on this tenant" alone is wider than a phone's reading column. */
  .ucx-window-row {
    grid-template-columns: minmax(0, 1fr) auto;
  }

  .ucx-window-row-ev {
    grid-column: 1 / -1;
  }
}

/* ---- src/parts/uc-live-bands.css ---- */
/* The /live bands, from the right half of docs/redesign/refs3/two-more.png. Partials:
   packages/ui/partials/uc-live-stack.ejs, uc-live-reads.ejs, uc-live-ceiling.ejs. uc-live-hero.ejs
   was the fourth until 13 September 2026, when the /live rebuild replaced its band and left it with no
   caller; packages/ui/tests/partial-callers.test.ts is what will name the next one.

   THE CLASS PREFIX IS lv, NOT uc AND NOT sc. packages/ui/src/parts/use-cases.css owns .uc-card and
   .uc-cards for the index at /use-cases, packages/ui/src/parts/scenario.css owns the .sc- set for the
   shared scenario bands, and every part is concatenated into one sheet in sorted file name order. A
   third .uc-card or a second .sc-hero here would win or lose silently by file order. The PARTIAL
   names keep the uc-live prefix the brief asked for; the CSS classes do not.

   WHAT THE COMP MEASURES, AND WHAT IS BUILT INSTEAD. Medians over thousands of pixels on the right
   half of the comp, which starts at x=774 and is 762 wide against a 1440 design, so colour survives
   the downscale and no metric does:

     page ground        #00111e     built as --paper   #001721
     card ground        #011726     built as --white   #0B2531
     primary button     #0278fe     built as --teal-dark #15D4D8

   The comp's cards are a little darker and cooler than this system's card, and its filled button is
   a true blue that is NOT this system's accent. The dark system has one accent deliberately, and a
   second is a token decision across nineteen routes that belongs to Ralph rather than to an agent.
   So both deviations are recorded here and neither is taken.

   THE ACCENT IS WRITTEN --teal-dark THROUGHOUT. On dark, --teal, --teal-deep, --teal-dark and --cyan
   all resolve to the same accent, and packages/ui/tests/stylesheet.test.ts reserves var(--teal) for
   a product marker, so writing --teal here would fail that test for a rule that marks no product.

   GREEN APPEARS UNDER Observed AND NOWHERE ELSE. Every state colour on this page comes from the
   evidence mark, which packages/ui/partials/ev.ejs draws, so no rule below sets --ok on anything.
   The comp puts a green tick beside nine lines across two bands. A tick reads as proof, so there are
   no ticks: each line carries its evidence mark, and four of the six carry Observed.

   WHAT LOADS AFTER THIS. apps/site/src/public/site.css loads after ui.css and holds generic .hero,
   .btn, .actions and .eyebrow rules that beat anything here at equal specificity. The hero reuses
   .btn, .actions and .sc-eyebrow deliberately, so that is the site's behaviour rather than a clash,
   and every structural class here carries the lv prefix so nothing in site.css reaches it. */

/* ---- The hero ---- */
.lv-hero { display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); gap: var(--s7); align-items: start; }
.lv-hero-body { display: grid; gap: var(--s4); }
.lv-hero-body > * { margin: 0; }
.lv-headline { margin-top: var(--s2); max-width: var(--measure-display); }
/* The comp sets the second line of the headline in the accent. It is one heading, so the accent is a
   span inside the h1 rather than a second element: a reader of the outline hears one line. */
.lv-headline-accent { color: var(--teal-dark); }
.lv-hero-figure { display: grid; }
@media (max-width: 900px) {
  .lv-hero { grid-template-columns: minmax(0, 1fr); gap: var(--s6); }
}

/* ---- The hero figure: the layers, and what each one answers ---- */
/* The figure carries no evidence mark and no link any more, so it also carries no focus stop. The
   rows are plain text in two named groups. See the head of uc-live-stack.ejs for why. */
.lv-stack { display: grid; gap: var(--s4); padding: var(--s5); }
.lv-stack-plates { display: grid; place-items: center; }
.lv-stack-plates svg { width: 100%; max-width: 200px; height: auto; }
.lv-stack-group { display: grid; gap: var(--s2); }
.lv-stack-cap { margin: 0; color: var(--ink-2); }
.lv-stack-list { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--s2); }
.lv-stack-row {
  font-size: var(--t-small); font-weight: 600;
  padding: var(--s1) var(--s3);
  border: 1px solid var(--rule); border-radius: var(--pill);
}
/* The half the page does not read takes the muted ink and a dashed edge rather than a state colour.
   Red is the refusal colour and nothing here is refused; these two are simply not reached. */
.lv-stack-group[data-lv-group="unread"] .lv-stack-row { color: var(--ink-2); border-style: dashed; }
.lv-stack-foot { color: var(--ink-2); margin: 0; }

/* ---- The reads ---- */
.lv-reads { display: grid; gap: var(--s4); }
.lv-read { display: grid; gap: var(--s3); padding: var(--s5); }
.lv-read-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--s2) var(--s4); }
.lv-read-title { margin: 0; }
.lv-read-note { margin: 0; color: var(--ink-2); max-width: var(--measure-notes); }
.lv-read-who { margin: 0; }
/* The request, as text rather than as a command block. It must WRAP rather than scroll: a box that
   scrolls sideways needs a focus stop to be reachable by keyboard, which is the ten hops this band
   was spending on five copies of what the raw drawer already carries. `anywhere` rather than
   `break-word` because a url has no spaces to break at. */
.lv-read-url {
  margin: 0; font-size: var(--t-small); color: var(--ink-2);
  overflow-wrap: anywhere; word-break: break-word;
}
.lv-read-look { margin: 0; color: var(--ink-2); max-width: var(--measure-notes); }
/* The one thing to look for in the answer, so a reader who presses the button knows what they are
   looking at rather than scrolling a signed statement hoping something stands out. */
.lv-read-look-word { color: var(--ink); font-weight: 600; }
.lv-read-actions { margin: 0; align-items: center; gap: var(--s3); }

/* ---- The bound ---- */
.lv-ceiling { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s4); }
.lv-ceiling-panel { display: grid; gap: var(--s3); align-content: start; padding: var(--s5); }
.lv-ceiling-cap { margin: 0; color: var(--ink-2); }
.lv-ceiling-line { margin: 0; color: var(--ink-2); max-width: var(--measure-notes); }
.lv-ceiling-ev { margin: 0; }
.lv-amount { margin: 0; display: flex; align-items: baseline; gap: var(--s2); }
.lv-amount-n { font-size: var(--t-h1); font-weight: 700; line-height: 1.1; font-variant-numeric: tabular-nums; }
.lv-amount-c { font-size: var(--t-h3); color: var(--ink-2); }
/* The amount above the bound takes the refusal colour, which is the one place on this page a state
   colour appears outside an evidence mark. It names a refusal rather than an absence of proof, which
   is the distinction packages/ui/src/parts/live.css already draws for the figure's one red row. */
.lv-amount-over .lv-amount-n { color: var(--no); }
/* What the refusal says, quoted from the code that builds it. A blockquote rather than a panel,
   because it is words somebody can go and read rather than an artefact read on the wire. */
.lv-says { margin: 0; padding-left: var(--s4); border-left: 2px solid var(--rule); display: grid; gap: var(--s2); }
.lv-says-text { margin: 0; font-family: var(--mono); font-size: var(--t-small); }
.lv-says-note { margin: 0; color: var(--ink-2); }
@media (max-width: 860px) {
  .lv-ceiling { grid-template-columns: minmax(0, 1fr); }
}

/* ---- The four scenario cards ---- */
.lv-scenarios { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s4); }
/* The whole card is the link, so the target is the card rather than the heading inside it. Grid
   rather than block, because the three lines are laid out and the anchor is the layout box. */
.lv-scenario {
  display: grid; gap: var(--s2); align-content: start;
  padding: var(--s5); border: 1px solid var(--rule); border-radius: var(--r-2);
  background: var(--white); color: var(--ink); text-decoration: none;
}
.lv-scenario:hover, .lv-scenario:focus-visible { border-color: var(--teal-dark); }
.lv-scenario-title { color: var(--ink); }
.lv-scenario-line { color: var(--ink-2); }
@media (max-width: 1100px) {
  .lv-scenarios { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .lv-scenarios { grid-template-columns: minmax(0, 1fr); }
}

/* ---- src/parts/uc-nav.css ---- */
/* THE USE CASES NAVIGATION, partials/uc-nav.ejs. The second navigation row, under the masthead.
 *
 * WHAT IT REFUSES TO DRAW. It draws no pill, no chip and no second underline style. The current
 * item was a filled cyan pill with dark text. The target marks the current item with a 2px brand
 * bar the width of the label, sitting on the strip's own bottom edge, and nothing else. A pill in
 * the brand reads as a control a reader can press, which a label for the page already open is not.
 *
 * THE DIVIDERS ARE --hairline, NOT --rule. --rule is the edge of a card or a panel, something a
 * person operates. Two --rule lines here drew a bright band across the top of every use case page.
 * The target's dividers are almost invisible and hold the row without announcing it.
 *
 * THERE IS ONE SEAM BETWEEN THE TWO ROWS AND THIS FILE DOES NOT DRAW IT. mast.css gives .masthead a
 * bottom border and _head.ejs places this strip immediately after </header>, so a border-top here
 * made a second line. With the sticky offset wrong by 2px as well, the target's single 1px seam
 * rendered as a line, then two pixels of scrolling page, then another line.
 *
 * THE ROW IS 46px AND THE LINKS FILL IT. Each link stretches to the full row height, so the current
 * item's bar lands on the bottom edge at bottom 0 rather than at a measured offset under the word.
 * The target does the same with a negative offset against a link with no vertical padding, and a
 * negative offset breaks the moment the row height or the line height moves.
 *
 * IT STICKS UNDER THE MASTHEAD, AT A HEIGHT THE MASTHEAD DECLARES. mast.css writes --masthead-h on
 * :root beside the rules that set the row, so the two cannot drift. They already had: this file
 * said 65px for a 64px row plus a 1px rule, the row became 62px, and a 2px slot of moving page
 * showed between the two borders while scrolling.
 * BELOW 1200px IT STOPS STICKING. The masthead row wraps at 1199px, hides its navigation and
 * reopens it as a full width column, so its height stops being a constant. This used to unstick at
 * 860px, which left 339px of width where a reader who opened the menu got a masthead several
 * hundred pixels tall over a strip still stuck at one row's height. The masthead is z-index 50 and
 * this is 40, so the open menu covered it.
 *
 * THE STRIP SCROLLS SIDEWAYS RATHER THAN WRAPPING. Six scenario names plus the index link do not
 * fit on a phone. A second row of links under a masthead reads as a second menu, and a menu that
 * wraps to three rows pushes the page heading below the fold. */
.uc-nav {
  position: sticky; top: var(--masthead-h, 63px); z-index: 40;
  background: var(--paper);
  border-bottom: 1px solid var(--hairline);
}
/* NO GAP ON THE ROW. The index link is pushed right by its own auto margin, so a gap here only
   took 24px off the scrolling list at every width and started it scrolling sooner than it had to. */
.uc-nav-row { display: flex; align-items: stretch; height: 46px; min-width: 0; }
.uc-nav-list {
  display: flex; align-items: stretch; gap: var(--s6);
  flex: 1 1 auto; min-width: 0; margin: 0; padding: 0; list-style: none;
  overflow-x: auto; scrollbar-width: none;
}
.uc-nav-list::-webkit-scrollbar { display: none; }
.uc-nav-item { flex: 0 0 auto; display: flex; }
.uc-nav-list a {
  position: relative; display: inline-flex; align-items: center;
  white-space: nowrap; text-decoration: none;
  color: var(--ink-nav); font-size: var(--t-label); font-weight: 400;
  transition: color 150ms ease;
}
.uc-nav-list a:hover { color: var(--ink); }
.uc-nav-list a[aria-current="page"] { color: var(--ink); font-weight: 600; }
/* The bar runs the full width of the label and sits on the strip's bottom edge. It carries no glow:
   the masthead's current item already owns the glowing bar, and one section marker per row is what
   tells a reader which row is which. */
.uc-nav-list a[aria-current="page"]::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
  background: var(--teal-dark);
}
.uc-nav-all {
  flex: 0 0 auto; margin-left: auto;
  display: inline-flex; align-items: center; gap: var(--s2);
  white-space: nowrap; text-decoration: none;
  color: var(--ink-nav); font-size: var(--t-label); font-weight: 500;
  transition: color 150ms ease;
}
.uc-nav-all:hover { color: var(--ink); }
.uc-nav-all[aria-current="page"] { color: var(--ink); font-weight: 600; }
.uc-nav-arrow { width: 16px; height: 16px; flex: none; }
@media (max-width: 1199px) {
  .uc-nav { position: static; }
}
/* THE INDEX LINK IS NOT HIDDEN ON A PHONE, and hiding it was the one narrow state that removed
   something rather than rearranging it. On /use-cases the index link is the ONLY element carrying
   aria-current, so a phone reader saw a strip with no current item and no route back to the index.
   The list scrolls and this link keeps its place at the right, which is what the scroll container
   was built for. */
@media (prefers-reduced-motion: reduce) {
  .uc-nav-list a, .uc-nav-all { transition: none; }
}

/* ---- src/parts/uc-next.css ---- */
/* THE NEXT USE CASE CONTROL, partials/uc-next.ejs.
 *
 * WHAT IT REFUSES TO DRAW. A card. It is the full width of the band with one hairline over it, so
 * it reads as the page handing over rather than as one more panel in a column of panels.
 *
 * IT CLOSES THE GAP ABOVE THE FOOTER. The sentence this replaces sat inside a band with 64px of
 * bottom padding, above a footer with 64px of top margin and 48px of top padding. That is 176px of
 * empty page between the last words of a route and the first of its footer, and Ralph read it as
 * what it looked like. The footer's margin is gone and the band that holds this row gives up its
 * bottom padding, so the whole separation is the footer's own 48px, which is the target's.
 */
.uc-next {
  display: grid; gap: var(--s2);
  margin-top: var(--s7); padding: var(--s6) 0 0;
  border-top: 1px solid var(--hairline);
  text-decoration: none; color: var(--ink);
}
.uc-next-eyebrow {
  font-size: var(--t-label); font-weight: 600; letter-spacing: 0.22em;
  text-transform: uppercase; color: var(--teal-dark);
}
.uc-next-row { display: flex; align-items: center; gap: var(--s4); }
.uc-next-label {
  font-family: var(--display); font-size: var(--t-h2); font-weight: 600;
  line-height: 1.1; letter-spacing: -0.02em; color: var(--ink);
}
.uc-next-arrow { width: 28px; height: 28px; flex: none; color: var(--teal-dark); transition: transform 180ms ease; }
.uc-next:hover .uc-next-label { color: var(--brand-strong); }
.uc-next:hover .uc-next-arrow { transform: translateX(6px); }
@media (prefers-reduced-motion: reduce) {
  .uc-next-arrow { transition: none; }
  .uc-next:hover .uc-next-arrow { transform: none; }
}

/* THE BAND THAT HOLDS THE HANDOVER GIVES UP ITS BOTTOM PADDING. A band pads itself on both sides
   because it sits between other bands. This one sits against the footer, and the row already draws
   its own rule and its own space above. Stated with :has so the band does not need a second class
   and a view cannot forget to add one. */
.band:has(> .uc-next) { padding-bottom: 0; }

/* ---- src/parts/uc-tile.css ---- */
/* THE TILE: packages/ui/partials/uc-tile.ejs, on /use-cases and /start.
 *
 * WHAT THIS FILE IS. The two additions the tile makes to the home page card. The card itself is
 * .hme-uc in packages/ui/src/parts/hme.css and this file does not restyle it: a tile and a home card
 * are one object, so a change to the home card reaches every tile in the same commit.
 *
 * WHAT IT ADDS.
 *   A heading in two halves. The last half takes the card's hue, which is how the use cases index
 *   sets a buyer's situation and then the buyer's question.
 *   The stage chips. They name the stages a scenario exercises, in the card's hue, and they are
 *   identity rather than state: a chip says which stage, never whether it passed.
 *
 * WHAT IT REFUSES. A state colour, a teal fill and a rule inside the card, for the reasons
 * packages/ui/src/parts/use-cases.css gives for the cards it used to draw.
 */
.ut-line { display: block; }
.ut-accent { color: var(--hue); }
/* `fit: true` ON THE PARTIAL. A question in two halves runs longer than a home card title, so the
   heading drops the home card's fixed two line height and follows its words. The home page passes
   no `fit`, so its seven cards keep the fixed height that starts every title on one baseline. */
.ut-fit .hme-uc-t { min-height: 0; }
/* The eyebrow on a grid tile sits on the arrow's row, so it takes the heading's right pad. At 390
   the longest one, "Fastest answer, 30 seconds", ran under the arrow without it. A wide tile keeps
   its arrow over the figure column, so its eyebrow needs no pad. */
.ut:not(.hme-uc-wide) .hme-uc-e { padding-right: 44px; }
.ut-copy { display: grid; }
.ut-copy > * { min-width: 0; }

.ut-stages { margin: var(--s4) 0 0; display: flex; flex-wrap: wrap; gap: var(--s2); }
.ut-stage {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 14px; line-height: 1; font-weight: 600;
  color: var(--hue);
  border: 1px solid color-mix(in srgb, var(--hue) 55%, transparent); border-radius: var(--pill);
  padding: 5px 10px 5px 8px;
}
.ut-stage::before { content: ""; width: 6px; height: 6px; flex: none; border-radius: var(--pill); background: var(--hue); }

/* ---- src/parts/uce.css ---- */
/* THE EVIDENCE COMPANION, apps/site/src/views/uc-evidence.ejs, on seven routes.
 *
 * WHAT THIS FILE IS. The whole of one page family, built on the interior page recipe the nine
 * ported routes share. There is no reference page for an evidence companion in the reference build,
 * so nothing here is copied from a screenshot of one. Every measure below is taken from
 * packages/ui/src/parts/arch-page.css, which measures /architecture off the running reference at
 * 1440, and from packages/ui/src/parts/ev-page.css, which measures /evidence off the same build.
 * Where the two agree, that is the number.
 *
 * THE NUMBERS, AND WHERE EACH COMES FROM.
 *   The measure is 1036, which is the reference's max-w-[1100px] px-8. It is already set on
 *     .uce-page in ev-page.css and this file does not restate it.
 *   Head padding 56, which is the reference's pt-14 and /architecture's .arc-top.
 *   Eyebrow 13px on 0.28em in the reference; 14px here, because the floor is a readability rule.
 *   Statement clamp(32px, 3.9vw, 56px) on 1.05 and -0.03em in an 880px measure, /architecture's.
 *   Lead 17px on 1.6 in a 640px measure, in --ink-lead, /architecture's.
 *   The tray: radius 12, padding 6, a hairline edge on --paper-alt. /architecture's control tray
 *     and /evidence's count strip are the same object at the same numbers.
 *   The two column grid: 40px gutter, minmax(0, 1fr) on both tracks.
 *   A card: padding 24, radius 16, a hairline edge on --white, 16px between cards, a 32px glyph
 *     16px from the words, a 17px/700 title and a 14px second line.
 *   A table: radius 12 on --paper-alt, a 14px/600 head on 12 by 20, rows of 10 by 20.
 *   The closing panel: radius 16, padding 32, a 1fr and 320px split on a 32px gutter.
 *
 * WHAT IT REFUSES TO DRAW.
 *   Green anywhere but on an Observed mark. The evidence chip carries its own colour from
 *     packages/ui/src/parts/ev.css and nothing here paints a claim card by its status. A card that
 *     went green would be the page saying the claim is proved before the reader has opened it.
 *   A tick, a pulse or a "valid" badge beside an artefact. The reference's evidence page draws a
 *     green "Valid signature" pill over its code block. This page verifies no signature: it fetches
 *     an artefact and decodes it. The panel says what it did instead, in _raw.ejs's own words.
 *   A second face. Space Grotesk is gone from every page and --display resolves to the same stack
 *     as --sans, so nothing here names a family.
 *
 * EVERY SELECTOR STARTS .uce- AND SITS UNDER .uce-page. Two views write that class: this page's
 * own and apps/site/src/views/platform-needs-evidence.ejs, which is another agent's file and uses
 * five of these classes, .uce-page, .uce-head, .uce-headline, .uce-lead and .uce-back. Those five
 * are kept and restyled so the two companions read as one design. Everything else added here is
 * written by this page alone.
 *
 * WHAT HAPPENS AT 1000, AT 760 AND AT 430. The instrument drops to one column and the claims become
 * a horizontal strip. The closing panel drops its second column under the first. The head's tray
 * wraps. Every grid track is minmax(0, 1fr), so a long claim name cannot push a track past the
 * viewport.
 * ================================================================ */

/* ================================================================
   The head.
   ================================================================ */

.uce-top { position: relative; padding-block: 56px 0; border-top: 0; }
.uce-top > * { position: relative; z-index: 1; }
/* THE AMBIENT POOL, AND position IS RESTATED RATHER THAN INHERITED. .rw-glow is the reference's
   fifth treatment and carries its own geometry, including position: absolute. The rule above it
   here weighs the same and packages/ui/src/parts/uce.css is read after rw.css, so without this
   restatement the pool loses and becomes a relatively positioned inline span, on which width and
   height do not apply. Measured in Chrome at 1440 before this line: 0 by 0, and the head drew no
   pool at all. z-index 0 keeps it under the words, which the rule above would otherwise lift to 1.
   The same defect and the same repair as .evx-hero-glow in ev-page.css. */
.uce-glow { position: absolute; z-index: 0; }
/* THE BANDS UNDER THE HEAD TAKE A STACKING POSITION. The pool is 420px tall on a 120px blur and
   reaches about 80px past the head. A positioned element paints over the content of a later static
   sibling, so without this the pool would tint the top of the worked example. */
.uce-band { position: relative; z-index: 1; }
.uce-copy { text-align: center; }

/* THE EYEBROW IS TWO WORDS WITH A RULE BETWEEN THEM: the section, then the subject of the page in
   the brand colour. /architecture draws the same pair.

   IT CARRIES NO TRACKING OF ITS OWN, AND THAT IS MEASURED RATHER THAN CHOSEN. The reference sets
   0.28em on the eyebrow of all three section routes it draws, and packages/ui/src/parts/arch-page.css
   asks for that number on .arc-eyebrow. It does not get it: `.eyebrow` in apps/site/src/public/
   site.css pins 0.14em, site.css is linked after ui.css in _head.ejs, and the two selectors weigh
   the same, so the later sheet wins. Measured in Chrome at 1440: /architecture renders 1.96px of
   tracking on a 14px eyebrow, which is 0.14em. Writing 0.28em here would render 0.14em as well, and
   a rule that changes nothing but reads as a difference is worse than no rule. Raising the
   specificity to beat site.css would make this the one eyebrow on the site with its own tracking.
   Both ported routes and this one now render the same eyebrow, which is the point. */
.uce-eyebrow { margin: 0; }
.uce-eyebrow-rule { margin: 0 var(--s2); color: var(--ink-2); }
.uce-eyebrow-accent { color: var(--teal-dark); }

/* THE STATEMENT. Balanced on both blocks, because these headlines run to two and three lines at
   1440 where the reference's own fits on one. The accent is a slice of the same string rather than
   a second copy of the words, so there is nothing here that can disagree with the head. */
.uce-page .uce-statement {
  margin: var(--s4) auto 0;
  max-width: 880px;
  font-size: clamp(32px, 3.9vw, 56px);
  line-height: 1.05;
  letter-spacing: -0.03em;
  text-wrap: balance;
}
.uce-page .uce-statement .accent { text-wrap: balance; }

/* THE FOUR SHARED RULES, LEFT AS THEY WERE, AND THAT IS DELIBERATE.
 *
 * apps/site/src/views/platform-needs-evidence.ejs writes .uce-head, .uce-headline, .uce-lead and
 * .uce-back on the companion at /how-it-works/evidence. That view belongs to another agent and is
 * part way through a rebuild of its own, so restyling those four here would half redress a page
 * nobody asked me to touch: measured at 1440 with the centred head applied to it, its eyebrow sat
 * left of a centred headline and its back link sat centred over a full width band rule.
 *
 * So the four keep their values and every rule this page adds is scoped under .uce-copy, which only
 * this view writes. When that companion is rebuilt it can take .uce-top and .uce-copy and inherit
 * the whole head in one line.
 */
.uce-page .uce-head { padding-bottom: var(--s6); }
.uce-headline { margin: var(--s3) 0 0; max-width: 22ch; }
.uce-lead { margin: var(--s4) 0 0; font-size: var(--t-body); color: var(--ink-2); }
.uce-back { margin: var(--s5) 0 0; }

/* --ink-lead IS THE COLOUR OF A LEAD, one step above secondary text. The reference sets #aebdd2 on
   every lead it draws, and before this token existed every builder reached for --ink-2, two steps
   down, which made a lead read as a caption. */
.uce-copy .uce-lead {
  margin: 20px auto 0;
  max-width: 640px;
  font-size: var(--t-body); line-height: 1.6;
  color: var(--ink-lead);
  text-wrap: pretty;
}

/* ---- The three figures, in the tray /architecture puts its controls in --------------------------
   THE CELLS ARE NOT SWITCHES AND MUST NOT LOOK LIKE ONE. The reference fills the current cell of a
   control tray and leaves the rest bare, which is how a reader knows it is a position. Nothing here
   is current, so every cell is drawn the same and none carries a ground.

   THE FIGURE IS --t-h1 AND NOT --t-figure. At 1440 --t-figure resolves to 40px, and three of them
   under a 56px statement inverts the two. */
.uce-counts {
  list-style: none;
  margin: var(--s6) auto 0;
  padding: 6px;
  display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s2);
  width: fit-content; max-width: 100%;
  border: 1px solid var(--hairline);
  border-radius: 12px;
  background: var(--paper-alt);
}
.uce-count {
  display: grid; justify-items: center; gap: var(--s1);
  padding: var(--s4) var(--s5);
  border-radius: 8px;
  min-width: 0;
}
.uce-count-value {
  font-size: var(--t-h1); line-height: var(--t-h1-line);
  font-weight: var(--t-h1-weight); letter-spacing: var(--t-h1-tracking);
  color: var(--ink);
}
.uce-count-label {
  font-size: var(--t-label); line-height: 1.4;
  text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--ink-2);
  text-wrap: pretty;
}

/* THE WAY BACK, AND IT IS TWO LINKS RATHER THAN ONE. A reader who came to check one claim wants the
   claim, and a reader who arrived from a search wants the index of all of them. */
.uce-copy .uce-back {
  margin: var(--s6) 0 0;
  display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s5);
}

/* The one link shape on this page, and it is the arrow every other route draws. */
.uce-link {
  display: inline-flex; align-items: center; gap: var(--s2);
  min-height: 24px;
  font-size: var(--t-label); line-height: 1.4;
  color: var(--teal-dark); text-decoration: none;
}
.uce-link::before {
  content: ""; display: block;
  width: 16px; height: 11px; flex: none;
  background: currentColor;
  -webkit-mask: var(--arrow-right) center / contain no-repeat;
  mask: var(--arrow-right) center / contain no-repeat;
}
.uce-link:hover { text-decoration: underline; text-underline-offset: 0.14em; }

/* ================================================================
   The band rhythm.
   ================================================================ */

/* THE REFERENCE DRAWS NO RULE BETWEEN SECTIONS. Every section on the three routes it draws is
   spacing alone: pt-12 and pt-16, no border. The site rule gives every band a --rule top edge and
   64 on both sides, so two adjacent bands opened 128 apart and cut the page into filed sections. */
.uce-band { border-top: 0; padding-block: var(--s8) 0; }
.uce-band-head { margin-bottom: var(--s5); }
.uce-h {
  margin: 0;
  font-size: 30px; line-height: 1.2;
  font-weight: var(--t-h1-weight); letter-spacing: var(--t-h1-tracking);
  color: var(--ink);
}
/* THE LINE UNDER A SECTION HEADING IS THE REFERENCE'S 15px MUTED SUB, NOT A 17px LEAD. Both of its
   section headings carry `mt-2 text-[15px] text-[#8ea3bd]`. At body size in primary ink it reads as
   a second headline. */
.uce-sub {
  margin: var(--s2) 0 0;
  max-width: 76ch;
  font-size: var(--t-small); line-height: var(--t-small-line);
  color: var(--ink-2);
}

/* THE WORKED EXAMPLE WITH NO FIGURE TAKES ONE COLUMN, and this is a fix by styling rather than by
   markup because packages/ui/partials/uc-example.ejs belongs to another agent. It lays its body out
   in two columns and draws the second only when the content file names a partial for it.
   /use-cases/across-the-boundary declares an example with no figure, so at 1440 the panel ran its
   text to 501px and left 436px of empty ground beside it. Measured on the served page. The selector
   asks whether the figure holds an ELEMENT rather than whether it is empty, because EJS leaves the
   newlines around the slot inside it and :empty would never match. */
.uce-page .sc-example-body:has(> .sc-example-figure:not(:has(*))) { grid-template-columns: minmax(0, 1fr); }

/* ================================================================
   The instrument: the claims beside one panel.
   ================================================================ */

/* 380px IS THE CLAIM COLUMN AND THE REST IS THE PANEL, which is not /architecture's even split and
   the reason is what each column holds. There the left column is three cards of prose and the right
   is the detail. Here the left column is a picker whose longest label is a capability name, and the
   right column carries an artefact url at 14px mono. Measured on the served markup at 1440: the
   longest url on /use-cases/across-the-boundary is 168 characters, and an even split left the panel
   498 wide, which put every command block into a sideways scroll. */
.uce-instrument {
  display: grid;
  grid-template-columns: 380px minmax(0, 1fr);
  gap: 40px;
  align-items: start;
}

/* ONE CLAIM, ONE COLUMN. The view draws no picker when the page carries a single row, so the
   instrument has one child and the 380px track would leave it in the wrong half of the band. */
.uce-instrument[data-one="true"] { grid-template-columns: minmax(0, 1fr); }
/* THE TABLE AND THE ARTEFACT LIST TAKE A MEASURE INSIDE A FULL WIDTH PANEL. A row of this table puts
   its term at the left edge and its value at the right, so across 972px of panel the pair reads as
   two unrelated columns. --read-max is the system's own reading width. The read pane is left alone:
   a request url is one unbroken string and takes every pixel it is given. */
.uce-instrument[data-one="true"] .uce-table,
.uce-instrument[data-one="true"] .uce-artefacts { max-width: var(--read-max); }

.uce-claims { display: flex; flex-direction: column; gap: var(--s4); min-width: 0; }

.uce-claim {
  display: flex; align-items: flex-start; gap: var(--s4);
  width: 100%;
  margin: 0;
  padding: var(--s5);
  text-align: left;
  font: inherit;
  border: 1px solid var(--hairline);
  border-radius: 16px;
  background: var(--white);
  cursor: pointer;
  transition: border-color var(--m-drawer) ease, background-color var(--m-drawer) ease;
}
.uce-claim:hover { border-color: var(--rule); }
/* THE ONE LIT CARD, and it is lit for being CURRENT rather than for being proved. The evidence chip
   on its face carries the status and nothing else on the card repeats it. The mixes are in a border
   and a shadow, where no text lands, so every ground under text stays a plain token the contrast
   tool can name. */
.uce-claim[aria-selected="true"] {
  background: var(--wash-teal);
  border-color: color-mix(in srgb, var(--teal-dark) 55%, transparent);
  box-shadow: 0 0 40px color-mix(in srgb, var(--teal-mid) 40%, transparent);
}
.uce-claim:focus-visible { outline: 2px solid var(--teal-dark); outline-offset: 2px; }

/* --teal-dark, NOT --teal, AND THE RULE IS THE VOCABULARY RATHER THAN A PREFERENCE.
   packages/ui/tests/stylesheet.test.ts reserves var(--teal) for a selector that declares
   data-treat="product": brand teal fills a Raidiam product marker and nothing else. */
.uce-claim-icon { flex: none; color: var(--teal-dark); display: inline-flex; }
.uce-claim-icon .sc-glyph { display: inline-flex; }
.uce-claim-icon svg { width: 32px; height: 32px; }
.uce-claim-body { display: grid; gap: var(--s1); min-width: 0; }
.uce-claim-t { font-size: 17px; font-weight: 700; line-height: 1.3; color: var(--ink); }
.uce-claim-s { font-size: var(--t-label); line-height: 1.45; color: var(--ink-2); }
.uce-claim-mark { margin-top: var(--s2); }

/* ---- The panel --------------------------------------------------------------------------------
   The reference's own: a rounded bordered card whose header is divided from the body by a rule that
   reaches both edges. The header pulls its margin back by the panel's padding and restores it as
   padding, so the rule reaches the edge and the words do not move. */
.uce-panels { min-width: 0; }
.uce-panel {
  border: 1px solid var(--hairline);
  border-radius: 16px;
  background: var(--paper-alt);
  padding: var(--s5);
  min-width: 0;
}
.uce-panel-head {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s3);
  margin: calc(-1 * var(--s5)) calc(-1 * var(--s5)) 0;
  padding: var(--s5);
  border-bottom: 1px solid var(--hairline);
}
.uce-panel-t {
  margin: 0;
  font-size: 22px; line-height: 1.25;
  font-weight: var(--t-h2-weight); letter-spacing: var(--t-h2-tracking);
  color: var(--ink);
}
/* THE SENTENCE IS THE DEFAULT VIEW OF EVERY ARTEFACT ON THIS PAGE, which is the whole rule this
   rebuild implements. It reads at body size in --ink-lead: one step under the title, well above the
   table rows under it, and never behind a press. */
.uce-proves {
  margin: var(--s5) 0 0;
  max-width: 66ch;
  font-size: 16px; line-height: 1.55;
  color: var(--ink-lead);
}

/* ---- The view tabs ----------------------------------------------------------------------------
   The reference sets its view tabs in one row with the current one filled and the rest carrying no
   ground, at rounded-md rather than as pills. It draws no pill switch anywhere on its evidence
   route, so neither does this page: one kind of switch, met three times. */
.uce-views { display: flex; flex-wrap: wrap; gap: var(--s2); margin-top: var(--s5); }
.uce-view-tab {
  border: 0;
  border-radius: 8px;
  padding: var(--s2) var(--s4);
  min-height: 36px;
  font: inherit;
  font-size: var(--t-label); font-weight: 500; line-height: 1.5;
  color: var(--ink-nav); background: transparent;
  cursor: pointer;
  transition: color var(--m-drawer) ease, background-color var(--m-drawer) ease;
}
.uce-view-tab:hover { color: var(--ink); }
.uce-view-tab[aria-selected="true"] { background: var(--wash-teal); color: var(--teal-dark); font-weight: 600; }
.uce-view-tab:focus-visible { outline: 2px solid var(--teal-dark); outline-offset: 2px; }
.uce-view { margin-top: var(--s5); min-width: 0; }

/* ---- The labelled table -----------------------------------------------------------------------
   Four terms and four values inside one rounded boundary, striped, which is the shape the reference
   prints a decoded artefact in. It sits on --white rather than on --paper-alt because the panel
   around it is already --paper-alt and a table the same colour as its panel reads as loose text. */
.uce-table {
  margin: 0;
  border: 1px solid var(--hairline);
  border-radius: 12px;
  background: var(--white);
  overflow: hidden;
}
.uce-table-row {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--s4);
  padding: 10px 20px;
}
.uce-table-row + .uce-table-row { border-top: 1px solid var(--hairline); }
.uce-table-row dt { font-size: var(--t-label); line-height: 1.5; color: var(--ink-2); }
/* --ink-row IS THE COLOUR OF A VALUE beside a dimmer label, which is what every row here is. */
.uce-table-row dd { margin: 0; font-size: var(--t-label); font-weight: 500; line-height: 1.5; color: var(--ink-row); text-align: right; }

.uce-more { margin: 20px 0 0; }

/* ---- The artefacts ----------------------------------------------------------------------------
   One artefact per row: its name as the link, the date it was read on the wire and the note the
   matrix carries under it. Nothing is dropped from what the claim row declares. */
.uce-artefacts { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s3); }
.uce-artefact {
  padding: var(--s4) 20px;
  border: 1px solid var(--hairline);
  border-radius: 12px;
  background: var(--white);
  min-width: 0;
}
.uce-artefact-t { margin: 0; font-size: var(--t-label); line-height: 1.45; overflow-wrap: anywhere; }
/* 24px MINIMUM, because the artefact name is one link with no other text on its line. Neither
   exemption in WCAG 2.2 clause 2.5.8 applies: the link is not inside a sentence, and the rows sit
   12px apart so the 24px circles would intersect. The same fix and the same reason as
   `.arc-explore-item a` in arch-page.css. */
.uce-artefact-t a { display: inline-flex; align-items: center; min-height: 24px; color: var(--teal-dark); }
.uce-artefact-n { margin: var(--s2) 0 0; font-size: var(--t-label); line-height: 1.5; color: var(--ink-2); }

/* The live read keeps the whole of _raw.ejs's shape, because the command block, the control and the
   answer are one mechanism and apps/site/src/public/site.js drives them by their data attributes.
   Only the spacing is stated here. */
.uce-view-raw .raw-get + .raw-get { margin-top: var(--s5); padding-top: var(--s5); border-top: 1px solid var(--hairline); }

/* The sentence the content file writes about the reads is _raw.ejs's own intro slot, at the head of
   the read pane. It reads at the size of a note rather than at body size, because the request under
   it is the thing on the pane. */
.uce-view-raw > .flow > p:first-child {
  margin-top: 0;
  max-width: 76ch;
  font-size: var(--t-small); line-height: var(--t-small-line);
  color: var(--ink-2);
}

/* ---- The page with no claim -------------------------------------------------------------------
   One of the six is named by no row in the capability matrix. It gets a panel that says so and the
   sentence _raw.ejs writes for a page with no declared read, rather than an empty instrument. */
.uce-empty {
  padding: var(--s6);
  border: 1px solid var(--hairline);
  border-radius: 16px;
  background: var(--paper-alt);
}
.uce-empty-line { margin: 0 0 var(--s4); max-width: 66ch; font-size: 16px; line-height: 1.55; color: var(--ink-lead); }
.uce-empty .measure { color: var(--ink-2); font-size: var(--t-small); line-height: var(--t-small-line); }

/* ================================================================
   The working: a list of closed drawers.
   ================================================================ */

/* ONE PANEL HOLDING A COLUMN OF DRAWERS. It used to be a tray of three tabs with the first reading
   open under it. Batch 2 closed every reading, so the band's face is the names of the readings and
   nothing else: a reader opens the one they came for. The panel is the same object the claim set
   above draws, so the two bands read as one page. */
.uce-drawers {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  padding: var(--s2) var(--s5);
  border: 1px solid var(--hairline);
  border-radius: 16px;
  background: var(--paper-alt);
  min-width: 0;
}
.uce-drawers > .drawer,
.uce-drawers > div > .drawer { max-width: none; margin: 0; border: 0; }
/* EVERY ITEM MAY SHRINK BELOW ITS CONTENT. A grid item's minimum is its content by default, and one
   reading on /use-cases/find-and-trust/evidence holds a 752px table: opened at 390 it widened the
   page to 772px. Measured by review, 29 September 2026. */
.uce-drawers > * { min-width: 0; }
/* The reading's name is an h3 inside the summary, set at the summary's own size. */
.uce-reading-h { margin: 0; font: inherit; color: inherit; letter-spacing: normal; }
.uce-lead-in { margin-bottom: var(--s3); }
/* A NOT OBSERVED CLAIM LIFTED OUT OF ITS READING, on the face above the drawer it came from. */
.uce-kept { padding: var(--s3) 0; }
.uce-kept > p { margin: 0; color: var(--ink-lead); }
.uce-anchor { position: absolute; top: 0; }
.uce-drawers > * + * { border-top: 1px solid var(--hairline); }

/* The rest of a claim's statement, in its drawer under the first sentence. */
.uce-proves-rest { margin: 0; max-width: 66ch; font-size: 16px; line-height: 1.55; color: var(--ink-lead); }
.uce-panel .drawer { margin-top: var(--s3); max-width: none; }

/* THE READING MEASURE IS 72ch AND NOT THE PAGE. A layer is continuous prose and the band is 1036
   wide, which is about 118 characters at body size: about twice what a reader tracks comfortably. */
.uce-read { max-width: 72ch; }
.uce-read > p { color: var(--ink-lead); }
.uce-read > h3 { color: var(--ink); }

/* ================================================================
   The hosts, and the closing panel.
   ================================================================ */

/* A rule over this band and none between any other two, which is the one rule the reference draws
   on its evidence route: a soft line over the closing row. */
.uce-hosts-in {
  border-top: 1px solid var(--hairline);
  padding-top: 40px;
  text-align: center;
}
.uce-payoff-h {
  margin: 0;
  font-size: 30px; line-height: 1.2;
  font-weight: var(--t-h1-weight); letter-spacing: var(--t-h1-tracking);
  color: var(--ink);
}
.uce-payoff-sub {
  margin: var(--s2) 0 0;
  font-size: var(--t-small); line-height: var(--t-small-line);
  color: var(--ink-2);
}
.uce-chips { margin-top: var(--s6); display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s3); }

.uce-close { padding-block: var(--s7) 0; }
.uce-panel-close {
  display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: var(--s6);
  padding: var(--s6);
  border: 1px solid var(--rule);
  border-radius: 16px;
  background: var(--paper-alt);
}
.uce-panel-h {
  margin: 0;
  font-size: 24px; line-height: 1.25;
  font-weight: var(--t-h1-weight); letter-spacing: var(--t-h1-tracking);
  max-width: 24ch;
  color: var(--ink);
}
.uce-panel-line { margin: var(--s2) 0 0; max-width: 44ch; font-size: var(--t-small); line-height: 1.6; color: var(--ink-lead); }
.uce-panel-btn { margin-top: var(--s5); }
.uce-panel-side-h { margin: 0; font-size: var(--t-label); font-weight: 600; line-height: 1.4; color: var(--ink); }
.uce-explore { list-style: none; margin: var(--s4) 0 0; padding: 0; display: grid; gap: var(--s3); }
.uce-explore-item a {
  display: inline-flex; align-items: center; gap: var(--s2);
  min-height: 24px;
  font-size: var(--t-label); line-height: 1.4;
  color: var(--teal-dark); text-decoration: none;
}
.uce-explore-item a::before {
  content: ""; display: block;
  width: 16px; height: 11px; flex: none;
  background: currentColor;
  -webkit-mask: var(--arrow-right) center / contain no-repeat;
  mask: var(--arrow-right) center / contain no-repeat;
}
.uce-explore-item a:hover { text-decoration: underline; text-underline-offset: 0.14em; }

/* A KNOWN LIMITATION, under the instrument on the page that makes the claim. Quiet, and in the
   evidence vocabulary rather than in a warning colour: the three state colours are spoken for and
   this is a fact about the tenant rather than a failure.

   TWO MODES, ONE SENTENCE. packages/ui/partials/uc-limit.ejs carries the reason. The shared rule
   below sets the vocabulary both modes hold to: small text, muted ink, a reading measure, and no
   colour of its own. Each mode then sets its weight in the page and nothing else. */
.uc-limit { font-size: var(--t-small); color: var(--ink-2); }
.uc-limit-line { max-width: 70ch; }

/* INLINE. A footnote to the instrument above it: one row, no rule, no panel, no ground. The
   measured defect it answers is a block 112px tall and 1216px wide standing as the last content on
   two scenario pages, which reads as the page's closing statement rather than as the figure's
   exception. The chip holds its line, so the sentence wraps against the chip rather than under it. */
.uc-limit-inline {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s3);
  margin: var(--s4) 0 0;
}

/* FULL. The evidence companion, where the limitation is the subject. A panel on the page ground
   with a hairline edge and an uppercase tracked head, which is the treatment every other reference
   block on that route already carries. */
.uc-limit-full {
  margin: var(--s5) 0 0; padding: var(--s5);
  border: 1px solid var(--hairline); border-radius: var(--r-2);
  background: var(--paper);
}
.uc-limit-full .uc-limit-head {
  margin: 0 0 var(--s3);
  font-size: var(--t-label); font-weight: 600;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-2);
}
.uc-limit-full .uc-limit-body {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s3);
  margin: 0;
}

/* ================================================================
   The narrow states.
   ================================================================ */

/* THE INSTRUMENT DROPS TO ONE COLUMN AT 1000 rather than at 900, which is arch-page.css's threshold
   and the same reason: the panel carries a table whose term and value need the width to stay on one
   line. Below it the claims become a row of cards that wrap, so the picker keeps its shape rather
   than becoming a tall stack the reader scrolls past to reach the panel. */
@media (max-width: 1000px) {
  .uce-instrument { grid-template-columns: minmax(0, 1fr); gap: var(--s6); }
  .uce-claims { flex-direction: row; flex-wrap: wrap; }
  .uce-claim { width: auto; flex: 1 1 280px; }
}

@media (max-width: 760px) {
  .uce-panel-close { grid-template-columns: minmax(0, 1fr); }
  .uce-table-row { flex-direction: column; align-items: flex-start; gap: var(--s1); }
  .uce-table-row dd { text-align: left; }
}

/* AT 430 THE CLAIM CARDS STOP SHARING A ROW. A 280px flex basis leaves two cards side by side at
   the phone width less two gutters, which breaks a capability name across four lines. */
@media (max-width: 430px) {
  .uce-claim { flex: 1 1 100%; }
  .uce-copy .uce-back { gap: var(--s3); }
  .uce-count { padding: var(--s3) var(--s4); }
}

/* ================================================================
   The figure bands, which a route declares through `evidenceFigures`.
   ================================================================ */

/* A FIGURE BAND OPENS ON ITS NUMBER, then its heading. The number is the band's place in the run of
   figures, in the eyebrow's type, so a reader scrolling a long route knows how far through it they
   are. It is aria-hidden: the heading carries the name, and "zero one" read aloud adds nothing. */
.uce-fig-n {
  margin: 0 0 var(--s2);
  font-size: 14px; line-height: 1.2; font-weight: 600;
  letter-spacing: 0.08em; color: var(--brand-strong);
}
.uce-fig-body { position: relative; }
/* THE WORDS SIT UNDER THE FIGURE AND READ AS ITS CAPTION: one paragraph at the lead's colour in a
   reading measure, then the drawer holding the rest. They never come first. */
.uce-fig-words { margin-top: var(--s5); max-width: 72ch; }
.uce-fig-cap > p { margin: 0; font-size: 16px; line-height: 1.6; color: var(--ink-lead); }
.uce-fig-words > .drawer { margin-top: var(--s4); max-width: none; }
.uce-fig-topic { margin: var(--s5) 0 0; font-size: 17px; line-height: 1.3; color: var(--ink); }
.uce-fig-topic:first-child { margin-top: 0; }

/* ---- src/parts/use-cases.css ---- */
/* The use cases index: apps/site/src/views/journeys.ejs, and the banner shape of
 * partials/journey-card.ejs that the same page renders.
 *
 * WHAT THIS FILE REFUSES TO DRAW. No glyph on a card, because the reference draws four text blocks
 * in one grid and puts a picture on none of them, and a picture on each one competes with the
 * question the card is there to ask. No var(--ok), var(--att) or var(--no) on a card, because those
 * three are the state colours: they say what is TRUE of a thing and they sit beside a word that
 * says so. No var(--teal) fill, because that marker means a Raidiam product and these are six
 * scenarios. No rule inside a card, because the reference divides a heading from its body by size
 * alone.
 *
 * THE SIX CARDS CARRY THE FOUR IDENTITY HUES, one per card, cycling. See section THE HUE CYCLE
 * below for what each hue lands on. An identity hue answers WHICH ONE of a set of peers this is and
 * carries no meaning of its own, which is exactly what frees it to separate six cards that are
 * otherwise the same object six times.
 *
 * WHY THIS IS A PART AND NOT AN EDIT TO src/ui.css. The base sheet carries `.journey-card`, which
 * films.ejs and architecture.ejs still lay out through `.journey-cards`. Those two pages belong to
 * other people this week. So nothing here touches either class: the index draws `.uc-` classes of
 * its own, the base rules stay exactly as the other two views found them, and a conflict between
 * two writers is a conflict rather than a rule that quietly disappears.
 *
 * MEASURED IN THE RUNNING REFERENCE ON 16 SEPTEMBER 2026, with getBoundingClientRect and
 * getComputedStyle on app/use-cases/page.tsx at a 1440 viewport, rather than read off a screenshot.
 * The reference value is on the left and what this file sets is on the right.
 *
 *   the box            max-w-[1536px] px-8, so 1472 of content   1472, the wide family, from .wrap
 *   above the eyebrow  56                                        56
 *   the eyebrow        13px, 600, 0.22em, brand                  14px, the floor, same weight and tracking
 *   the statement      mt 16, 820 wide, 44px / 1.08 / -0.03em    the same, at the site's 54px step
 *   the lead           mt 20, 560 wide, 16px / 1.6, #aebdd2      the same, and #aebdd2 is --ink-lead
 *   the grid           mt 48, two columns, gap 20                the same, one column under 860
 *   a card             28 of padding, radius 14, brand border    28, --r-3 which is 14, same border
 *   the card ground    a vertical gradient between two panels    the same, between --white and --paper-alt
 *   the card label     12px, 600, 0.2em                          14px, the floor, same weight and tracking
 *   the card heading   mt 16, 26px / 1.12 / -0.02em, 700         the same
 *   the card body      mt 16, 15px / 1.55, takes the free height the same, --ink-2 which is #8ea3bd
 *   the card action    mt 24, 14px, 600, brand strong            the same
 *
 * THREE REFERENCE VALUES ARE REFUSED HERE. Its 13px eyebrow and its 12px card label both sit under
 * the 14px floor, which is a readability rule rather than a style choice and which
 * packages/ui/tests/stylesheet.test.ts enforces across the bundle. Its card label colour #7fd8e6 is
 * a fourth cyan this system does not carry, so the label takes --teal-dark, the one accent.
 *
 * CONTRAST. Every ground used here is a token, so every pair is one packages/ui/tools/contrast.mjs
 * already gates by name. The card ground is a gradient between two of them, which is the
 * reference's own treatment, and both ends are gated:
 *   d-ink      on d-card        13.79   the question on a card
 *   d-ink      on d-surface     14.97   the same question over the foot of the gradient
 *   d-ink-lead on d-ground       9.94   the lead under the statement
 *   d-ink-2    on d-card         7.11   the answer, the chips and the key
 *   d-accent   on d-card        10.17   the label and the accented half of a question
 *   d-accent   on d-wash-teal    7.60   the glyph inside the banner's tile
 *   d-ink      on d-wash-teal   12.11   the banner while the pointer is on it
 *   d-rule     on d-card         3.08   a stage chip edge
 * The last is a component boundary, so its floor is the 3 to 1 of WCAG 1.4.11 rather than 4.5.
 */

/* ---- THE HEAD ---- */
/* The band keeps its bottom padding, so the rule over the closing band sits in the gap under the
   comparison banner. With none, the rule ran along the banner's bottom edge and read as a second
   border. */
.uc-top { padding-top: 56px; }
.uc-top .eyebrow { margin-bottom: 0; letter-spacing: 0.22em; }

/* THE STATEMENT TAKES THE SITE'S DISPLAY STEP, WHICH IS 54px AT 1440.
   It was 44px, the reference's own number for this one route, on the reasoning that an index opens
   quieter than the site's first page. Measured across twenty one routes on 16 September 2026, that
   left five different h1 sizes on one site and this page holding the only 44. One display step on
   every page but the home page is the rule now, so the clamp is the shared token and the size
   cannot drift again. It is weight 700, and the second sentence takes the brand the way every
   statement on this site does. */
.uc-title {
  margin: var(--s4) 0 0;
  max-width: 820px;
  font-family: var(--display);
  font-size: var(--t-display);
  line-height: var(--t-display-line);
  letter-spacing: -0.03em;
  font-weight: 700;
  text-wrap: balance;
}
.uc-title .accent { color: var(--teal-dark); }

/* The lead is a rendered markdown section, so a paragraph arrives with its own margin.
   IT TAKES --ink-lead, WHICH IS THE REFERENCE'S #aebdd2 AND IS NEW. Every lead on this site used
   to take --ink-2, two steps down, which set a lead at the weight of a caption. */
.uc-lead { margin-top: 20px; max-width: 560px; color: var(--ink-lead); font-size: 16px; line-height: 1.6; }
.uc-lead > p { margin: 0; }
.uc-lead > p + p { margin-top: var(--s3); }

/* THE READING KEY, IN ONE ROW. The frame line names the condition every scenario shares. The key
   names the six chips. Both used to stack under the lead, which put four paragraphs between the
   masthead and the first card. Side by side they read as a key to the grid, which is what they are.
   They fall to one column under 1000, where two 46 character columns stop fitting. */
/* THE PAIR OF ACTIONS IN THE HEAD. One row, side by side, which the reference treats as a single
   gesture rather than two controls. It wraps rather than stacking at a narrow width, and it sets no
   colour of its own: .btn and .btn-quiet carry the pill. */
.uc-actions { margin-top: var(--s6); display: flex; flex-wrap: wrap; gap: var(--s3); }

.uc-meta {
  margin-top: var(--s6);
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s4) var(--s6);
  max-width: 1040px;
}
@media (max-width: 1000px) { .uc-meta { grid-template-columns: minmax(0, 1fr); } }
.uc-frame, .uc-key { margin: 0; color: var(--ink-2); font-size: var(--t-label); line-height: 1.5; }
.uc-key-verb { color: var(--ink); font-weight: 600; }

/* ---- THE SIX CARDS ----
 *
 * TWO COLUMNS ON A 20px GUTTER, which is the reference's grid. Six cards fall 2, 2 and 2, so no row
 * is left short and the rule that used to stretch an odd last card across both columns is gone: it
 * matched nothing at six and it drew a shape the reference has no counterpart for. A seventh card
 * would sit alone on its row, which is what the reference does with a short row.
 * At 1440 a card is 678 wide, which is the width the 26px heading was drawn for. */
/* The tile grid since 29 September 2026: the home page's grid (.hme-uc-grid) with this page's gap
   above it. The .uc-card rules below still serve partials/journey-card.ejs. */
.uc-tiles { margin-top: var(--s7); }
.uc-cards { margin-top: var(--s7); display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; }
@media (max-width: 860px) { .uc-cards { grid-template-columns: minmax(0, 1fr); } }

/* THE CARD. A vertical gradient panel, a brand border at low alpha, and a 14px radius. This is
   treatment 2 from the reference, and the border is what tells a card that opens a page from a
   panel that only holds text. A colour-mix is allowed in a border and refused in a flat background;
   the ground here is a gradient between two plain tokens, so no mix reaches it. */
.uc-card {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  display: flex; flex-direction: column;
  min-width: 0;
  padding: 28px;
  background: linear-gradient(180deg, var(--white) 0%, var(--paper-alt) 100%);
  border: 1px solid color-mix(in srgb, var(--teal-dark) 20%, transparent);
  border-radius: var(--r-3);
  transition: border-color var(--m-drawer) ease;
}

/* The soft light the reference puts in the top right corner of a card under the pointer. It is a
   gradient, so the mix is allowed, and it is behind everything because the card clips it. */
.uc-card::after {
  content: "";
  /* LAID OUT INSIDE THE CARD AND MOVED WITH NEITHER AN OFFSET NOR A TRANSFORM.
     It used to sit at top and right of minus 24px. The card clips it, so nothing was ever visible
     past the edge and no reader lost anything, but the element's LAYOUT box still ran 24px past the
     content box. tools/redesign/responsive.mjs reads scrollWidth against clientWidth and reported
     every one of the six cards as text cut and unreachable, at all five widths. A tool that reports
     six false cuts per page is a tool the next person stops reading, which is how a real cut gets
     missed.
     AND IT IS NOT A TRANSFORM EITHER. The first attempt kept the element at right 0 and moved it
     with translate(20%, -20%). 20 percent of 120px is 24px, so the overflow came back byte for byte,
     because a transform contributes to scrollable overflow just as a negative offset does. Measured,
     not assumed: the card reported scrollWidth 470 against clientWidth 446 both before and after.
     The circle sits in the corner and the gradient reaches it. */
  position: absolute; top: 0; right: 0;
  width: 120px; height: 120px;
  border-radius: var(--pill);
  background: radial-gradient(circle, color-mix(in srgb, var(--teal-dark) 34%, transparent), transparent 70%);
  opacity: 0;
  z-index: -1;
  pointer-events: none;
  transition: opacity var(--m-drawer) ease;
}
.uc-card:hover::after, .uc-card:focus-within::after { opacity: 1; }

/* THE CARD'S TOP ROW. The reference puts one label here. This puts the label at the left and the
   stages this scenario exercises at the right, because the stages say which part of the capability
   flow the page runs and the reference has no slot for them anywhere. Putting them here leaves the
   four rows the reference draws down the card exactly as it draws them. */
.uc-card-top {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: var(--s3) var(--s4);
  flex-wrap: wrap;
}

/* THE LABEL. Who asks the question, where the reference prints a card number. The sans family on
   0.2em, because the reference sets every uppercase label on the page in one family and one
   tracking. The line wraps rather than truncating: at one column on a phone the longest of the six
   needs more width than the card has, and a label cut off mid word reads as a defect. */
.uc-kicker {
  margin: 0;
  min-width: 0; overflow-wrap: break-word;
  font-size: var(--t-label); line-height: 1.35;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--teal-dark);
}

/* The buyer's question. It is the card's heading and it holds the only anchor. 26px on 1.12 with
   -0.02em tracking is the reference's card heading, three steps above the body under it. The two
   halves are separate lines, and the second one takes the brand, which is the reference's own
   treatment and the strongest thing on its card. A question that carries one sentence renders one
   line and takes no accent. */
.uc-ask {
  margin: var(--s4) 0 0;
  font-size: 26px; line-height: 1.12; letter-spacing: -0.02em; font-weight: 700;
}
.uc-ask-line { display: block; }
/* THE ACCENTED HALF STAYS BRAND ON EVERY CARD, THE REFUSED ONE INCLUDED, and that is a decision
   rather than an oversight. The refused colour marks the card whose SUBJECT is something going
   wrong. Painting the question itself red says the ANSWER is no, and the answer under it is that a
   change lands at each consumer's next read. So the tone shows in the label, the chip and the
   action, and the question is asked in the same colour as the other five. */
.uc-ask-line.accent { color: var(--teal-dark); }
.uc-ask a { color: inherit; text-decoration: none; }
/* The stretched hit area. The whole card is clickable and the keyboard still gets one stop. */
.uc-ask a::before { content: ""; position: absolute; inset: 0; border-radius: var(--r-3); }
.uc-card:hover .uc-ask a, .uc-card:focus-within .uc-ask a { text-decoration: underline; text-underline-offset: 0.14em; }
.uc-sub { margin-top: var(--s2); color: var(--ink-2); font-size: var(--t-small); line-height: var(--t-small-line); }

/* ---- THE ANSWER ----
 *
 * THE ROW THE PANEL ASKED FOR. Four business readers read this page on 16 September 2026 and two
 * scrolled past it: every card asked a question and answered nothing, so a reader left with what
 * they arrived with. This row is the answer, and it is the scenario page's own `statement`, read at
 * render rather than written again on this page.
 *
 * IT IS THE REFERENCE'S BODY SLOT: 15px on 1.55, secondary ink, 16px under the heading, and it
 * takes the free height of the card so the action row sits on the foot of every card in a row at
 * the same height. */
.uc-answer {
  margin: var(--s4) 0 0;
  flex: 1;
  color: var(--ink-2);
  font-size: 15px; line-height: 1.55;
}

/* ---- THE ACTION ROW ----
 *
 * ONE ROW, ONE THING, which is the reference exactly: a single action 24px under the body, at 14px
 * semibold in the bright brand with an arrow that moves on hover. The words are the name of the
 * page the card opens, where the reference writes "View use case" six times. */
.uc-foot { margin: var(--s5) 0 0; }
/* INLINE, NOT FLEX, and that is the fix for a defect this file already recorded once under .uc-go.
   The reference writes "View use case" in every card, which never wraps. This writes the name of
   the page the card opens, and the longest of the six needs two lines inside a 350px card. As a
   flex row the arrow is a flex item, so it leaves the words behind and sits alone at the right hand
   edge. Inline, it follows the last word wherever that word lands. Measured at 390 wide: the foot
   reported 307 against a 292 box as a flex row and reports no overflow inline. */
.uc-open {
  display: inline-block;
  font-size: var(--t-label); font-weight: 600; line-height: 1.4;
  color: var(--brand-strong);
}
.uc-open::after {
  content: ""; display: inline-block; vertical-align: -1px;
  width: 16px; height: 11px; margin-left: var(--s2);
  background: currentColor;
  -webkit-mask: var(--arrow-right) center / contain no-repeat;
  mask: var(--arrow-right) center / contain no-repeat;
  transition: transform var(--m-drawer) ease;
}
.uc-card:hover .uc-open::after, .uc-card:focus-within .uc-open::after { transform: translateX(3px); }

/* THE STAGE CHIPS. They sit at the right of the card's top row. partials/journey-card.ejs draws the
   same chips in the same classes, so one set of rules serves both. */
.uc-stages { margin: 0; display: flex; flex-wrap: wrap; gap: var(--s2); }
.uc-stage {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--t-label); line-height: 1; font-weight: var(--t-label-weight);
  color: var(--ink-2);
  border: 1px solid var(--rule); border-radius: var(--pill);
  padding: 5px 10px 5px 8px;
}
.uc-stage::before { content: ""; width: 6px; height: 6px; flex: none; border-radius: var(--pill); background: var(--teal-dark); }

.uc-card:hover, .uc-card:focus-within { border-color: color-mix(in srgb, var(--teal-dark) 50%, transparent); }

/* ---- THE HUE CYCLE ----
 *
 * WHAT IT IS. One rule set that gives every card in the grid one of the four identity hues and puts
 * it in five places on that card: the top edge, the label, the accented half of the question, the
 * stage chips and the action. The top edge is the reference's own card treatment, a hairline panel
 * lit from above by its own colour, and the four places under it are what makes the colour read as
 * the card's rather than as an edge somebody drew.
 *
 * WHY A CARD NEEDS ONE AT ALL. Measured across twenty one routes at 1440 on 16 September 2026, this
 * page drew ZERO of the four identity hues, and twelve routes drew none. Ralph: "the entire site has
 * gone blue monocromatic". Six cards in one grid, in one colour, in the same four rows, read as one
 * object repeated six times, and a reader scanning for their own question has nothing to scan by.
 *
 * IT IS POSITIONAL AND IT LIVES IN THE STYLESHEET. A card takes its hue from where it sits in the
 * grid, so a content file cannot pick one and a scenario cannot be tied to a colour. Four hues over
 * six cards repeat at the fifth. The grid is two columns, so the repeat falls UNDER its own hue
 * rather than beside it, and no two touching cards share a colour.
 *
 * WHAT IT REFUSES TO DRAW. A state colour. Green means Observed, amber means in progress and red
 * means refused, each beside the word that says so, and none of the three appears on this page. The
 * card whose subject is a withdrawal used to take var(--no) on its label, its chip dot, its action
 * and its hover edge, which put the refusal colour on the words "Asked by security operations".
 * That is decoration in a colour that carries a meaning, so those four rules are gone and the card
 * runs the cycle with the other five. The answer on its face still says what happens.
 *
 * CONTRAST, computed from packages/ui/tokens/tokens.json with the formula in
 * packages/ui/tools/contrast.mjs. Every one of the four is already gated against the three dark
 * grounds at the 4.5 TEXT floor rather than the 3 of a graphic, so a label, a chip and an action may
 * be set in one. On d-card, the lightest of the three and therefore the one that decides:
 *   d-blue      7.35      d-violet    6.62      d-magenta   10.16      d-sand      10.41
 */
.uc-cards .uc-card { --hue: var(--d-blue); }
.uc-cards .uc-card:nth-child(4n + 2) { --hue: var(--d-violet); }
.uc-cards .uc-card:nth-child(4n + 3) { --hue: var(--d-magenta); }
.uc-cards .uc-card:nth-child(4n + 4) { --hue: var(--d-sand); }

/* The lit edge. The three other sides keep the brand hairline the reference draws, so the card is
   still one of a family and the hue is the light on it rather than a box around it. */
.uc-cards .uc-card {
  border-top-color: var(--hue);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--hue) 35%, transparent);
}
.uc-cards .uc-card:hover, .uc-cards .uc-card:focus-within {
  border-color: color-mix(in srgb, var(--hue) 50%, transparent);
  border-top-color: var(--hue);
}
/* The corner light under the pointer, in the card's own hue rather than in the one brand cyan. */
.uc-cards .uc-card::after { background: radial-gradient(circle, color-mix(in srgb, var(--hue) 30%, transparent), transparent 70%); }
.uc-cards .uc-card .uc-kicker { color: var(--hue); }
.uc-cards .uc-card .uc-ask-line.accent { color: var(--hue); }
.uc-cards .uc-card .uc-open { color: var(--hue); }
/* The stage chips take the card's hue rather than a colour of their own. They name which part of
   the capability flow the scenario exercises, and the stage names are already the words: the colour
   here says which CARD they belong to, which is what keeps a chip row from reading as a verdict. */
.uc-cards .uc-card .uc-stage { border-color: var(--hue); color: var(--hue); }
.uc-cards .uc-card .uc-stage::before { background: var(--hue); }

/* ---- THE TWO ROW SHAPES ----
 *
 * The banner and the wide card are a row rather than a tile, and the reference has no counterpart
 * for either. This page renders the banner; the wide card is drawn by partials/journey-card.ejs and
 * shown in the gallery, and its rules stay here so the gallery keeps drawing it. Both keep the
 * leading glyph they were built with, because a row with nothing at its left edge reads as a stray
 * paragraph, and both keep the foot line that names where they go. */
.uc-icon {
  width: 48px; height: 48px; flex: none;
  display: grid; place-items: center;
  border-radius: var(--r-2);
  border: 1px solid color-mix(in srgb, var(--teal-dark) 55%, transparent);
  background: var(--wash-teal);
  color: var(--teal-dark);
  transition: border-color var(--m-drawer) ease, box-shadow var(--m-drawer) ease;
}
.uc-icon svg { width: 26px; height: 26px; }

/* The foot line: where the row goes. Drawn as a link and, on the wide card, hidden from assistive
   technology, because the anchor above already carries these words.

   BLOCK, NOT FLEX, and that is the fix for a real defect rather than a preference. As a flex row the
   arrow is a flex item, so on a scenario name that runs to two lines it left the words behind and
   sat alone at the right hand edge. Inline, it follows the last word wherever that word lands. */
.uc-go {
  margin-top: auto; padding-top: var(--s3);
  font-size: var(--t-small); font-weight: 600; line-height: var(--t-small-line);
  color: var(--teal-dark);
  text-wrap: balance;
}
.uc-go::after {
  content: ""; display: inline-block; vertical-align: -1px;
  width: 15px; height: 10px; margin-left: var(--s2);
  background: currentColor;
  -webkit-mask: var(--arrow-right) center / contain no-repeat;
  mask: var(--arrow-right) center / contain no-repeat;
  transition: transform var(--m-drawer) ease;
}

/* THE BANNER. One row: the figure glyph, the claim, the action. It links to the before and after
   figure on the home page, which is where that comparison is drawn.

   IT TAKES THE REFERENCE'S PANEL RATHER THAN A SECOND BRAND BORDER. The cards above it carry the
   brand edge, and a banner with the same edge reads as a seventh card. The reference draws a panel
   that is not a card as a plain rule on the band ground, and that is what this is. */
.uc-banner {
  display: flex; align-items: center; gap: var(--s5);
  margin-top: 20px;
  padding: var(--s6);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
  background: var(--paper-alt);
  color: var(--ink); text-decoration: none;
  transition: border-color var(--m-drawer) ease, background-color var(--m-drawer) ease;
}
.uc-banner:hover { border-color: var(--teal-dark); background: var(--wash-teal); }
.uc-banner .uc-banner-body { display: grid; gap: var(--s2); min-width: 0; }
.uc-banner .uc-banner-ask { font-size: var(--t-h3); line-height: var(--t-h3-line); font-weight: var(--t-h3-weight); }
.uc-banner .uc-go { margin: 0; padding: 0; margin-left: auto; white-space: nowrap; }
.uc-banner:hover .uc-go::after { transform: translateX(3px); }
.uc-banner:hover .uc-icon { border-color: var(--teal-dark); box-shadow: 0 0 22px color-mix(in srgb, var(--teal-dark) 24%, transparent); }
@media (max-width: 760px) {
  .uc-banner { flex-wrap: wrap; gap: var(--s4); }
  .uc-banner .uc-go { margin-left: 0; }
}

/* THE WIDE SHAPE. The same card, laid on its side. No page renders it now that the catalogue
   objection is the first card in the grid; the gallery does, so the rules stay. */
.uc-card-wide { flex-direction: row; align-items: center; gap: var(--s5); }
.uc-card-wide .uc-body { display: grid; gap: var(--s3); min-width: 0; }
.uc-card-wide .uc-ask { margin-top: 0; }
.uc-card-wide .uc-sub { margin-top: 0; }
.uc-card-wide .uc-stages { margin-top: 0; padding-top: 0; }
.uc-card-wide .uc-go { margin-top: 0; padding-top: 0; margin-left: auto; white-space: nowrap; }
.uc-card-wide:hover .uc-icon { border-color: var(--teal-dark); box-shadow: 0 0 22px color-mix(in srgb, var(--teal-dark) 24%, transparent); }
.uc-card-wide:hover .uc-go::after { transform: translateX(3px); }
@media (max-width: 760px) {
  .uc-card-wide { flex-direction: column; align-items: stretch; }
  .uc-card-wide .uc-go { margin-left: 0; margin-top: var(--s2); }
}

/* MOTION, AND WHAT THIS BLOCK IS ACTUALLY FOR.
 *
 * The base sheet already clamps every transition and animation on the page to 0.001ms with
 * !important under `prefers-reduced-motion: reduce`, so the fades above stop without help. What it
 * cannot reach is a TRANSFORM applied on :hover. That is not a duration, so it survives the clamp
 * and the arrow still slides. Those are what this block removes, and the transition resets beside
 * them state the intent rather than doing the work.
 *
 * The corner light and the icon's hover glow are deliberately NOT removed. Both appear with no
 * duration, so each is a state a pointer reveals rather than motion, and taking them away would
 * leave the hover affordance on this page weaker than every other page for a reader who asked for
 * less movement.
 *
 * Proved by consequence, not by reading. A probe opens /use-cases with reduced motion emulated,
 * puts the pointer on each card and the banner in turn, confirms the element matches :hover before
 * reading anything, and reads the COMPUTED transform of the element and of its arrow.
 *
 * The :hover guard is not decoration. Without it the probe hovered seven elements in one page, the
 * pointer failed to land on the banner, and the banner reported clean while it was moving. */
@media (prefers-reduced-motion: reduce) {
  .uc-card, .uc-icon, .uc-open::after, .uc-go::after, .uc-banner { transition: none; }
  .uc-card:hover .uc-open::after, .uc-card:focus-within .uc-open::after { transform: none; }
  .uc-card-wide:hover .uc-go::after, .uc-banner:hover .uc-go::after { transform: none; }
}



/* ---- src/parts/wc.css ---- */
/* /use-cases/when-something-changes: the page and its one instrument, packages/ui/partials/wc-reach.ejs.
 *
 * THE TREATMENTS ARE components/diagram-section.tsx's, taken from rw.css by class: the hub, the
 * pedestal and the ambient pool. The time rail is components/use-case/uc06-diagram.tsx's: a hairline
 * with ringed dots that glow. This file places them and draws the rail and the reach.
 *
 * HUE IS IDENTITY. Each row of the reach carries one hue in `--hue`: a recognition, an identity, an
 * artefact, a running copy. THE GREEN ENVIRONMENT HUE IS NOT USED ON THIS FIGURE, because it sits
 * next to --ok and green means Observed on this site.
 *
 * STATE IS STATE, AND ONLY GONE CARRIES A STATE COLOUR. --no appears under data-state="no" beside
 * the word the legend gives it. A node that stays is the lit card with no state colour, so no node
 * on this figure is green.
 */

/* ---- THE PAGE ---- */
.wc-page { --page-max: 1472px; }
.wc-top { position: relative; padding-block: 3.5rem var(--s5); }
.wc-top > * { margin: 0; }
.wc-top .sc-eyebrow { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s3); letter-spacing: 0.22em; color: var(--slate); }
.wc-top .sc-headline { margin-top: var(--s4); line-height: 1.02; letter-spacing: -0.035em; max-width: 22ch; }
.wc-top .sc-headline .accent { display: block; }
.wc-top .sc-lead { margin-top: 1.25rem; max-width: 34rem; font-size: 17px; line-height: 1.55; color: var(--ink-lead); }
.wc-top .sc-actions { margin-top: var(--s5); display: flex; flex-wrap: wrap; gap: var(--s4); }
/* FROM 1100 THE COPY TAKES TWO COLUMNS OVER THE INSTRUMENT, the headline on the left and the lead
   and the actions on the right, which is how the standard page sets its top band at the same width. */
@media (min-width: 1100px) {
  .wc-top { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); column-gap: 4rem; grid-template-areas: "eyebrow eyebrow" "head lead" "head actions"; align-items: start; }
  .wc-top .sc-eyebrow { grid-area: eyebrow; }
  .wc-top .sc-headline { grid-area: head; }
  .wc-top .sc-lead { grid-area: lead; }
  .wc-top .sc-actions { grid-area: actions; }
}

.wc-band { padding-block: var(--s4) var(--s6); }

/* ---- THE OUTCOME ROW, the reference's benefits row: ringed 52px glyphs, hairlines between ---- */
.wc-payoff { padding-block: var(--s6); }
.wc-pays { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); }
.wc-pays li { display: flex; flex-direction: column; align-items: center; text-align: center; padding: 0 var(--s4); }
.wc-pays li + li { border-left: 1px solid var(--hairline); }
.wc-pay-i { width: 52px; height: 52px; }
.wc-pay-i svg { width: 26px; height: 26px; }
.wc-pay-t { margin: var(--s4) 0 0; font-size: 18px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.wc-pay-l { margin: var(--s2) 0 0; max-width: 19rem; text-wrap: balance; font-size: 15px; line-height: 1.5; color: var(--ink-2); }
@media (max-width: 900px) {
  .wc-pays { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: var(--s6); }
  .wc-pays li:nth-child(3) { border-left: 0; }
}
@media (max-width: 520px) {
  .wc-pays { grid-template-columns: minmax(0, 1fr); }
  .wc-pays li + li { border-left: 0; border-top: 1px solid var(--hairline); padding-top: var(--s5); }
}

/* ---- THE INSTRUMENT ---- */
.wc { position: relative; margin: 0; }
.wc-glow { top: 40%; width: 1100px; height: 520px; opacity: 0.22; }
.wc-set { position: relative; margin: 0; padding: 0; border: 0; min-width: 0; }

/* The step heads: a ringed number, a verb, and the one line that says what the reader does. */
.wc-step { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px var(--s3); margin: 0 0 var(--s3); }
.wc-n {
  display: inline-flex; align-items: center; justify-content: center; align-self: center;
  width: 28px; height: 28px; border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--teal-dark) 60%, transparent);
  color: var(--brand-strong); font-size: 14px; font-weight: 700;
}
.wc-verb { font-size: 14px; font-weight: 600; letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink); }
.wc-does { font-size: 15px; color: var(--ink-2); }

/* 1. THE PICK. Five tabs in one row wherever they fit. WHERE THEY WRAP, THE LAST ROW STRETCHES, so
   an odd tab takes the full row rather than standing alone at half width and a different height. */
.wc-tabs { display: flex; flex-wrap: wrap; gap: var(--s3); }
.wc-tab {
  flex: 1 1 130px;
  display: flex; align-items: center; gap: var(--s3);
  min-height: 64px; padding: 10px var(--s4);
  border-radius: 12px; cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--ink) 12%, transparent);
  background: linear-gradient(180deg, color-mix(in srgb, var(--paper-alt) 90%, transparent) 0%, color-mix(in srgb, var(--paper) 90%, transparent) 100%);
  transition: border-color 160ms ease, box-shadow 160ms ease;
}
.wc-tab:hover { border-color: color-mix(in srgb, var(--teal-dark) 50%, transparent); }
.wc-tab-i { flex: 0 0 auto; color: var(--ink-2); }
.wc-tab-i svg { width: 24px; height: 24px; display: block; }
.wc-tab-t { display: grid; gap: 2px; min-width: 0; }
.wc-tab-label { font-size: 15px; font-weight: 600; line-height: 1.25; color: var(--ink); }
.wc-tab-act { font-size: 14px; line-height: 1.3; color: var(--ink-2); }

/* 2 AND 3. THE STAGE: the hub on the left, the window and the reach on the right. */
.wc-stage { display: grid; grid-template-columns: minmax(0, 320px) minmax(0, 1fr); gap: var(--s6); margin-top: var(--s6); align-items: start; }
.wc-hub { padding: var(--s5); text-align: center; }
.wc-pubs, .wc-frames, .wc-reads { display: grid; }
.wc-pub, .wc-frame, .wc-read {
  grid-area: 1 / 1;
  visibility: hidden; opacity: 0;
  transition: opacity var(--m-drawer) ease, visibility 0s linear var(--m-drawer);
}
.wc-ped { margin-top: calc(-1 * var(--s3)); }
.wc-pub-label { margin: var(--s3) 0 0; font-size: 20px; line-height: 1.25; font-weight: 700; color: var(--ink); }
.wc-pub-surface { margin: var(--s3) 0 0; font-size: 15px; line-height: 1.5; color: var(--ink-2); text-wrap: balance; }
.wc-pub-who { display: block; margin-bottom: 4px; font-weight: 600; color: var(--brand-strong); }

/* THE FRAME: the window in a column beside the reach. */
.wc-frame { display: grid; grid-template-columns: minmax(0, 260px) minmax(0, 1fr); gap: var(--s5); align-items: start; }

/* THE RAIL, uc06-diagram.tsx's: ringed dots that glow, joined by a hairline. EACH STOP DRAWS THE
   SEGMENT TO THE NEXT ONE, so the line ends at the last dot rather than at the end of the box. */
.wc-rail { position: relative; list-style: none; margin: 0; padding: var(--s2) 0 0 34px; display: grid; gap: var(--s5); }
.wc-stop { position: relative; display: grid; gap: 4px; align-content: start; }
.wc-stop:not(:last-child)::before {
  content: ""; position: absolute; left: -25px; top: 17px; bottom: calc(-1 * var(--s5) - 3px); width: 2px; border-radius: 2px;
  background: linear-gradient(180deg, var(--teal-dark) 0%, color-mix(in srgb, var(--teal-dark) 45%, transparent) 100%);
}
.wc-dot {
  position: absolute; left: -31px; top: 3px; width: 14px; height: 14px; border-radius: 50%;
  border: 2px solid var(--teal-dark); background: var(--paper);
  box-shadow: 0 0 8px color-mix(in srgb, var(--teal-dark) 70%, transparent);
}
.wc-t { font-size: 14px; font-weight: 600; color: var(--brand-strong); }
.wc-stop-l { font-size: 15px; font-weight: 600; color: var(--ink); }
.wc-pub-when, .wc-issued { font-size: 15px; line-height: 1.45; color: var(--ink-2); }
.wc-pub-bound { display: inline-block; margin-top: 2px; font-size: 20px; font-weight: 700; color: var(--brand-strong); }
.wc-issued-n { font-weight: 700; color: var(--ink); white-space: nowrap; }
.wc-outcome { justify-self: start; }
.wc-outcomes-now { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; }
.wc-or, .wc-where { font-size: 14px; color: var(--ink-2); }
/* THE WORST CASE AND THE NOTE, under the rail and inside the frame they qualify. */
.wc-worst, .wc-note { margin: var(--s4) 0 0; padding-top: var(--s3); border-top: 1px solid var(--hairline); font-size: 14px; line-height: 1.5; color: var(--ink-2); }
.wc-note { display: grid; gap: 4px; }

/* THE REACH. Rows lit in their own hue from above, as the reference lights an environment card. */
.wc-tree { display: grid; gap: var(--s2); }
.wc-row { display: grid; grid-template-columns: minmax(0, 8.5em) minmax(0, 1fr); align-items: center; gap: var(--s3); }
.wc-row-label { font-size: 14px; font-weight: 600; color: var(--hue); }
.wc-row-nodes { display: flex; flex-wrap: wrap; gap: var(--s2); }
/* THE NODES SHARE THE ROW, so the reach reads as a lit grid rather than a column of chips with an
   empty half beside it. */
.wc-row-nodes > .wc-node { flex: 1 1 0; min-width: 150px; max-width: 280px; }
.wc-node {
  display: grid; gap: 1px; padding: 7px 12px 8px; border-radius: 10px;
  border: 1px solid color-mix(in srgb, var(--ink) 10%, transparent);
  border-top-color: color-mix(in srgb, var(--hue) 70%, transparent);
  background: linear-gradient(180deg, color-mix(in srgb, var(--paper-alt) 90%, transparent) 0%, color-mix(in srgb, var(--paper) 90%, transparent) 100%);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--hue) 45%, transparent);
}
.wc-node-name { font-size: 14px; font-weight: 600; color: var(--ink); }
.wc-node-sub { font-size: 14px; color: var(--ink-2); }
.wc-node[data-state="no"] { border-color: var(--no); background: var(--wash-no); box-shadow: none; }
.wc-node[data-state="no"] .wc-node-name { text-decoration: line-through; }
/* OUT OF SCOPE IS A DASHED BORDER AND THE SECONDARY INK, NEVER AN OPACITY, so every pair stays one
   the contrast gate can name. */
.wc-node[data-state="out"] { border-style: dashed; border-top-color: var(--rule); box-shadow: none; background: var(--paper); }
.wc-node[data-state="out"] .wc-node-name { font-weight: 400; color: var(--ink-2); }

.wc-legend { list-style: none; display: flex; flex-wrap: wrap; gap: var(--s2) var(--s5); margin: var(--s5) 0 0; padding: var(--s4) 0 0; border-top: 1px solid var(--hairline); }
.wc-legend li { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 2px 6px; font-size: 14px; color: var(--ink-2); }
.wc-legend-word { font-weight: 600; color: var(--ink); }
.wc-legend-dot { width: 12px; height: 12px; border-radius: 4px; border: 1px solid var(--ink-2); }
.wc-legend li[data-state="no"] .wc-legend-dot { border-color: var(--no); background: var(--wash-no); }
.wc-legend li[data-state="out"] .wc-legend-dot { border-style: dashed; }

/* THE READING, under the stage: the scope, its verb, its evidence label, and what keeps running. */
.wc-reads { margin-top: var(--s6); }
.wc-read { border-top: 1px solid var(--hairline); padding-top: var(--s4); }
.wc-read-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2) var(--s3); margin: 0; }
.wc-read-name { font-size: 18px; font-weight: 700; color: var(--ink); }
.wc-read-verb { font-size: 14px; color: var(--ink-2); }
.wc-read-ev { margin-left: auto; }
.wc-keeps { margin: var(--s3) 0 0; font-size: 15px; line-height: 1.5; color: var(--ink); }
.wc-keeps-h { margin-right: var(--s2); font-size: 14px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: var(--slate); }

/* THE CHECKED SCOPE. Written out to five, which is the ceiling wc-reach.ejs refuses to pass. */
.wc-set > .wc-in:nth-of-type(1):checked ~ .wc-stage .wc-pub:nth-of-type(1),
.wc-set > .wc-in:nth-of-type(2):checked ~ .wc-stage .wc-pub:nth-of-type(2),
.wc-set > .wc-in:nth-of-type(3):checked ~ .wc-stage .wc-pub:nth-of-type(3),
.wc-set > .wc-in:nth-of-type(4):checked ~ .wc-stage .wc-pub:nth-of-type(4),
.wc-set > .wc-in:nth-of-type(5):checked ~ .wc-stage .wc-pub:nth-of-type(5),
.wc-set > .wc-in:nth-of-type(1):checked ~ .wc-stage .wc-frame:nth-of-type(1),
.wc-set > .wc-in:nth-of-type(2):checked ~ .wc-stage .wc-frame:nth-of-type(2),
.wc-set > .wc-in:nth-of-type(3):checked ~ .wc-stage .wc-frame:nth-of-type(3),
.wc-set > .wc-in:nth-of-type(4):checked ~ .wc-stage .wc-frame:nth-of-type(4),
.wc-set > .wc-in:nth-of-type(5):checked ~ .wc-stage .wc-frame:nth-of-type(5),
.wc-set > .wc-in:nth-of-type(1):checked ~ .wc-reads .wc-read:nth-of-type(1),
.wc-set > .wc-in:nth-of-type(2):checked ~ .wc-reads .wc-read:nth-of-type(2),
.wc-set > .wc-in:nth-of-type(3):checked ~ .wc-reads .wc-read:nth-of-type(3),
.wc-set > .wc-in:nth-of-type(4):checked ~ .wc-reads .wc-read:nth-of-type(4),
.wc-set > .wc-in:nth-of-type(5):checked ~ .wc-reads .wc-read:nth-of-type(5) { visibility: visible; opacity: 1; transition-delay: 0s; }

.wc-set > .wc-in:nth-of-type(1):checked ~ .wc-pick .wc-tab:nth-of-type(1),
.wc-set > .wc-in:nth-of-type(2):checked ~ .wc-pick .wc-tab:nth-of-type(2),
.wc-set > .wc-in:nth-of-type(3):checked ~ .wc-pick .wc-tab:nth-of-type(3),
.wc-set > .wc-in:nth-of-type(4):checked ~ .wc-pick .wc-tab:nth-of-type(4),
.wc-set > .wc-in:nth-of-type(5):checked ~ .wc-pick .wc-tab:nth-of-type(5) {
  border-color: var(--teal-dark);
  background: radial-gradient(120% 120% at 50% 0%, color-mix(in srgb, var(--teal-mid) 35%, transparent) 0%, color-mix(in srgb, var(--paper) 92%, transparent) 70%);
  box-shadow: 0 0 24px color-mix(in srgb, var(--teal-dark) 22%, transparent), inset 0 1px 0 color-mix(in srgb, var(--brand-strong) 40%, transparent);
}
.wc-set > .wc-in:nth-of-type(1):checked ~ .wc-pick .wc-tab:nth-of-type(1) .wc-tab-i,
.wc-set > .wc-in:nth-of-type(2):checked ~ .wc-pick .wc-tab:nth-of-type(2) .wc-tab-i,
.wc-set > .wc-in:nth-of-type(3):checked ~ .wc-pick .wc-tab:nth-of-type(3) .wc-tab-i,
.wc-set > .wc-in:nth-of-type(4):checked ~ .wc-pick .wc-tab:nth-of-type(4) .wc-tab-i,
.wc-set > .wc-in:nth-of-type(5):checked ~ .wc-pick .wc-tab:nth-of-type(5) .wc-tab-i { color: var(--brand-strong); }

/* THE FOCUS RING goes on the label the radio stands for, because the radio itself is hidden. */
.wc-set > .wc-in:nth-of-type(1):focus-visible ~ .wc-pick .wc-tab:nth-of-type(1),
.wc-set > .wc-in:nth-of-type(2):focus-visible ~ .wc-pick .wc-tab:nth-of-type(2),
.wc-set > .wc-in:nth-of-type(3):focus-visible ~ .wc-pick .wc-tab:nth-of-type(3),
.wc-set > .wc-in:nth-of-type(4):focus-visible ~ .wc-pick .wc-tab:nth-of-type(4),
.wc-set > .wc-in:nth-of-type(5):focus-visible ~ .wc-pick .wc-tab:nth-of-type(5) {
  outline: 2px solid var(--focus-ring); outline-offset: 3px; box-shadow: var(--focus-halo);
}

/* THE MOTION. The four stops light in turn in the frame in view, and each gone node flashes once
   when the third stop, the next request, lights. The selector starts to match when a scope is
   chosen, so the run restarts on every choice. Every word and every final state is on screen
   before, during and after. The delay is set per stop below, so the chain sets no delay. */
.wc-set > .wc-in:nth-of-type(1):checked ~ .wc-stage .wc-frame:nth-of-type(1) .wc-dot,
.wc-set > .wc-in:nth-of-type(2):checked ~ .wc-stage .wc-frame:nth-of-type(2) .wc-dot,
.wc-set > .wc-in:nth-of-type(3):checked ~ .wc-stage .wc-frame:nth-of-type(3) .wc-dot,
.wc-set > .wc-in:nth-of-type(4):checked ~ .wc-stage .wc-frame:nth-of-type(4) .wc-dot,
.wc-set > .wc-in:nth-of-type(5):checked ~ .wc-stage .wc-frame:nth-of-type(5) .wc-dot { animation-name: wc-lit; animation-duration: 0.7s; animation-timing-function: ease-out; animation-fill-mode: both; }
.wc-set > .wc-in:nth-of-type(1):checked ~ .wc-stage .wc-frame:nth-of-type(1) .wc-node[data-state="no"],
.wc-set > .wc-in:nth-of-type(2):checked ~ .wc-stage .wc-frame:nth-of-type(2) .wc-node[data-state="no"],
.wc-set > .wc-in:nth-of-type(3):checked ~ .wc-stage .wc-frame:nth-of-type(3) .wc-node[data-state="no"],
.wc-set > .wc-in:nth-of-type(4):checked ~ .wc-stage .wc-frame:nth-of-type(4) .wc-node[data-state="no"],
.wc-set > .wc-in:nth-of-type(5):checked ~ .wc-stage .wc-frame:nth-of-type(5) .wc-node[data-state="no"] { animation: wc-hit 0.5s ease-out 1.4s both; }
.wc-set .wc-stop:nth-child(1) .wc-dot { animation-delay: 0.1s; }
.wc-set .wc-stop:nth-child(2) .wc-dot { animation-delay: 0.7s; }
.wc-set .wc-stop:nth-child(3) .wc-dot { animation-delay: 1.3s; }
.wc-set .wc-stop:nth-child(4) .wc-dot { animation-delay: 1.9s; }

@keyframes wc-lit {
  0% { background: var(--paper); box-shadow: 0 0 8px color-mix(in srgb, var(--teal-dark) 70%, transparent); }
  40% { background: var(--brand-strong); box-shadow: 0 0 18px var(--brand-strong); }
  100% { background: var(--paper); box-shadow: 0 0 8px color-mix(in srgb, var(--teal-dark) 70%, transparent); }
}
@keyframes wc-hit {
  0% { transform: scale(1); }
  40% { transform: scale(1.06); }
  100% { transform: scale(1); }
}

/* ---- WIDTHS ---- */
/* THE CONNECTOR, where the hub sits beside the rail. One glowing wire from the hub to the first
   dot, which is the publication. Both step heads take one height, so the hub and the frame start
   on one line and the wire meets the dot. */
@media (min-width: 1201px) {
  .wc-hub::after {
    content: ""; position: absolute; top: 44px; left: 100%; width: calc(var(--s6) + 3px); height: 2px;
    background: linear-gradient(90deg, color-mix(in srgb, var(--teal-dark) 30%, transparent) 0%, var(--teal-dark) 100%);
    box-shadow: 0 0 6px var(--teal-dark);
  }
  .wc-stage .wc-step { min-height: 58px; align-content: flex-start; }
  .wc-frame .wc-rail { padding-top: 34px; }
}
/* FROM 1200 DOWN THE HUB TURNS SIDEWAYS AND TAKES THE FULL WIDTH: the pedestal beside the words.
   A centred card at 560px left 400px of nothing beside it. */
@media (max-width: 1200px) {
  .wc-stage { grid-template-columns: minmax(0, 1fr); gap: var(--s5); }
  .wc-hub { padding: var(--s3) var(--s5); text-align: left; }
  .wc-pub { display: grid; grid-template-columns: 112px minmax(0, 1fr); column-gap: var(--s4); align-items: center; }
  .wc-pub .wc-ped { grid-row: 1 / span 2; margin: 0; }
  .wc-pub-label { margin: 0; align-self: end; }
  .wc-pub-surface { margin-top: 4px; align-self: start; text-wrap: pretty; }
  .wc-pub-who { display: inline; margin: 0 4px 0 0; }
}
/* THE NARROW STATE. The act under each tab goes, because the tab's own words name the act, and the
   rail turns from a column into a row of four stops over the reach, so a reader still meets
   publish, wait, refuse and expire in that order. */
@media (max-width: 900px) {
  .wc-tab-act { display: none; }
  .wc-tab { min-height: 56px; padding: 8px var(--s3); }
  .wc-frame { grid-template-columns: minmax(0, 1fr); gap: var(--s5); }
  .wc-rail { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s3); padding: 24px 0 0; }
  .wc-dot { left: 0; top: -24px; }
  .wc-stop:not(:last-child)::before { left: 14px; right: calc(-1 * var(--s3)); top: -18px; bottom: auto; width: auto; height: 2px; background: var(--teal-dark); }
  .wc-pub-bound { font-size: 18px; }
  .wc-read-ev { margin-left: 0; }
}
/* AT A PHONE WIDTH two tabs share a row and the fifth takes the last row whole. The four stops go
   two by two, and the nodes of one row share the row, so three running copies read side by side. */
@media (max-width: 520px) {
  .wc-tab { flex-basis: 150px; min-height: 52px; }
  .wc-rail { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: calc(var(--s5) + 24px); }
  .wc-stop:nth-child(2)::before { display: none; }
  .wc-row { grid-template-columns: minmax(0, 1fr); gap: 4px; }
  .wc-row-nodes > .wc-node { min-width: 0; max-width: none; }
  .wc-hub { padding: var(--s3) var(--s4); }
  .wc-pub { grid-template-columns: 76px minmax(0, 1fr); column-gap: var(--s3); }
  .wc-pub .wc-ped { height: 72px; }
  .wc-pub .wc-ped::before { width: 72px; height: 44px; filter: blur(20px); }
  .wc-pub .wc-ped::after { width: 64px; }
  .wc-pub .wc-ped .rw-ped-contact { width: 52px; }
  .wc-pub .wc-ped .rw-ped-i svg { width: 32px; height: 32px; }
  .wc-pub-label { font-size: 18px; }
}

@media (prefers-reduced-motion: reduce) {
  .wc-tab, .wc-pub, .wc-frame, .wc-read { transition: none; }
  .wc-set .wc-dot, .wc-set .wc-node[data-state="no"] { animation: none !important; }
}

/* ---- THE WINDOWS, packages/ui/partials/wc-windows.ejs, on the evidence route ----
   One track per scope on one time axis. The read window is the brand, lit; the token window is the
   brand at a lower weight with a hatch, so the two read apart without a second hue; the unreadable
   list case is dashed, because it replaces the read window rather than adding to it. */
.wcw { position: relative; margin: 0; }
.wcw-key { list-style: none; margin: 0 0 var(--s5); padding: 0; display: flex; flex-wrap: wrap; gap: var(--s2) var(--s5); font-size: 14px; color: var(--ink-2); }
.wcw-key li { display: inline-flex; align-items: center; gap: var(--s2); }
.wcw-sw { width: 28px; height: 12px; border-radius: 3px; }
.wcw-tracks { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s4); }
.wcw-track { display: grid; grid-template-columns: minmax(0, 15rem) minmax(0, 1fr) minmax(0, 10rem); align-items: center; gap: var(--s4); }
.wcw-name { margin: 0; display: grid; gap: 4px; }
.wcw-label { font-size: 15px; font-weight: 600; color: var(--ink); }
.wcw-bar { position: relative; display: grid; gap: 4px; padding: 4px 0; border-radius: 8px; border: 1px solid var(--hairline); background: var(--paper); }
.wcw-lane { position: relative; height: 26px; }
.wcw-seg { position: absolute; top: 0; bottom: 0; border-radius: 5px; display: flex; align-items: center; justify-content: flex-end; padding: 0 6px; }
/* THE READ WINDOW'S NUMBER STARTS AT ITS LEFT EDGE AND MAY RUN PAST A SHORT WINDOW onto the hatch,
   where the token's own number sits at the far end, so a 60 s window at a phone width stays legible. */
.wcw-seg-read, .wcw-seg-alt { justify-content: flex-start; z-index: 1; }
.wcw-seg-n { font-size: 14px; font-weight: 700; white-space: nowrap; }
.wcw-seg-read .wcw-seg-n, .wcw-seg-alt .wcw-seg-n { position: relative; }
/* THE READ WINDOW IS A LIT EDGE ON A FLAT WASH, not a bright fill, so its number is ink on a token
   pair the contrast gate names, and a number that runs past a short window stays ink on the hatch. */
.wcw-seg-read, .wcw-sw-read {
  background: var(--wash-teal);
  border: 1px solid var(--teal-dark);
  box-shadow: 0 0 10px color-mix(in srgb, var(--teal-dark) 45%, transparent), inset 0 1px 0 color-mix(in srgb, var(--brand-strong) 50%, transparent);
}
.wcw-seg-read .wcw-seg-n { color: var(--ink); }
.wcw-seg-token, .wcw-sw-token {
  background: repeating-linear-gradient(135deg, color-mix(in srgb, var(--teal-dark) 30%, transparent) 0 6px, color-mix(in srgb, var(--teal-dark) 12%, transparent) 6px 12px);
  border: 1px solid color-mix(in srgb, var(--teal-dark) 50%, transparent);
}
.wcw-seg-token .wcw-seg-n { color: var(--ink); }
.wcw-seg-alt, .wcw-sw-alt { border: 1px dashed var(--teal-dark); background: linear-gradient(90deg, color-mix(in srgb, var(--teal-dark) 10%, transparent) 0%, color-mix(in srgb, var(--teal-dark) 10%, transparent) 100%); }
.wcw-seg-alt .wcw-seg-n { color: var(--ink); }
.wcw-worst-alt { display: block; margin-top: 4px; }
.wcw-worst-alt .mono { display: inline; font-size: 15px; }
.wcw-worst { margin: 0; font-size: 14px; color: var(--ink-2); }
.wcw-worst .mono { display: block; font-size: 18px; font-weight: 700; color: var(--ink); }
.wcw-axis { position: relative; height: 28px; margin: var(--s2) calc(10rem + var(--s4)) 0 calc(15rem + var(--s4)); border-top: 1px solid var(--rule); }
.wcw-tick { position: absolute; top: 0; transform: translateX(-50%); padding-top: 6px; white-space: nowrap; font-size: 14px; color: var(--ink-2); }
.wcw-tick:first-child { transform: none; }
.wcw-tick:last-child { transform: translateX(-100%); }
.wcw-tick::before { content: ""; position: absolute; left: 50%; top: -1px; width: 1px; height: 5px; background: var(--rule); }
.wcw-tick .mono { font-size: 14px; }
@media (max-width: 700px) {
  .wcw-track { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "name worst" "bar bar"; gap: var(--s2) var(--s3); }
  .wcw-name { grid-area: name; }
  .wcw-worst { grid-area: worst; text-align: right; }
  .wcw-bar { grid-area: bar; }
  .wcw-axis { margin: var(--s2) 0 0; }
  /* ONLY THE ENDS OF THE SCALE at a phone width: the inner ticks sit close enough to collide. */
  .wcw-tick:not(:first-child):not(:last-child) { display: none; }
}

/* ---- THE KEYS IN ONE WITHDRAWAL, packages/ui/partials/wc-keys.ejs ----
 * A table on the reference's side panel treatment: a vertical gradient, a brand border at low
 * alpha. Each key wears its identity hue in `--h` on the dot by its name and on the row's left
 * edge. "Not declared" is muted ink, never a state colour: it says no source declares the value. */
.wck { margin: 0; display: grid; gap: var(--s5); }
.wck-table { width: 100%; border-collapse: separate; border-spacing: 0; border: 1px solid color-mix(in srgb, var(--teal-dark) 30%, transparent); border-radius: 12px; overflow: hidden; background: linear-gradient(180deg, var(--white) 0%, var(--paper) 100%); }
.wck-table th, .wck-table td { text-align: left; vertical-align: top; padding: var(--s4); border-top: 1px solid var(--hairline); }
.wck-table thead th { border-top: 0; font-size: 14px; font-weight: 600; letter-spacing: 0.22em; text-transform: uppercase; color: var(--ink-2); }
.wck-row > :first-child { box-shadow: inset 3px 0 0 var(--h); }
.wck-whose { font-size: 16px; font-weight: 600; color: var(--ink); white-space: nowrap; }
.wck-dot { display: inline-block; width: 10px; height: 10px; margin-right: var(--s2); border-radius: 50%; background: var(--h); box-shadow: 0 0 10px var(--h); vertical-align: 1px; }
.wck-cell { display: table-cell; }
.wck-v, .wck-s, .wck-ev { display: block; }
.wck-v { font-size: 16px; font-weight: 600; color: var(--ink); }
.wck-s { margin-top: 2px; font-size: 14px; line-height: 1.45; color: var(--ink-2); }
.wck-inferred { font-style: italic; }
.wck-ev { margin-top: var(--s2); font-size: 14px; }
.wck-nd { color: var(--ink-2); }
.wck-shared { margin: 0; max-width: 60rem; font-size: 15px; line-height: 1.55; color: var(--ink); }
.wck-worst { padding: var(--s4) var(--s5); border: 1px solid var(--hairline); border-radius: 12px; }
.wck-worst-t { margin: 0 0 var(--s4); font-size: 14px; font-weight: 600; letter-spacing: 0.22em; text-transform: uppercase; color: var(--teal-dark); }
.wck-stats { margin: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s5); }
.wck-stat { display: grid; align-content: start; gap: 4px; padding-left: var(--s4); border-left: 1px solid var(--hairline); }
.wck-stat:first-child { padding-left: 0; border-left: 0; }
.wck-stat dt { font-size: 14px; color: var(--ink-2); }
.wck-stat dd { margin: 0; display: grid; gap: 4px; }
.wck-n { font-size: 22px; font-weight: 700; letter-spacing: -0.01em; color: var(--ink); }
.wck-n.wck-nd { color: var(--ink-2); }
@media (max-width: 760px) {
  .wck-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  .wck-table, .wck-table tbody, .wck-row, .wck-table th, .wck-table td { display: block; }
  .wck-row { border-top: 1px solid var(--hairline); box-shadow: inset 3px 0 0 var(--h); }
  .wck-row:first-child { border-top: 0; }
  .wck-row > :first-child { box-shadow: none; }
  .wck-table th, .wck-table td { border-top: 0; padding: var(--s3) var(--s4); }
  .wck-cell::before { content: attr(data-term); display: block; margin-bottom: 4px; font-size: 14px; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-2); }
  .wck-whose { white-space: normal; }
  .wck-stats { grid-template-columns: minmax(0, 1fr); gap: var(--s4); }
  .wck-stat { padding-left: 0; border-left: 0; }
}

/* ---- src/parts/why.css ---- */
/* The three scenario cards that close /why, packages/ui/partials/why-explore.ejs.
   View: apps/site/src/views/why.ejs. The page's own instruments are in wy.css.

   THE REST OF THIS FILE WENT ON 29 SEPTEMBER 2026, when /why was rebuilt from instruments. It styled
   the hero globe, the boundary map, the seven question ledger and the five reasons of the page
   before, and the partials that drew three of them (why-kinds, wh-ledger, why-reasons) went with
   it because nothing rendered them any more. The scenario cards stay, so their rules stay. */

/* ==========================================================================
   5. The three scenario cards
   ==========================================================================

   The comp's closing row: three cards on the supplied mesh, each one a route into a scenario that
   runs against the live estate.

   THE THREE HUES ARE THE IDENTITY SET AND THEY MEAN NOTHING, WHICH IS THE POINT. The comp tints its
   cards blue, violet and green and all three are drawn. The third used to be a quiet brand tint,
   refused the identity green on the grounds that green means Observed. That rule is about STATE: an
   Observed mark answers what is true of a thing, it sits beside a word, and it links its artefact.
   A card edge makes no such claim. --d-sand is out of the set only because it sits close to --att
   on a card that carries no word, which is a legibility reason rather than a refusal.

   THE MESH IS MASKED AWAY FROM THE WORDS. The texture fades out towards the top left, so the title
   sits on the flat card ground rather than on a picture. A ground the contrast gate can name is the
   whole reason the colour rule exists, and a photograph under text is the same hole in a third
   spelling.

   THE CARD MAY CARRY NO LINE. /why passes the route and the name alone, because the sentence under
   each card is that scenario page's own opening line and a reader meets it again one click later. */

.wx { display: grid; gap: var(--s5); }
/* The heading and the row's own link on one line, which is what the comp draws. */
.wx-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s3) var(--s5);
}
.wx-heading { margin: 0; }
.wx-row {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s5);
}
/* THE CARD IS MEASURED OFF THE REFERENCE BUILD, and it is drawn on / as well as here. The reference
   sets this card twice: app/page.tsx draws it at radius 16 with 28px of padding and a 22px title,
   and app/use-cases/page.tsx draws the same object at radius 14 with the same 28px padding. Both
   agree on the padding, so that is the number taken, and the radius is --r-3, which is 14. */
.wx-card {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-3);
  border: 1px solid color-mix(in srgb, var(--rule) 45%, transparent);
  border-left: 3px solid var(--wx-hue, var(--rule));
  background: var(--white);
}
.wx-card[data-hue="blue"] { --wx-hue: var(--d-blue); }
.wx-card[data-hue="violet"] { --wx-hue: var(--d-violet); }
.wx-card[data-hue="magenta"] { --wx-hue: var(--d-magenta); }

/* The texture. One declaration, one request, three cards, and it is masked to the lower right so
   no glyph lands on it. */
.wx-card::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background-image: url("/img/wave-mesh.jpg");
  background-size: cover;
  background-position: 50% 60%;
  mix-blend-mode: screen;
  opacity: 0.55;
  -webkit-mask-image: linear-gradient(to top left, var(--ink) 0%, transparent 66%);
  mask-image: linear-gradient(to top left, var(--ink) 0%, transparent 66%);
  pointer-events: none;
}
/* The hue, as a wash over the texture. A gradient, which is where the colour rule lets a mix live,
   and it sits under the text layer rather than behind a glyph: the mask above has already taken the
   texture out from under the words. */
.wx-card::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background: radial-gradient(120% 90% at 10% 100%, color-mix(in srgb, var(--wx-hue) 26%, transparent), transparent 70%);
  pointer-events: none;
}

.wx-link {
  position: relative;
  z-index: 1;
  display: grid;
  gap: var(--s2);
  min-height: 9rem;
  align-content: start;
  padding: 28px;
  color: inherit;
  text-decoration: none;
}
.wx-title { font-size: 22px; color: var(--ink); }
.wx-line { font-size: var(--t-small); line-height: 1.5; color: var(--ink-2); max-width: 280px; }
.wx-go {
  justify-self: end;
  align-self: end;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  margin-top: var(--s4);
  border-radius: var(--pill);
  border: 1px solid color-mix(in srgb, var(--rule) 70%, transparent);
  color: var(--ink);
  transition: border-color var(--m-drawer) ease, transform var(--m-drawer) ease;
}
.wx-go svg { width: 16px; height: 16px; }
.wx-link:hover .wx-go { border-color: var(--wx-hue); transform: translateX(2px); }
.wx-all { margin: 0; font-size: var(--t-small); white-space: nowrap; }

@media (max-width: 900px) {
  .wx-row { grid-template-columns: minmax(0, 1fr); }
  .wx-link { min-height: 0; }
}

/* ALL MOTION STOPS. The scenario card's arrow steps right on hover. The border colour still
   changes, because that is the hover signal; only the movement stops. */
@media (prefers-reduced-motion: reduce) {
  .wx-go { transition: none; }
  .wx-link:hover .wx-go { transform: none; }
}

/* ---- src/parts/wrt.css ---- */
/* /use-cases/wherever-it-runs: its one instrument, packages/ui/partials/wrt-token.ejs.
 *
 * THE TREATMENTS ARE components/diagram-section.tsx's, from the reference build, by class from
 * rw.css: the hub card, the environment card lit from above on its pedestal, the glowing connectors
 * with filled arrowheads, the ambient pool. This file places them and draws the ceilings and the rail.
 *
 * FOUR IDENTITY HUES AND NO STATE COLOUR. Each runtime carries its hue in `--hue` on its own column:
 * the cloud workload blue (--d-blue), the enrolled workstation green (--d-magenta), the workstation
 * with a hardware bound key violet (--d-violet) and the operator's key amber (--d-sand). A hue says
 * which runtime. KEPT AND WITHHELD ARE STATES and are drawn in ink only: a solid chip and a dashed,
 * struck chip. Nothing on this figure is Observed, so --ok, --att and --no appear nowhere here.
 */

/* ---- THE PAGE ----
   The rhythm is /use-cases/your-own-assistant's, which is the standard the rebuild measures against:
   the copy on top, the instrument across the full measure under it, the outcome row, then the close.
   The instrument never shares a row with the copy, because four columns each carrying three rows
   and a token need the width; CLAUDE.md rule 5 records what happened when they did not get it. */
.wrp { --page-max: 1472px; }
.wrp-top { position: relative; padding-block: 3.5rem var(--s6); display: grid; gap: var(--s7, 4rem); }
.wrp-copy > * { margin: 0; }
.wrp-copy .sc-eyebrow { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s3); letter-spacing: 0.22em; color: var(--slate); }
.wrp-copy .sc-eyebrow .ev { letter-spacing: normal; text-transform: none; }
.wrp-copy .sc-headline { margin-top: var(--s4); line-height: 1.02; letter-spacing: -0.035em; }
.wrp-copy .sc-lead { margin-top: 1.25rem; max-width: 36rem; font-size: 17px; line-height: 1.55; color: var(--ink-lead); }
.wrp-copy .sc-lead > p { margin: 0; }
.wrp-copy .sc-actions { margin-top: var(--s5); display: flex; flex-wrap: wrap; gap: var(--s4); }
/* ABOVE 1100 THE COPY TAKES TWO COLUMNS OVER THE INSTRUMENT: the headline on the left, the lead and
   the actions on the right, which is how the standard page draws its head at the same widths. */
@media (min-width: 1100px) {
  .wrp-copy { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: var(--s7, 4rem); grid-template-areas: "eyebrow eyebrow" "head lead" "head actions"; align-items: start; }
  .wrp-copy .sc-eyebrow { grid-area: eyebrow; }
  .wrp-copy .sc-headline { grid-area: head; }
  .wrp-copy .sc-lead { grid-area: lead; margin-top: var(--s4); }
  .wrp-copy .sc-actions { grid-area: actions; }
}
.wrp-figure { min-width: 0; }

/* THE OUTCOME ROW, the reference's benefits row: ringed 52px glyphs, hairlines between columns. */
.wrp-payoff { padding-block: var(--s6); }
.wrp-outcomes { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); }
.wrp-outcomes li { display: flex; flex-direction: column; align-items: center; text-align: center; padding: 0 var(--s4); }
.wrp-outcomes li + li { border-left: 1px solid var(--hairline); }
.wrp-outcome-i { width: 52px; height: 52px; }
.wrp-outcome-i svg { width: 26px; height: 26px; }
.wrp-outcome-t { margin: var(--s4) 0 0; font-size: 18px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.wrp-outcome-l { margin: var(--s2) 0 0; max-width: 19rem; text-wrap: balance; font-size: 15px; line-height: 1.5; color: var(--ink-2); }
@media (max-width: 900px) {
  .wrp-outcomes { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: var(--s6); }
  .wrp-outcomes li + li { border-left: 0; }
  .wrp-outcomes li:nth-child(even) { border-left: 1px solid var(--hairline); }
}
@media (max-width: 480px) {
  .wrp-outcomes { grid-template-columns: minmax(0, 1fr); }
  .wrp-outcomes li:nth-child(even) { border-left: 0; }
}

/* ---- THE INSTRUMENT ---- */
/* ---- THE INSTRUMENT ---- */
.wrt { position: relative; margin: 0; container-type: inline-size; min-width: 0; }
.wrt > * { position: relative; z-index: 1; }
.wrt > .wrt-glow { position: absolute; z-index: 0; top: 280px; width: 1100px; height: 520px; }

/* ---- THE CHECKS ---- */
.wrt-hub { max-width: 520px; margin: 0 auto; padding: var(--s5) var(--s5) var(--s4); }
.wrt-hub-i { display: inline-flex; color: var(--teal-dark); filter: drop-shadow(0 0 10px var(--teal-dark)); }
.wrt-hub-i svg { width: 40px; height: 40px; }
.wrt-hub-t { margin: var(--s2) 0 0; font-size: 22px; line-height: 1.25; font-weight: 700; color: var(--ink); }
.wrt-hub-l { margin: 4px 0 0; font-size: 15px; line-height: 1.5; color: var(--ink-2); }
.wrt-chips { list-style: none; margin: var(--s3) 0 0; padding: 0; display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s2); }
.wrt-chips li { padding: 4px 10px; border-radius: 6px; border: 1px solid var(--hairline); font-size: 14px; line-height: 1.4; font-weight: 500; color: var(--ink); }

/* ---- THE FAN, the reference's connectors ---- */
.wrt-fan { display: block; width: 100%; height: 72px; filter: drop-shadow(0 0 5px var(--teal-dark)); }
.wrt-wire { fill: none; stroke: var(--teal-dark); stroke-width: 2; stroke-linecap: round; vector-effect: non-scaling-stroke; opacity: 0.85; }

/* ---- THE FOUR COLUMNS ----
   NO GAP BETWEEN THE TRACKS, so each column centre is exactly where the fan's wire ends; each column
   pads itself instead. THE COLUMNS SHARE THEIR ROWS through subgrid and each card lays its parts
   straight into them, so four faces end on one line and four ceilings start on one line whatever
   wraps. Measured before this: the ceilings stepped 20px at 1280. */
.wrt-cols { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); grid-template-rows: repeat(6, auto); gap: 0; }
.wrt-col { display: grid; grid-row: span 6; grid-template-rows: subgrid; min-width: 0; padding-inline: calc(var(--s5) / 2); }
.wrt-col > .wrt-head, .wrt-col .wrt-drop { justify-self: center; }
.wrt-card { display: contents; }
.wrt-head { width: 0; height: 0; border-left: 7px solid transparent; border-right: 7px solid transparent; border-top: 11px solid var(--brand-strong); }
.wrt-ped { height: 72px; }
/* THE FACE FILLS ITS SHARED ROW, so four faces end on one line. */
.wrt-face { padding: var(--s4); }
.wrt-t { margin: 0; font-size: 17px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.wrt-s { margin: 4px 0 0; font-size: 14px; line-height: 1.45; color: var(--ink-2); }
.wrt-rows { margin: var(--s3) 0 0; }
.wrt-row { padding: 9px 0; border-top: 1px solid var(--hairline); }
.wrt-row dt { font-size: 14px; line-height: 1.35; font-weight: 600; color: var(--hue); }
.wrt-row dd { margin: 3px 0 0; font-size: 15px; line-height: 1.45; color: var(--ink); }
.wrt-row-token dd { font-family: var(--mono); font-size: 14px; }
.wrt-claim-k { color: var(--ink-2); }
.wrt-claim-v { font-weight: 600; color: var(--ink); }
/* ABSENT IS AN EMPTY SLOT, NOT A THIRD VALUE: the word in a dashed box in the second ink. */
.wrt-row-token[data-absent="true"] .wrt-claim-v { color: var(--ink-2); font-weight: 500; font-style: italic; padding: 0 6px; border: 1px dashed var(--rule); border-radius: 4px; }
.wrt-reach { margin: var(--s3) 0 0; padding-top: var(--s3); border-top: 1px dashed var(--rule); font-size: 14px; line-height: 1.45; color: var(--ink-2); }

/* THE DROP from the card to its ceiling, and from the ceiling to the platform. */
.wrt-drop { position: relative; width: 2px; height: 30px; background: var(--hue); opacity: 0.75; box-shadow: 0 0 6px var(--hue); }
.wrt-drop-low { height: 26px; }
.wrt-drop-dot { position: absolute; left: -3px; top: 0; width: 8px; height: 8px; border-radius: 50%; background: var(--hue); opacity: 0; }

/* ---- THE CEILING ---- */
.wrt-ceiling { border-radius: 10px; border: 1px solid var(--hairline); border-top: 2px solid var(--hue); background: var(--paper); padding: var(--s3) var(--s4); }
.wrt-ceiling-h { display: flex; justify-content: space-between; gap: var(--s2); margin: 0 0 var(--s2); font-size: 14px; line-height: 1.3; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-2); }
.wrt-ceiling-n { letter-spacing: normal; text-transform: none; color: var(--ink); white-space: nowrap; }
.wrt-types { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.wrt-type { padding: 2px 8px; border-radius: 6px; border: 1px solid var(--ink-2); font-family: var(--mono); font-size: 14px; line-height: 1.5; color: var(--ink); }
.wrt-type[data-state="withheld"] { border-style: dashed; border-color: var(--rule); color: var(--ink-2); text-decoration: line-through; }
.wrt-ceiling-none { margin: 0; font-size: 15px; line-height: 1.45; color: var(--ink); }

/* ---- THE PLATFORM ---- */
.wrt .wrt-platform { display: flex; align-items: center; justify-content: center; gap: var(--s3); text-align: left; padding: var(--s4) var(--s5); }
.wrt-platform-i { display: inline-flex; color: var(--teal-dark); filter: drop-shadow(0 0 8px var(--teal-dark)); }
.wrt-platform-i svg { width: 32px; height: 32px; }
.wrt-platform-w { display: flex; flex-direction: column; }
.wrt-platform-t { font-size: 18px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.wrt-platform-l { font-size: 15px; line-height: 1.5; color: var(--ink-2); }

/* ---- THE NARROW STATE: one rail from the checks to the platform ---- */
@container (max-width: 900px) {
  .wrt > .wrt-glow { top: 200px; }
  .wrt-fan, .wrt-head, .wrt-drop { display: none; }
  .wrt-hub { max-width: none; }
  .wrt-cols { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; gap: var(--s4); padding: var(--s5) 0 var(--s5) 44px; position: relative; }
  .wrt-cols::before { content: ""; position: absolute; left: 17px; top: 0; bottom: 0; width: 2px; background: var(--teal-dark); opacity: 0.7; box-shadow: 0 0 6px var(--teal-dark); }
  .wrt-col { display: block; grid-row: auto; padding-inline: 0; position: relative; }
  /* THE PEDESTAL BECOMES THE NODE ON THE RAIL: the glyph in its hue, standing on the line. */
  .wrt-ped { position: absolute; left: -44px; top: 12px; width: 36px; height: 36px; border-radius: 50%; background: var(--paper); border: 1.5px solid var(--hue); align-items: center; }
  .wrt-ped::before, .wrt-ped::after, .wrt-ped .rw-ped-contact { display: none; }
  .wrt-ped .rw-ped-i { margin: 0; }
  .wrt-ped .rw-ped-i svg { width: 20px; height: 20px; }
  .wrt-card { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); gap: var(--s3); align-items: start; }
  .wrt .wrt-platform { justify-content: flex-start; }
}
@container (max-width: 560px) {
  .wrt-card { grid-template-columns: minmax(0, 1fr); }
}

/* ---- THE LOOP ----
   Twelve seconds, four quarters, one runtime lit in each: a dot runs down the column's wire and its
   ceiling lights. Nothing appears or disappears, so every frame carries the whole argument. */
@media (prefers-reduced-motion: no-preference) {
  .wrt-drop-dot { animation: wrt-dot 12s linear infinite; }
  .wrt-ceiling { animation: wrt-lit 12s ease-in-out infinite; }
  [data-i="2"] .wrt-drop-dot, [data-i="2"] .wrt-ceiling { animation-delay: 3s; }
  [data-i="3"] .wrt-drop-dot, [data-i="3"] .wrt-ceiling { animation-delay: 6s; }
  [data-i="4"] .wrt-drop-dot, [data-i="4"] .wrt-ceiling { animation-delay: 9s; }
}
@keyframes wrt-dot {
  0%, 9% { top: 0; opacity: 0; }
  10% { top: 0; opacity: 1; }
  15% { top: 24px; opacity: 1; }
  16%, 100% { top: 24px; opacity: 0; }
}
@keyframes wrt-lit {
  0%, 12% { box-shadow: none; }
  16%, 24% { box-shadow: 0 0 22px var(--hue); }
  30%, 100% { box-shadow: none; }
}

/* ---- src/parts/ws-page.css ---- */
/*
 * /working-session, rebuilt on 16 September 2026 against the design foundation the nine ported
 * pages share, because this route has no reference page of its own.
 *
 * WHAT THIS FILE DRAWS. Four bands: a centred hero that carries the assurance line under its
 * controls and the instrument under that, a room band saying who to send, an agenda band holding
 * the six questions the six use case pages end on, and a close.
 * apps/site/src/views/working-session.ejs writes the markup and
 * apps/site/content/working-session.md carries every word this page owns.
 *
 * THE INSTRUMENT IS INSIDE THE HERO BAND AND IT USED TO BE A BAND OF ITS OWN with its top rule
 * switched off, which drew the same picture and still left the opening band of the conversion page
 * a block of words. /how-it-works and /architecture both open with their instrument inside the hero
 * band; this now does too, and the rule that was already off is gone with the section.
 *
 * THE ARC. The figure reads downward: three cards for what you bring, three connectors converging
 * into Raidiam Connect, one connector leaving it, and one card for what you leave with. Four
 * objects, four identity hues.
 *
 * WHERE THE MEASUREMENTS COME FROM. packages/ui/src/parts/hiw.css and
 * packages/ui/src/parts/arch-page.css, which are the ported reference pages this one has to look
 * like. Each rule below that takes a number from them says so. The recipe is: a centred hero at the
 * 1036 interior measure, a 56px top, a 0.28em eyebrow on secondary ink, the display token, a 560px
 * lead on --ink-lead, then ruled bands each opening with a 30px centred heading whose tail carries
 * the accent.
 *
 * SCOPE. Every rule carries .ws-page, which that view writes on its one wrapper and no other view
 * writes anywhere. So nothing here reaches another route, including the rules that sit on shared
 * classes such as .eyebrow.
 *
 * THE SCOPE IS ALSO WHAT MAKES THESE RULES APPLY. apps/site/src/public/site.css loads AFTER this
 * bundle, so a bare .eyebrow here loses to site.css at equal weight. The page class is one class
 * more than the rule it beats. Removing it does not widen a rule, it silences it.
 *
 * THE TREATMENTS ARE ASKED FOR BY NAME, NEVER COPIED. .rw-ped, .rw-card, .rw-hub, .rw-wires,
 * .rw-glow, .rw-panel, .rw-ring and .rw-btn live in packages/ui/src/parts/rw.css, ported from the
 * reference build. This file adds the layout around them and the type inside them. Three pages had
 * each grown their own plinth and their own glow before rw.css existed, and the differences were
 * accidents. A correction to a treatment has to land on every page at once.
 *
 * WHAT THIS FILE REFUSES TO DRAW.
 *
 * A FORM. The content file states that this site collects nothing and stores nothing, and that the
 * button opens a booking page Raidiam runs. A form here would be the one thing on this page a
 * reader could check and find untrue.
 *
 * A GREEN MARK. Green means Observed on this site and an Observed mark links its artefact. Nothing
 * on this page is read from the running estate, so no rule below paints a state token.
 *
 * A SIZE UNDER THE FLOOR. The reference sets 13px and 12.5px on the small text of a card. Every
 * size here is a scale token and the smallest is var(--t-label), which is 14. The floor is a
 * readability rule rather than a style choice, and packages/ui/tests/stylesheet.test.ts enforces it.
 *
 * COLOUR. Every value is a token. All four of the identity hues are used, --d-blue, --d-violet,
 * --d-magenta and --d-sand, passed in as --hue by the view from each item's own front matter. They
 * mean nothing on their own, which is what lets them carry identity here: the state vocabulary is
 * spent, and a hue that also means a verdict cannot do both jobs.
 *
 * HOW A HUE REACHES AN ELEMENT. The view sets --hue on the row, the card or the list item, and the
 * rules below read it. That is one mechanism, and it is the one rw.css already uses for the pedestal
 * and the card, so a hue reaches a treatment this file has never heard of.
 *
 * THE TWO EXCEPTIONS ARE PAINTED INLINE BY THE VIEW, and both are in rw.css rather than here: a
 * connector's stroke and an arrowhead's fill. rw.css states them as brand for every page that draws
 * wires, so this page states its own on the element. packages/ui/partials/lvp-arrive.ejs paints its
 * connectors the same way for the same reason.
 *
 * CONTRAST. Every pair below is one packages/ui/tools/contrast.mjs already enumerates by name:
 *   ink        on paper and on paper-alt    a headline, a band heading, a card title, a question
 *   ink-lead   on paper                     the hero lead
 *   ink-row    on paper and on paper-alt    the value in a role card and in a step
 *   ink-2      on paper and on paper-alt    the eyebrow, a row label, a caption
 *   teal-dark  on paper and on paper-alt    the accented tail, an arrow, a numeral with no hue
 *
 * THE FOUR HUES AS TEXT, WHICH IS WHAT A NUMERAL IS. packages/ui/tools/contrast.mjs already gates
 * d-blue, d-violet, d-magenta and d-sand against d-ground, d-surface and d-card at 4.5, and the
 * build maps --paper to d-ground and --paper-alt to d-surface, so the numerals on the agenda rows
 * and in the after panel sit on gated pairs. Run on 16 September 2026 the lowest of the twelve was
 * d-violet on d-card at 6.62. The pedestal glyph, the connector, the card edge and the ring are
 * graphics rather than text and carry no word of their own.
 *   ink        on white                     the hub name
 *   on-brand   on teal-deep                 the label inside the filled pill
 */

/* THE MEASURE, stated once, on the page wrapper rather than on one band.
   An interior page takes 1036px and this page already declared it, but it declared it on the hero's
   own wrap, so the hero sat at 1036 and the three bands under it sat at 1361. Measured at 1440 on
   16 September 2026 before this line moved: 1036, 1361, 1361, 1361. `.wrap` reads --page-max from
   the element it is set on, so setting it on the page wrapper is what makes every band inherit the
   one measure. The number is unchanged. */
.ws-page { --page-max: 1036px; }

/* ---- The hero -----------------------------------------------------------------------------------
   Centred, which is the interior recipe rather than a preference: .hw-hero and .arc-copy are both
   centred and both open a ported reference page. This hero was left aligned in a 1036 column, which
   left 500px of empty ground to the right of every line and made the page read as a different
   product from the two it sits between in the navigation. */
.ws-page .ws-hero {
  position: relative;
  overflow: hidden;
  /* .hw-hero pt-14, 56px. The foot is one step deeper than the reference's hero because the
     instrument now ends this band rather than opening the next one. */
  padding-block: 56px var(--s8);
  text-align: center;
}

.ws-page .ws-hero-in { position: relative; z-index: 1; }
.ws-page .ws-hero-in > * { margin: 0; }

/* .hw-eyebrow: 14px at the floor, weight 600, uppercase, 0.28em, on secondary ink. The site's own
   `.eyebrow` sets 0.14em, weight 700 and the brand colour, so the reference's values are named here
   and the class is not reused half overridden. */
.ws-page .ws-eyebrow {
  margin: 0;
  font-size: var(--t-label);
  font-weight: 600;
  line-height: var(--t-label-line);
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--ink-2);
}

/* .hw-headline: mt-4, centred, the display token, balanced.
   THE ACCENTED TAIL IS ITS OWN LINE. The reference lets its headline break on the measure because
   its headline is one sentence. This one is two sentences of nearly equal length, so the break is
   stated rather than left to the measure: "Ninety minutes." over "Your own estate." */
.ws-page .ws-headline { margin: var(--s4) auto 0; max-width: 20ch; text-wrap: balance; }
.ws-page .ws-headline .accent { display: block; }

/* .hw-lead: mt-5, 560px, 17px on 1.6, --ink-lead. One step brighter than secondary ink, which is
   what stops the sentence under a headline reading as a note about the headline. */
.ws-page .ws-lead {
  margin: 20px auto 0;
  max-width: 560px;
  color: var(--ink-lead);
  font-size: var(--t-body);
  line-height: 1.6;
}
.ws-page .ws-lead p { margin: 0; }
.ws-page .ws-lead p + p { margin-top: var(--s3); }

/* The reference sets its two controls in ONE ROW and the pair reads as one gesture. 36px above them
   is .hw-tabs' mt-9, which is the same gap the reference leaves between a lead and the first
   control under it. */
.ws-page .ws-actions { margin-top: 36px; justify-content: center; gap: var(--s4); }

/* THE ASSURANCE LINE. It is the only claim on this page a reader can check for themselves before
   pressing anything, so it sits directly under the controls and nothing else does. A hairline over
   it and nothing else around it: a border would make it a panel, and a panel reads as a disclaimer
   rather than as a promise. */
.ws-page .ws-assure {
  margin: var(--s6) auto 0;
  padding-top: var(--s5);
  max-width: 560px;
  border-top: 1px solid var(--hairline);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: center;
  gap: var(--s1) var(--s2);
  font-size: var(--t-small);
  line-height: var(--t-small-line);
}
.ws-page .ws-assure-i { color: var(--teal-dark); align-self: center; }
.ws-page .ws-assure-i .sc-glyph { display: block; }
.ws-page .ws-assure-i svg { width: 18px; height: 18px; display: block; }
.ws-page .ws-assure-lead { color: var(--ink); font-weight: 600; }
.ws-page .ws-assure-rest { color: var(--ink-2); }

/* ---- The instrument -----------------------------------------------------------------------------
   The arc, read downward: three cards for what you bring, a converging wire layer, the hub, one
   wire leaving it, and the card for what you leave with. It is the reference's own anatomy for one
   release reaching four environments, turned the other way up: one object every connector touches,
   and a lit card at the end of each connector. No heading sits over it, because the reference puts
   none over its own instrument and the headline above it already says what it says.

   IT SITS INSIDE THE HERO BAND, so it takes no rule and no measure of its own. The gap above it is
   the one gap between the assurance line and the figure. */
.ws-page .ws-figure { position: relative; margin-top: var(--s8); }

/* THE THREE LABELS ON THE ARC. Uppercase and tracked, the same treatment the reference gives the
   words beside its own figure, at the 14px floor. They are the only words on the figure that are
   not on a card, so they are set on secondary ink: a label that competes with a card title stops
   being a label. */
.ws-page .ws-fig-label {
  margin: 0 0 var(--s4);
  font-size: var(--t-label);
  line-height: var(--t-label-line);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: var(--ink-2);
}
/* The second label sits between the hub and the wires that leave it, so it carries the gap above it
   and the wires start directly under it. */
.ws-page .ws-fig-label-out { margin-top: var(--s5); margin-bottom: var(--s2); }

.ws-page .ws-hub-row { display: flex; justify-content: center; }
.ws-page .ws-hub { width: min(430px, 100%); }
.ws-page .ws-hub > * { margin: 0; }
/* WHO YOU MEET, on the hub: a label, then one ring and one name per role. The rows stack and share
   one left edge, so the rings line up under each other. */
.ws-page .ws-hub-with {
  margin-top: var(--s4);
  padding-top: var(--s4);
  border-top: 1px solid var(--rule);
  font-size: var(--t-label); line-height: var(--t-label-line); font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.22em; color: var(--ink-2);
}
.ws-page .ws-hub-room {
  list-style: none; margin: var(--s3) auto 0; padding: 0; width: fit-content;
  display: flex; flex-direction: column; align-items: flex-start; gap: var(--s3);
}
.ws-page .ws-hub-room li { display: flex; align-items: center; gap: var(--s3); color: var(--ink); font-size: 15px; font-weight: 600; }
/* The people take the brand ring from rw.css, all alike: no hue, because the figure spends the hues
   on the things you bring and leave with. */
.ws-page .ws-hub-ring { width: 36px; height: 36px; flex: none; }
.ws-page .ws-hub-ring svg { width: 18px; height: 18px; }
.ws-page .ws-hub-eyebrow {
  font-size: var(--t-label);
  line-height: var(--t-label-line);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: var(--ink-2);
}
.ws-page .ws-hub-name {
  margin-top: var(--s2);
  font-family: var(--display);
  font-size: var(--t-h2);
  line-height: var(--t-h2-line);
  color: var(--ink);
}

/* The wire layers. Each svg carries a 1200 unit wide box and preserveAspectRatio none, so y is one
   to one with this element and x is close enough that the residual scale never reaches 1.5 above
   the breakpoint where the layers are hidden. The height is fixed here because the box has none,
   and each height matches its own viewBox: 88 into the hub, 56 out of it.

   THE TWO ARE NOT THE SAME HEIGHT ON PURPOSE. The layer above the hub carries three curves that
   have to bend from the outer columns to the centre, and the layer below carries one straight line.
   Giving the straight one 88px as well left a long empty stripe between the hub and the card. */
.ws-page .ws-wires svg { height: 100%; }
.ws-page .ws-wires-in { height: 88px; }
.ws-page .ws-wires-out { height: 56px; }

.ws-page .ws-brings {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s5);
}

/* A CARD ANSWERS THE QUESTION IT RAISES WITHOUT BEING OPENED. The reference's environment card
   carries a title, a subtitle and labelled rows on its face, and this one follows it: what you
   bring, which one, the stage it enters and the surface that owns that stage. A card that shows a
   chip and hides the rest makes a reader press something to learn anything. */
.ws-page .ws-bring {
  display: grid;
  align-content: start;
  gap: var(--s2);
  text-align: center;
}

/* The pedestal stands the glyph on light. rw.css draws the four layers; this sets the glyph to the
   size those layers are measured for and drops the card's own gap for the row under it. */
.ws-page .ws-bring .rw-ped { margin-bottom: var(--s3); }
.ws-page .ws-bring .rw-ped-i .sc-glyph { display: block; }
.ws-page .ws-bring .rw-ped-i svg { width: 44px; height: 44px; }

.ws-page .ws-bring-title {
  margin: 0;
  font-family: var(--display);
  font-size: var(--t-h3);
  line-height: var(--t-h3-line);
  color: var(--ink);
}
.ws-page .ws-bring-sub {
  margin: 0;
  color: var(--ink-2);
  font-size: var(--t-small);
  line-height: var(--t-small-line);
}

/* The rows. A label and a value on one line, separated by a decorative hairline rather than a rule:
   nothing here is a boundary and nothing here is operated, so losing the line would cost a reader
   nothing, which is the test --hairline exists for.

   THE LABEL WRAPS ONTO ITS OWN LINE RATHER THAN SQUEEZING THE VALUE. At the 1036 measure a card is
   329px wide, and the widest value on the figure is "Your authorisation server and your resource".
   Measured at 1440: with the label and the value on one line that value took four lines beside a
   two word label. The row stacks below 360px of card instead. */
.ws-page .ws-bring-rows {
  margin: var(--s4) 0 0;
  display: grid;
  gap: 0;
  text-align: left;
}
.ws-page .ws-bring-rows > div {
  display: grid;
  gap: var(--s1);
  padding-block: var(--s2);
  border-top: 1px solid var(--hairline);
}
.ws-page .ws-bring-rows dt {
  margin: 0;
  color: var(--ink-2);
  font-size: var(--t-label);
  line-height: var(--t-label-line);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.14em;
}
.ws-page .ws-bring-rows dd {
  margin: 0;
  min-width: 0;
  color: var(--ink-row);
  font-size: var(--t-small);
  line-height: var(--t-small-line);
}

/* ---- What you leave with, the foot of the arc ----------------------------------------------------
   TWO CARDS, LAID ACROSS RATHER THAN DOWN, and that is what tells them apart from the three above.
   A card in the same portrait shape would read as one more thing you bring. They sit in a two column
   row as wide as the figure, and the wire layer above them lands on each card's centre. */
.ws-page .ws-outs {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s5);
}
.ws-page .ws-out {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: var(--s5);
  text-align: left;
}
/* The pedestal is 92px of standing room for a 44px glyph, measured for a card that carries it above
   the title. Across the card it only needs the glyph and its pool, so the height comes down and the
   glyph keeps the drop shadow rw.css gives it. */
.ws-page .ws-out-ped { height: 76px; width: 96px; flex: 0 0 auto; }
.ws-page .ws-out-ped .sc-glyph { display: block; }
.ws-page .ws-out-ped svg { width: 40px; height: 40px; }
.ws-page .ws-out-body { display: grid; gap: var(--s2); min-width: 0; }
.ws-page .ws-out-title {
  font-family: var(--display);
  font-size: var(--t-h3);
  line-height: var(--t-h3-line);
  font-weight: 700;
  color: var(--ink);
}
.ws-page .ws-out-sub {
  color: var(--ink-2);
  font-size: var(--t-small);
  line-height: var(--t-small-line);
}

/* ---- A ruled band and its head ------------------------------------------------------------------
   .hw-result-in: a hairline, 40px under it, centred, a 30px heading whose tail takes the accent.
   Both bands below open this way, so the recipe is written once.

   THE RULE IS THE BAND'S OWN AND IS NOT DRAWN AGAIN HERE. `.band` already puts a 1px rule across
   the top of every section, and .hw-result-in draws its own because /how-it-works is one long wrap
   with no sections in it. Measured at 1440: with a hairline on this element too, the two sat one
   pixel apart in different colours, #4d6a89 over #18293a, which reads as a thick smudged rule
   rather than as one line. The 40px is still the reference's, moved onto the band's padding. */
.ws-page .ws-band-head { text-align: center; }
.ws-page .ws-band-h,
.ws-page .ws-payoff-line {
  margin: 0;
  font-family: var(--display);
  font-size: 30px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.02em;
  color: var(--ink);
  /* 680px rather than the 24ch a display headline takes. Measured at 1440: the payoff line is
     nineteen words, and at 24ch of a 30px face it broke over four short ragged lines in the middle
     of a 1036px band. The reference sets no measure on this heading at all; 680 is the widest this
     one can be before it stops reading as a centred heading. */
  max-width: 680px;
  margin-inline: auto;
  text-wrap: balance;
}
.ws-page .ws-band-h .accent { color: var(--teal-dark); }
.ws-page .ws-band-lead {
  margin: var(--s3) auto 0;
  max-width: 560px;
  color: var(--ink-2);
  font-size: var(--t-small);
  line-height: var(--t-small-line);
}
/* In the agenda head the eyebrow sits above the heading, so it carries the gap rather than the
   heading carrying a top margin it does not want in the other band. */
.ws-page .ws-band-head .ws-eyebrow { margin-bottom: var(--s3); }

/* ---- Who to send --------------------------------------------------------------------------------
   The question this page was not answering. A CISO on the panel of 16 September 2026: "I need to
   know whether to send an architect or a procurement lead before I press anything."

   THE LAYOUT IS THE REFERENCE'S OWN. /how-it-works sets a stack of cards in the left column and one
   panel in the right, at gap-6. Here the stack is the three roles and the panel is what happens
   after the press. Every line in both columns is a sentence this page already declared. */
.ws-page .ws-room { padding-block: 40px var(--s8); }
.ws-page .ws-room-in {
  margin-top: var(--s7);
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s5);
  align-items: start;
}

.ws-page .ws-roles {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--s3);
  align-content: start;
}
/* The step card treatment from the reference's left column: a hairline, the alternate ground and a
   12px radius. It is not .rw-card, because .rw-card is lit from above by a hue and a role is not one
   of the three things you bring. */
.ws-page .ws-role {
  display: flex;
  align-items: flex-start;
  gap: var(--s4);
  border: 1px solid var(--hairline);
  border-radius: 12px;
  background: var(--paper-alt);
  padding: var(--s4) var(--s5);
}
.ws-page .ws-role .rw-ring .sc-glyph { display: inline-flex; }
/* THE RING TAKES THE ROLE'S IDENTITY HUE. Three people, three hues, so a reader can tell one row
   from the next before reading either. rw.css draws the ring's edge at 40% of the brand; this reads
   the same 40% of the row's own hue instead. The glyph inside is painted by the view, because that
   value is per row and lives in the content file. */
.ws-page .ws-role-ring {
  color: var(--hue, var(--teal-dark));
  border-color: color-mix(in srgb, var(--hue, var(--teal-dark)) 40%, transparent);
}
.ws-page .ws-role-body { display: grid; gap: var(--s1); min-width: 0; }
.ws-page .ws-role-who {
  font-family: var(--display);
  font-size: var(--t-body);
  font-weight: 700;
  line-height: 1.3;
  color: var(--ink);
}
.ws-page .ws-role-when {
  font-size: var(--t-label);
  line-height: var(--t-label-line);
  color: var(--ink-2);
}
.ws-page .ws-role-does {
  margin-top: var(--s1);
  font-size: var(--t-small);
  line-height: var(--t-small-line);
  color: var(--ink-row);
}

/* THE SEQUENCE, NOT A PARAGRAPH. These four sentences describe one thing happening after another,
   so they are numbered and read in that order. They were four paragraphs of prose in a panel at the
   foot of the page, where a reader deciding whether to press the control had already pressed it. */
.ws-page .ws-after { align-self: start; }
.ws-page .ws-after-list { list-style: none; margin: 0; padding: 0; display: grid; }
.ws-page .ws-after-list > li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--s4);
  align-items: baseline;
  padding-block: var(--s4);
}
.ws-page .ws-after-list > li + li { border-top: 1px solid var(--hairline); }
.ws-page .ws-after-list > li:first-child { padding-top: 0; }
.ws-page .ws-after-list > li:last-child { padding-bottom: 0; }
/* THE NUMERAL TAKES THE STEP'S IDENTITY HUE, which is the same job the numeral does on an agenda
   row below. It answers which step this is and nothing else: a step has no state, and this panel
   describes what happens after a press rather than what is true of anything. The brand is the
   fallback, so a row whose --hue the view never set is still legible rather than invisible. */
.ws-page .ws-after-n {
  font-size: var(--t-label);
  line-height: var(--t-label-line);
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--hue, var(--teal-dark));
  font-variant-numeric: tabular-nums;
}
.ws-page .ws-after-l {
  font-size: var(--t-small);
  line-height: var(--t-small-line);
  color: var(--ink-row);
}

/* ---- The agenda ---------------------------------------------------------------------------------
   THE SIX QUESTIONS, READ FROM THE SIX USE CASE PAGES. The payoff line has always promised the
   questions each use case ends on, answered against the reader's own estate. Those questions are
   declared: each use case content file carries its own `workingQuestion`. The view reads them from
   those files, so nothing here is a meeting agenda somebody wrote for the slot.

   ONE COLUMN, NOT TWO. Six rows in a 2 by 3 grid is shorter and reads as a set of cards. A reader
   arriving on this band is deciding who to send, and a numbered list running down the page is the
   shape that answers it: these are the six things the ninety minutes works through, in order. */
.ws-page .ws-agenda { padding-block: 40px var(--s8); }
.ws-page .ws-qs {
  list-style: none;
  margin: var(--s7) 0 0;
  padding: 0;
  border-top: 1px solid var(--hairline);
}
.ws-page .ws-q { border-bottom: 1px solid var(--hairline); }

.ws-page .ws-q-link {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: var(--s5);
  align-items: center;
  padding: var(--s5) var(--s4);
  text-decoration: none;
  border-radius: 10px;
  transition: background-color 160ms ease;
}
.ws-page .ws-q-link:hover { background: var(--paper-alt); }
.ws-page .ws-q-link:hover .ws-q-go { transform: translateX(3px); }

/* THE NUMERAL CARRIES THE ROW'S IDENTITY HUE. Six rows cycling the four hues, so a reader running
   down the list can tell one use case from its neighbour before reading either title. The hue makes
   no claim about the use case: the state vocabulary is Observed, Deployment evidence, Product
   capability and Not observed, and this band reads nothing from the running estate. */
.ws-page .ws-q-n {
  font-family: var(--display);
  font-size: var(--t-h3);
  line-height: 1;
  font-weight: 700;
  color: var(--hue, var(--teal-dark));
  font-variant-numeric: tabular-nums;
}
.ws-page .ws-q-body { display: grid; gap: var(--s2); min-width: 0; }
.ws-page .ws-q-case {
  font-size: var(--t-label);
  line-height: var(--t-label-line);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--ink-2);
}
.ws-page .ws-q-text {
  font-size: var(--t-body);
  line-height: 1.45;
  color: var(--ink);
}
.ws-page .ws-q-go {
  color: var(--teal-dark);
  display: inline-flex;
  transition: transform 160ms ease;
}
.ws-page .ws-q-go svg { width: 20px; height: 20px; display: block; }

/* ---- The close ----------------------------------------------------------------------------------
   One action, the way every ported page closes. The panel that used to sit beside it is now the
   sequence in the room band, where a reader meets it before the decision rather than after it. */
.ws-page .ws-close { padding-block: 0 var(--s8); }

/* ---- Narrow -------------------------------------------------------------------------------------
   The instrument needs a designed narrow state rather than a stacked one. Three cards hold their row
   down to 760px because each one carries two short stacked rows. Below that the wire layer has
   nothing left to reach across, so it goes and the cards run down the page in order, hub first,
   which is the reading order the figure already has. */
@media (max-width: 1100px) {
  .ws-page .ws-room-in { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 760px) {
  .ws-page .ws-hero { padding-block: var(--s7); }
  /* The wire layers go rather than stretch. Three curves that span 1200 units of a 360px box read as
     three near vertical lines, and a straight line under the hub reads as a stray rule. The arc is
     still in the reading order: bring, hub, leave with, each under its own label. */
  .ws-page .ws-wires { display: none; }
  .ws-page .ws-brings { grid-template-columns: minmax(0, 1fr); gap: var(--s4); }
  .ws-page .ws-hub-row { margin-block: var(--s5); }
  /* Across the card the pedestal takes 96px of a 358px row, which leaves the title breaking mid
     word. It stands over the text instead, which is the shape the three cards above already use. */
  .ws-page .ws-outs { grid-template-columns: minmax(0, 1fr); gap: var(--s4); }
  .ws-page .ws-out { grid-template-columns: minmax(0, 1fr); gap: var(--s3); text-align: center; }
  .ws-page .ws-out-ped { width: auto; }
  .ws-page .ws-band-h,
  .ws-page .ws-payoff-line { font-size: var(--t-h1); line-height: var(--t-h1-line); }
  /* The arrow goes and the row becomes two columns. At 390px the numeral, the question and a 20px
     arrow left the question 190px wide, which broke the longest of the six over seven lines. The
     whole row is still the link, so nothing is lost with the arrowhead. */
  .ws-page .ws-q-link { grid-template-columns: auto minmax(0, 1fr); gap: var(--s4); padding-inline: 0; }
  .ws-page .ws-q-go { display: none; }
}

@media (max-width: 420px) {
  /* The ring is 52px and a role card is 358px at this width, so the glyph and the text stack. */
  .ws-page .ws-role { flex-direction: column; gap: var(--s3); }
}

/* ---- src/parts/wy.css ---- */
/* /why: the page and its three instruments, packages/ui/partials/wy-scale.ejs, wy-record.ejs and
 * wy-boundary.ejs. View: apps/site/src/views/why.ejs. Content: apps/site/content/why.md.
 *
 * THE TREATMENTS ARE components/diagram-section.tsx's, from the reference build, as rw.css carries
 * them: the lit card, the hub, the ambient pool and the ringed glyph. This file places them and
 * draws what is particular to the three figures.
 *
 * IDENTITY HUES AND NO STATE COLOUR. Each organisation dot, each question and each item you keep
 * carries one of the four environment hues in `--hue` on its own element. A hue says which one. No
 * rule here reads --ok, --att or --no, because nothing on this page reports a state.
 */

/* ---- THE PAGE ---- */
.wy-page { --page-max: 1472px; }
.wy-eyebrow {
  margin: 0; font-size: 14px; font-weight: 600; letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--teal-dark);
}
.wy-band { position: relative; }
.wy-band-head { display: grid; gap: var(--s3); margin-bottom: var(--s7, 4rem); max-width: 60rem; }
.wy-band-head > * { margin: 0; }
.wy-h2 { letter-spacing: -0.03em; line-height: 1.08; text-wrap: balance; }
.wy-h2 .accent { display: block; color: var(--teal-dark); }

/* ---- THE HERO: the hiker photograph and the copy ----
   Ported from apps/site/src/views/rw/why-body.ejs, where Ralph set its crop and treatment in three
   rounds on 16 September 2026. The numbers are that view's, measured there, not re-derived:
     WIDTH  82 per cent of the band, capped at the viewport height less 96px, times 2.403, so a
            short window narrows the picture rather than growing the band. 2.403 is the image's
            own 1944 by 809 ratio. Two more caps keep it clear of the copy, set out below.
     FIT    contain, anchored right centre, so every callout baked into the picture stays in view.
     BLEED  it runs to the viewport's right edge and is masked to transparent on its left over the
            first third, so it dissolves into the ground the copy stands on.
     VEIL   the ground fades over its top and bottom edges, so the band has no hard line.
   Below 1280 the picture goes and the copy keeps the band. The rw view made the same cut at 1024:
   without room for a scene beside a headline, half a photograph is worse than none.
   THE MASK IS WRITTEN WITH TOKENS. A mask reads only alpha, so the opaque stop is the page ground
   token and the 45 per cent stop is a mix of it, rather than the rgba and hex literals the rw view
   carried, which the stylesheet test refuses. */
.wy-hero { position: relative; overflow: hidden; }
.wy-hero-photo {
  position: absolute; top: 0; bottom: 0; right: 0; display: none;
  width: min(82%, calc((100vh - 96px) * 2.403));
  background: url("/img/rw/why-hero-callouts.jpg") right center / contain no-repeat;
  -webkit-mask-image: linear-gradient(90deg, transparent 0%, color-mix(in srgb, var(--paper) 45%, transparent) 14%, var(--paper) 34%);
  mask-image: linear-gradient(90deg, transparent 0%, color-mix(in srgb, var(--paper) 45%, transparent) 14%, var(--paper) 34%);
  pointer-events: none;
}
.wy-hero-veil { position: absolute; inset: 0; pointer-events: none; background: linear-gradient(180deg, var(--paper) 0%, transparent 18%, transparent 72%, var(--paper) 100%); }
.wy-hero-in { position: relative; padding-block: var(--s6) var(--s7, 4rem); }
/* THE PICTURE SHOWS FROM 1280, NOT FROM 1024 AS IT DID IN THE rw VIEW, AND IT KEEPS CLEAR OF THE
   COPY. Measured on 29 September 2026 with the text hidden and every pixel under each line of copy
   sampled against that line's colour:
     at 1024 the picture started 184px from the left and the headline ran across the hiker;
     at 1440 and 82 per cent the end of the accent line sat on picture pixels at 2.7 to 1;
     at 1700 the copy starts inside a centred 1472 measure while the picture is anchored to the
     viewport's right edge, and the same line read 2.0 to 1.
   So the picture's left edge is held at least 420px right of where the copy starts, which puts the
   copy over the transparent part of the mask: 100% less 452px while the copy starts at the 32px
   gutter, and 50% plus 316px once the measure centres at 1536. The two meet at 1536. */
@media (min-width: 1280px) {
  .wy-hero-photo { display: block; width: min(82%, calc((100vh - 96px) * 2.403), calc(100% - 452px), calc(50% + 316px)); }
  .wy-hero-in { padding-block: 5rem; }
  .wy-top-copy { max-width: 500px; }
}
.wy-top-copy { position: relative; display: grid; gap: 0; align-content: start; }
.wy-top-copy > * { margin: 0; }
.wy-headline { margin-top: var(--s4); line-height: 1.02; letter-spacing: -0.035em; max-width: none; text-wrap: balance; }
.wy-lead { margin-top: 1.25rem; max-width: 440px; font-size: 17px; line-height: 1.55; color: var(--ink-lead); }
.wy-actions { margin-top: var(--s6); display: flex; flex-wrap: wrap; gap: var(--s4); }

/* ---- THE PROBLEM BAND, which holds the scale switch ---- */
.wy-top { position: relative; }
.wy-top-glow { top: 260px; }
.wy-top .wy-band-head { margin-bottom: var(--s5); }

/* ---- THE SCALE SWITCH ---- */
.wy-scale { position: relative; margin: 0; display: grid; gap: var(--s5); }
/* THE GROUP IS A FIELDSET, SO ITS LEGEND NAMES IT. The browser's own fieldset box is taken off. */
.wy-scale-pick { margin: 0; padding: 0; border: 0; min-width: 0; display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: var(--s3) var(--s4); }
.wy-scale-pick-l { float: left; padding: 0; font-size: 14px; font-weight: 600; letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink-2); }
.wy-scale-pick-set {
  display: inline-flex; gap: 4px; padding: 4px; border-radius: 999px;
  border: 1px solid var(--rule); background: var(--paper-alt);
}
/* THE RADIOS ARE REAL AND FOCUSABLE, and hidden only from sight inside their labels. The group
   takes one Tab stop and the arrow keys move within it. */
.wy-scale-r { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0; overflow: hidden; clip-path: inset(50%); opacity: 0; }
.wy-scale-opt {
  position: relative; min-width: 52px; min-height: 40px; padding: 0 var(--s3);
  display: inline-flex; align-items: center; justify-content: center;
  border: 2px solid transparent; border-radius: 999px; cursor: pointer;
  font-size: 16px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--ink-2);
  transition: background 160ms ease, color 160ms ease;
}
.wy-scale-opt:hover { color: var(--ink); }
.wy-scale-opt:has(:checked) { background: var(--teal-deep); color: var(--on-brand); }
.wy-scale-opt:has(:focus-visible) { outline: 2px solid var(--focus-ring); outline-offset: 3px; }
/* FORCED COLOURS DROP THE FILL, so the checked size keeps a drawn edge the system colours paint. */
@media (forced-colors: active) {
  .wy-scale-opt:has(:checked) { border-color: CanvasText; }
}

.wy-scale-stage { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s5); }
.wy-scale-side {
  position: relative; min-width: 0;
  display: grid; grid-template-rows: auto auto 1fr; justify-items: center; gap: var(--s2);
  padding: var(--s5) var(--s4) var(--s4);
  border-radius: 14px;
  border: 1px solid var(--hairline);
  background: linear-gradient(180deg, color-mix(in srgb, var(--paper-alt) 80%, transparent) 0%, color-mix(in srgb, var(--paper) 60%, transparent) 100%);
}
.wy-scale-side[data-side="shared"] {
  border-color: color-mix(in srgb, var(--teal-dark) 30%, transparent);
  box-shadow: 0 0 48px color-mix(in srgb, var(--teal-dark) 10%, transparent), inset 0 1px 0 color-mix(in srgb, var(--brand-strong) 30%, transparent);
}
.wy-scale-title { margin: 0; font-size: 15px; font-weight: 600; letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink-2); text-align: center; }
.wy-scale-count { margin: 0; text-align: center; font-size: 16px; color: var(--ink-2); }
.wy-scale-n b { display: block; font-size: 44px; line-height: 1.05; font-weight: 700; letter-spacing: -0.03em; font-variant-numeric: tabular-nums; color: var(--ink); }
.wy-scale-side[data-side="shared"] .wy-scale-n b { color: var(--brand-strong); }
.wy-scale-svg { display: block; width: 100%; max-width: 340px; height: auto; overflow: visible; }
.wy-scale-note { margin: 0; text-align: center; font-size: 14px; color: var(--ink-2); }

/* ONE STATE SHOWS AT A TIME, chosen by the checked radio. A browser without :has() shows the state
   the markup marks as the start, so the figure is never empty. */
.wy-scale-n, .wy-scale-svg { display: none; }
.wy-scale:has(.wy-k0:checked) [data-k="0"],
.wy-scale:has(.wy-k1:checked) [data-k="1"],
.wy-scale:has(.wy-k2:checked) [data-k="2"],
.wy-scale:has(.wy-k3:checked) [data-k="3"] { display: block; }
@supports not selector(:has(*)) {
  .wy-scale .wy-start { display: block; }
}

.wy-mesh { fill: none; stroke: var(--slate); stroke-width: 1; opacity: 0.55; }
.wy-spokes { fill: none; stroke: var(--teal-dark); stroke-width: 1.6; opacity: 0.9; stroke-dasharray: 5 7; }
.wy-dots .h0 { --hue: var(--d-blue); }
.wy-dots .h1 { --hue: var(--d-violet); }
.wy-dots .h2 { --hue: var(--d-magenta); }
.wy-dots .h3 { --hue: var(--d-sand); }
.wy-dots circle { fill: var(--hue); stroke: var(--paper); stroke-width: 2; filter: drop-shadow(0 0 6px var(--hue)); }
/* THE POOL IS A FLAT CIRCLE AT LOW OPACITY, NOT A BLUR. A CSS filter on an element inside an SVG
   has not always rendered in WebKit, and a pool that vanishes leaves a hub with no light on it. */
.wy-hub-pool { fill: var(--teal-mid); opacity: 0.22; }
.wy-hub { fill: var(--paper-alt); stroke: var(--teal-dark); stroke-width: 1.5; }
.wy-hub-i { color: var(--brand-strong); }

/* THE CHANGE IS SEEN, NOT JUMPED. The drawing that appears fades up. Reduced motion gets it at rest.
   The spokes do not flow: an infinite animation under a filter repainted eight paths every frame to
   say nothing the dashes do not already say. */
@media (prefers-reduced-motion: no-preference) {
  .wy-scale-svg { animation: wy-in 420ms ease-out both; }
}
@keyframes wy-in { from { opacity: 0; transform: scale(0.97); } to { opacity: 1; transform: none; } }

/* THE NARROW STATE. The two titles take the same two line box, so "One trust model" wrapping does
   not push its count and drawing lower than the pair it is compared with. */
@media (max-width: 640px) {
  .wy-scale-stage { gap: var(--s3); }
  .wy-scale-side { padding: var(--s4) var(--s2) var(--s3); }
  .wy-scale-title { font-size: 14px; line-height: 1.3; letter-spacing: 0.1em; min-height: 2.6em; display: flex; align-items: flex-end; justify-content: center; }
  .wy-scale-n b { font-size: 32px; }
  .wy-scale-count { font-size: 14px; }
}

/* ---- THE SEVEN QUESTIONS AND THE ONE RECORD ---- */
.wy-rec {
  position: relative; margin: 0;
  display: grid; grid-template-columns: minmax(0, 0.9fr) 96px minmax(0, 1.25fr);
  column-gap: 0;
}
.wy-rec-ask-h { grid-column: 1; align-self: end; margin: 0 0 var(--s4); font-size: 14px; font-weight: 600; letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink-2); }
.wy-rec-card-h {
  grid-column: 3; display: flex; align-items: center; gap: var(--s3);
  padding: var(--s5) var(--s5) var(--s4);
  border: 1px solid color-mix(in srgb, var(--teal-dark) 35%, transparent); border-bottom: 0;
  border-radius: 14px 14px 0 0;
  background: radial-gradient(120% 140% at 50% 0%, color-mix(in srgb, var(--teal-mid) 40%, transparent) 0%, color-mix(in srgb, var(--white) 92%, transparent) 70%);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--brand-strong) 35%, transparent);
}
.wy-rec-card-h > span { display: grid; gap: 2px; }
.wy-rec-mark { width: 22px; height: auto; flex: 0 0 auto; }
.wy-rec-title { font-size: 20px; font-weight: 700; color: var(--ink); }
.wy-rec-sub { font-size: 15px; color: var(--ink-2); }
.wy-rec-rows { grid-column: 1 / -1; list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: subgrid; }
.wy-rec-row { display: grid; grid-template-columns: subgrid; grid-column: 1 / -1; align-items: stretch; }
/* A BROWSER WITHOUT SUBGRID gets the same three columns declared again, which draws the same
   picture because every row carries identical tracks. */
@supports not (grid-template-columns: subgrid) {
  .wy-rec-rows, .wy-rec-row { grid-template-columns: minmax(0, 0.9fr) 96px minmax(0, 1.25fr); }
}
.wy-rec-q {
  align-self: center; margin: 6px 0;
  display: flex; align-items: center; gap: var(--s3);
  padding: 10px var(--s4) 10px 10px;
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--hue) 45%, transparent);
  background: linear-gradient(90deg, color-mix(in srgb, var(--hue) 14%, transparent) 0%, color-mix(in srgb, var(--paper-alt) 90%, transparent) 70%);
  font-size: 16px; font-weight: 600; line-height: 1.3; color: var(--ink);
}
.wy-rec-qi {
  flex: 0 0 auto; width: 36px; height: 36px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid color-mix(in srgb, var(--hue) 55%, transparent);
  color: var(--hue);
}
.wy-rec-qi svg { width: 19px; height: 19px; }
.wy-rec-wire { position: relative; container-type: inline-size; align-self: center; height: 2px; margin-left: -1px; background: linear-gradient(90deg, color-mix(in srgb, var(--hue) 30%, transparent), var(--hue)); box-shadow: 0 0 8px var(--hue); }
.wy-rec-wire::after {
  content: ""; position: absolute; right: -1px; top: 50%; transform: translateY(-50%);
  border-style: solid; border-width: 6px 0 6px 9px; border-color: transparent transparent transparent var(--hue);
}
.wy-rec-spark { position: absolute; top: 50%; left: 0; width: 8px; height: 8px; margin-top: -4px; border-radius: 50%; background: var(--hue); box-shadow: 0 0 10px var(--hue); opacity: 0; }
@media (prefers-reduced-motion: no-preference) {
  .wy-rec-spark { animation: wy-spark 14s linear infinite; animation-delay: calc(var(--i) * 2s); }
}
/* THE SPARK MOVES BY TRANSFORM, NOT BY `left`, so it composites rather than laying out the row every
   frame. The wire is a size container, so 100cqw is the wire's own length. */
@keyframes wy-spark {
  0% { transform: translateX(0); opacity: 0; }
  1% { opacity: 1; }
  9% { transform: translateX(calc(100cqw - 8px)); opacity: 1; }
  11%, 100% { transform: translateX(calc(100cqw - 8px)); opacity: 0; }
}
.wy-rec-a {
  margin: 0; display: grid; grid-template-columns: 7.5rem minmax(0, 1fr); align-items: center; gap: var(--s4);
  padding: 14px var(--s5);
  border-inline: 1px solid color-mix(in srgb, var(--teal-dark) 35%, transparent);
  border-top: 1px solid var(--hairline);
  background: linear-gradient(180deg, color-mix(in srgb, var(--white) 92%, transparent), color-mix(in srgb, var(--paper-alt) 92%, transparent));
}
.wy-rec-row:last-child .wy-rec-a { border-bottom: 1px solid color-mix(in srgb, var(--teal-dark) 35%, transparent); border-radius: 0 0 14px 14px; padding-bottom: var(--s5); }
.wy-rec-term { font-size: 14px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--hue); }
.wy-rec-ans { font-size: 16px; line-height: 1.45; color: var(--ink-lead); }

/* THE NARROW STATE. Each question sits over its answer with a short vertical wire, and the record
   keeps its lit edge down the whole run, so the seven still read as one record. */
@media (max-width: 900px) {
  .wy-rec { grid-template-columns: minmax(0, 1fr); }
  .wy-rec-ask-h { display: none; }
  .wy-rec-card-h { grid-column: 1; }
  .wy-rec-rows { grid-column: 1; }
  .wy-rec-row { grid-column: 1; grid-template-columns: minmax(0, 1fr); padding: var(--s4) var(--s4) var(--s4); border-inline: 1px solid color-mix(in srgb, var(--teal-dark) 35%, transparent); border-top: 1px solid var(--hairline); background: linear-gradient(180deg, color-mix(in srgb, var(--white) 92%, transparent), color-mix(in srgb, var(--paper-alt) 92%, transparent)); }
  .wy-rec-row:last-child { border-bottom: 1px solid color-mix(in srgb, var(--teal-dark) 35%, transparent); border-radius: 0 0 14px 14px; }
  .wy-rec-q { margin: 0; justify-self: start; }
  .wy-rec-wire { justify-self: start; margin: 0 0 0 27px; width: 2px; height: 18px; background: var(--hue); }
  .wy-rec-wire::after { right: auto; left: 50%; top: auto; bottom: -6px; transform: translateX(-50%); border-width: 7px 5px 0 5px; border-color: var(--hue) transparent transparent transparent; }
  .wy-rec-spark { display: none; }
  .wy-rec-a, .wy-rec-row:last-child .wy-rec-a { grid-template-columns: minmax(0, 1fr); gap: 2px; padding: var(--s3) 0 0; border: 0; border-radius: 0; background: none; }
}

/* ---- THE PROOF ----
   The credibility partial is shared with other pages and is not edited here. Every rule below is
   scoped under .wy-proof, so it reaches this page only. It turns the partial's typeset rows into a
   picture: the named ecosystems become lit cards and the four published figures become tiles.
   A HUE ON A CARD'S TOP EDGE SAYS WHICH CARD, AND NOTHING ELSE. The cards carried a glowing dot in
   their hue until the context reviewer of 29 September 2026 read five coloured dots, one green, as
   status lights. A dot is the shape a state mark takes on this site, so it went; the lit edge stays.
   THE ROWS ARE FLEX, NOT A FIXED GRID. The names come from apps/site/content/home.md, so the count
   can change. Each card grows to fill its row, so no count leaves a hole. */
.wy-band-lead { max-width: 44rem; font-size: 17px; line-height: 1.55; color: var(--ink-lead); }
.wy-proof { display: grid; gap: var(--s6); }
.wy-proof .credibility { margin-top: 0; padding-top: 0; border-top: 0; display: grid; gap: var(--s4); }
.wy-proof .credibility-mark-row { display: flex; flex-wrap: wrap; gap: var(--s3); }
.wy-proof .credibility-mark {
  flex: 1 1 200px;
  position: relative; min-height: 112px; align-content: end; gap: 6px;
  padding: var(--s5) var(--s4) var(--s4);
  border-radius: 12px;
  border: 1px solid color-mix(in srgb, var(--ink) 10%, transparent);
  border-top: 2px solid color-mix(in srgb, var(--hue) 70%, transparent);
  background: linear-gradient(180deg, color-mix(in srgb, var(--hue) 12%, transparent) 0%, color-mix(in srgb, var(--paper-alt) 85%, transparent) 55%, color-mix(in srgb, var(--paper) 85%, transparent) 100%);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--hue) 45%, transparent), 0 0 32px color-mix(in srgb, var(--hue) 8%, transparent);
}
.wy-proof .credibility-mark:nth-child(4n + 1) { --hue: var(--d-blue); }
.wy-proof .credibility-mark:nth-child(4n + 2) { --hue: var(--d-violet); }
.wy-proof .credibility-mark:nth-child(4n + 3) { --hue: var(--d-magenta); }
.wy-proof .credibility-mark:nth-child(4n + 4) { --hue: var(--d-sand); }
.wy-proof .credibility-mark-n { font-size: 22px; }
.wy-proof .credibility-mark-s { color: var(--hue); }
.wy-proof .credibility-row { display: flex; flex-wrap: wrap; gap: var(--s3); }
.wy-proof .credibility .fig {
  flex: 1 1 220px;
  align-content: center; gap: 6px; padding: var(--s5);
  border-radius: 12px; border: 1px solid color-mix(in srgb, var(--teal-dark) 28%, transparent);
  background: radial-gradient(120% 90% at 50% 0%, color-mix(in srgb, var(--teal-mid) 30%, transparent) 0%, color-mix(in srgb, var(--white) 92%, transparent) 70%);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--brand-strong) 30%, transparent);
}
.wy-proof .credibility .fig .value { font-size: 40px; letter-spacing: -0.03em; color: var(--brand-strong); }
.wy-proof .credibility .fig .label { font-size: 15px; }
.wy-proof .credibility-note { margin-top: var(--s2); }
.wy-std { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s4) var(--s6); padding-top: var(--s5); border-top: 1px solid var(--hairline); }
.wy-std-h { margin: 0; font-size: 14px; font-weight: 600; letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink-2); }
.wy-std-l { flex: 1 1 100%; margin: 0; font-size: 15px; color: var(--ink-2); }
.wy-std .hm-std { gap: var(--s3); }
.wy-std .hm-std-name {
  display: inline-flex; align-items: center; min-height: 44px; padding: 0 var(--s5);
  border-radius: 999px; border: 1px solid color-mix(in srgb, var(--teal-dark) 40%, transparent);
}
.wy-std .hm-std-name .std { font-size: 16px; text-decoration: none; color: var(--ink); }
.wy-std .hm-std-name:hover .std { color: var(--brand-strong); }
@media (max-width: 760px) {
  .wy-proof .credibility-mark { flex-basis: 140px; min-height: 96px; }
  .wy-proof .credibility-mark-n { font-size: 19px; }
  .wy-proof .credibility .fig { flex-basis: 140px; padding: var(--s4); }
  /* 24px keeps "Thousands" on one line in a 137px tile at 390. */
  .wy-proof .credibility .fig .value { font-size: 24px; }
}

/* ---- THE BOUNDARY ---- */
.wy-bd {
  position: relative; margin: 0;
  display: grid; grid-template-columns: minmax(0, 0.85fr) 72px minmax(0, 1.4fr); align-items: stretch;
}
.wy-bd-glow { top: 40%; left: 25%; width: 560px; }
.wy-bd-holds { position: relative; align-self: start; text-align: left; padding: var(--s6); }
.wy-bd-h { margin: 0 0 var(--s5); display: flex; align-items: center; gap: var(--s3); font-size: 15px; font-weight: 600; letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink-2); }
.wy-bd-h img { width: 18px; height: auto; }
.wy-bd-hl { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }
.wy-bd-hl li { padding: var(--s4) 0; border-top: 1px solid var(--hairline); }
.wy-bd-hl li:first-child { border-top: 0; padding-top: 0; }
.wy-bd-hl li, .wy-bd-k > span:last-child { display: grid; gap: 4px; }
.wy-bd-n { font-size: 17px; font-weight: 700; line-height: 1.3; color: var(--ink); }
.wy-bd-l { font-size: 15px; line-height: 1.5; color: var(--ink-2); }
.wy-bd-line { position: relative; display: flex; align-items: center; justify-content: center; }
.wy-bd-line::before { content: ""; position: absolute; top: 0; bottom: 0; left: 50%; border-left: 2px dashed var(--rule); }
.wy-bd-line span {
  position: relative; padding: var(--s2) var(--s3); border-radius: 999px;
  border: 1px solid var(--rule); background: var(--paper);
  font-size: 14px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-2);
  writing-mode: vertical-rl; transform: rotate(180deg);
}
.wy-bd-keeps { position: relative; min-width: 0; }
.wy-bd-h-keep { padding-top: var(--s2); }
.wy-bd-kl { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s3); }
.wy-bd-k { display: flex; gap: var(--s4); align-items: flex-start; padding: var(--s4) var(--s4) var(--s4); }
.wy-bd-first { grid-column: 1 / -1; }
/* The first card is full width, so an even count leaves the last card alone on its row: it takes the
   full width too rather than leave a hole beside it. */
.wy-bd-k:last-child:nth-child(even) { grid-column: 1 / -1; }
.wy-bd-first .wy-bd-n { font-size: 20px; }
.wy-bd-first .wy-bd-l { font-size: 16px; color: var(--ink-lead); }
.wy-bd-a { justify-self: start; margin-top: 4px; font-size: 15px; font-weight: 600; color: var(--teal-dark); }
.wy-bd-ki {
  flex: 0 0 auto; width: 40px; height: 40px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid color-mix(in srgb, var(--hue) 55%, transparent); color: var(--hue);
}
.wy-bd-ki svg { width: 20px; height: 20px; }
@media (max-width: 1100px) {
  .wy-bd { grid-template-columns: minmax(0, 1fr); }
  .wy-bd-line { height: 64px; }
  .wy-bd-line::before { top: 50%; bottom: auto; left: 0; right: 0; border-left: 0; border-top: 2px dashed var(--rule); }
  .wy-bd-line span { writing-mode: horizontal-tb; transform: none; }
}
@media (max-width: 640px) {
  .wy-bd-holds { padding: var(--s5); }
  .wy-bd-kl { grid-template-columns: minmax(0, 1fr); }
}

/* ---- THE CLOSE ---- */
.wy-close { gap: var(--s7, 4rem); }

/* ---- src/parts/xb.css ---- */
/* THE CROSSING, packages/ui/partials/xb-crossing.ejs, the instrument on
   /use-cases/across-the-boundary.

   THE TREATMENTS ARE components/diagram-section.tsx's and components/use-case/uc05-diagram.tsx's,
   from the reference build. uc05 draws this page's subject: a partner agent's requests, your trust
   decision, and a tick or a cross per request on your side. Its look is ported here: the lit cards,
   the hub, the pedestals and the ambient pool. Its green "Scoped access granted" pill is refused,
   because green means Observed on this site and no platform grants anything on this tenant.

   THE LAYOUT IS FOUR COLUMNS AND EVERY LANE IS A SUBGRID OF THEM: the partner card, the type asked
   for, the boundary, and your side. A lane's wire is drawn in three pieces, one per cell, so each
   piece lives in the cell it crosses and no piece needs to know another column's width. The wall is
   one absolute line at the boundary column's centre. With the first column fixed at 20rem and the
   second and fourth equal, that centre is at 50% plus half of 20rem at every width. */

.xb { position: relative; margin: 0; display: grid; gap: var(--s5); container-type: inline-size; }
.xb-glow { top: 120px; }

/* ---- The policy control, a radio group: one Tab stop, arrow keys inside it ------------------- */
/* THE CONTROL IS YOURS, SO IT STANDS ON YOUR SIDE: at the top of the lit panel behind the answer
   column, over the heading that names whose answer the column is. It stood in the top left for one
   round, and both reviewers read it there as the partner's policy. */
.xb-policy { position: relative; z-index: 1; grid-column: 4; grid-row: 1; align-self: start; justify-self: center; margin: var(--s5) var(--s3) 0; min-width: 0; border: 0; padding: 0; display: grid; justify-items: center; gap: var(--s2); }
.xb-policy-legend { padding: 0; margin: 0 auto var(--s2); text-align: center; letter-spacing: 0.14em; font-size: var(--t-label); font-weight: 600; letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink-2); }
.xb-policy-opts { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s2); }
.xb-opt { display: inline-flex; }
.xb-opt-label {
  display: inline-block; border: 1px solid var(--hairline); border-radius: 999px;
  padding: 9px 16px; background: var(--paper-alt);
  font-size: var(--t-label); font-weight: 600; color: var(--ink-2); cursor: pointer;
}
.xb-opt input:checked + .xb-opt-label { background: var(--wash-teal); border-color: color-mix(in srgb, var(--teal-dark) 55%, transparent); color: var(--ink); }
.xb-opt input:focus-visible + .xb-opt-label { outline: 2px solid var(--teal-dark); outline-offset: 2px; }

/* ---- The stage ------------------------------------------------------------------------------ */
.xb-stage {
  position: relative;
  display: grid;
  --c1: 20rem; --hopw: 260px;
  grid-template-columns: var(--c1) minmax(0, 1fr) var(--hopw) minmax(0, 1fr);
  column-gap: 0;
  row-gap: var(--s5);
  align-items: end;
}

/* THE BOUNDARY. A dashed line lit in the brand, from under the hop card to the foot of the lanes.
   In the narrow state it starts at the top of the stage and the control's own ground covers it
   until the hop card. */
.xb-wall {
  position: absolute; top: 40px; bottom: -8px; left: calc(50% + var(--c1) / 2); width: 2px; margin-left: -1px;
  background: repeating-linear-gradient(180deg, color-mix(in srgb, var(--teal-dark) 80%, transparent) 0 8px, transparent 8px 14px);
  filter: drop-shadow(0 0 6px color-mix(in srgb, var(--teal-dark) 70%, transparent));
  pointer-events: none;
}

/* YOUR SIDE, drawn as a territory. A panel lit from above in your hue runs the height of the
   figure behind the answer column, so what crosses the wall visibly arrives somewhere: the
   reference's environment card treatment, stretched to hold every answer. It starts just past the
   hop column and is pure decoration, so it carries no text and sits under everything. */
.xb-zone {
  position: absolute; top: 0; bottom: -16px; right: -12px;
  left: calc(50% + var(--c1) / 2 + var(--hopw) / 2);
  border-radius: 16px; pointer-events: none;
  border: 1px solid color-mix(in srgb, var(--d-blue) 18%, transparent);
  border-top-color: color-mix(in srgb, var(--d-blue) 55%, transparent);
  background: linear-gradient(180deg, color-mix(in srgb, var(--d-blue) 12%, transparent) 0%, color-mix(in srgb, var(--d-blue) 3%, transparent) 55%, transparent 100%);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--d-blue) 45%, transparent), 0 0 60px color-mix(in srgb, var(--d-blue) 8%, transparent);
}
.xb-head-you, .xb-got { position: relative; z-index: 1; }
/* THEIR SIDE, drawn as a quieter territory in the neutral ink, so the figure reads as two places
   with one boundary between them and the empty top left is the partner's ground rather than a gap.
   It carries no party hue, because it holds two parties, each with its own. */
.xb-zone-them {
  left: -12px; right: calc(50% - var(--c1) / 2 + var(--hopw) / 2);
  border-color: var(--hairline);
  background: linear-gradient(180deg, color-mix(in srgb, var(--ink) 4%, transparent) 0%, transparent 70%);
  box-shadow: none;
}

.xb-head { margin: 0; }
/* THEIR SIDE'S TWO BLOCKS, each the mirror of one on your side and in the same grid row: the key
   level with your control, and the eyebrow and heading level with yours. */
.xb-them-key { position: relative; z-index: 1; grid-row: 1; grid-column: 1 / 3; align-self: start; margin: var(--s5) 0 0 var(--s4); display: grid; justify-items: start; gap: var(--s2); }
.xb-key-l { margin: 0 0 var(--s2); font-size: var(--t-label); font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-2); }
.xb-key { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--s2); }
.xb-key li {
  display: inline-flex; align-items: center; gap: var(--s2);
  padding: 9px 16px; border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--hue) 45%, transparent);
  background: linear-gradient(180deg, color-mix(in srgb, var(--hue) 12%, transparent), color-mix(in srgb, var(--hue) 4%, transparent));
  font-size: var(--t-label); font-weight: 600; color: var(--ink);
}
.xb-key-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--hue); box-shadow: 0 0 8px var(--hue); }
.xb-head-them { position: relative; z-index: 1; grid-row: 2; grid-column: 1 / 3; align-self: end; padding: 0 0 var(--s2) var(--s4); display: grid; gap: var(--s1); }
.xb-head-them > p { margin: 0; }
.xb-them-org { font-size: var(--t-label); font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-2); }
.xb-them-t { font-size: 18px; font-weight: 700; color: var(--ink); }

/* THE HOP, the hub card standing on the wall. */
.xb-hop { grid-column: 3; grid-row: 1 / 3; align-self: start; position: relative; z-index: 1; background-color: var(--paper); margin: 0 var(--s2); padding: var(--s3) var(--s3) var(--s4); display: grid; gap: var(--s2); align-content: start;
  grid-template-columns: minmax(0, 1fr); }
.xb-hop > * { margin: 0; }
.xb-hop-t { font-size: 16px; font-weight: 700; color: var(--ink); }
.xb-hop-role code, .xb-hop-l code { font-family: var(--mono); font-size: 14px; color: var(--brand-strong); overflow-wrap: normal; }
.xb-hop-c { display: grid; gap: var(--s2); grid-row: 3; grid-column: 1; }
/* THE CARD KEEPS ONE HEIGHT IN EVERY SETTING, so moving the control never moves the lanes under it.
   Every setting's block sits in the same grid cell and the ones not chosen are kept in layout but
   invisible, so the tallest block sets the height at every width. A fixed min-height was tried
   first and measured short of the declared block by 15 to 42px, depending on the width. Visibility
   hidden also takes the block out of the accessibility tree, as `hidden` did. */
.xb .xb-hop-c[hidden] { display: grid !important; visibility: hidden; }
.xb-hop-c > p { margin: 0; }
.xb-hop-l { font-size: var(--t-label); color: var(--ink-2); }
.xb-hop-types { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s1) var(--s2); }
.xb-hop-types code, .xb-ask code, .xb-got-v code {
  display: inline-block; font-family: var(--mono); font-size: 14px; line-height: 1.4; color: var(--ink);
  padding: 4px 10px; border-radius: 8px; overflow-wrap: normal;
}
.xb-hop-types code { border: 1px solid color-mix(in srgb, var(--teal-dark) 50%, transparent); background: linear-gradient(180deg, color-mix(in srgb, var(--teal-dark) 14%, transparent), color-mix(in srgb, var(--teal-dark) 6%, transparent)); }
.xb-hop-none { font-size: 15px; font-weight: 700; color: var(--no); }

/* YOUR SIDE's head: a pedestal in your hue over your name and the heading that says whose answer
   the column is. The heading is the fix from commit 46b43f69, kept: the answer is your authority's. */
.xb-head-you { grid-column: 4; grid-row: 2; display: grid; justify-items: center; text-align: center; padding-bottom: var(--s2); }
.xb-head-you > p { margin: 0; }
.xb-you-org { margin-top: var(--s2) !important; font-size: var(--t-label); font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: var(--d-blue); }
.xb-you-t { margin-top: var(--s1) !important; font-size: 18px; font-weight: 700; color: var(--ink); text-wrap: balance; }
.xb-head-you { padding-inline: var(--s3); }

/* ---- One partner, and its lanes ------------------------------------------------------------- */
.xb-partner { grid-column: 1 / -1; display: grid; grid-template-columns: subgrid; align-items: center; }
.xb-card { grid-column: 1; position: relative; z-index: 1; display: flex; align-items: center; gap: var(--s3); padding: var(--s4) var(--s4) var(--s4) var(--s3); }
.xb-card-ped { flex: none; width: 80px; margin-left: calc(var(--s2) * -1); }
.xb-card-body { min-width: 0; display: grid; gap: var(--s1); }
.xb-card-body > * { margin: 0; }
.xb-org { font-size: var(--t-label); font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: var(--hue); }
.xb-agent { font-size: 18px; font-weight: 700; color: var(--ink); }
.xb-facts { list-style: none; margin: var(--s2) 0 0; padding: 0; display: grid; gap: var(--s1); }
.xb-facts li { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: var(--s2); }
.xb-fact-t { font-size: var(--t-label); color: var(--ink-2); }
.xb-fact-v { font-size: var(--t-label); font-weight: 600; color: var(--ink); overflow-wrap: anywhere; }
.xb-fact-v code { font-family: var(--mono); font-size: 14px; color: var(--ink); overflow-wrap: normal; }

.xb-lanes { grid-column: 2 / -1; list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: subgrid; row-gap: var(--s3); }
.xb-lane { grid-column: 1 / -1; display: grid; grid-template-columns: subgrid; align-items: center; min-height: 44px; }

/* The three wire pieces. Each is a flex child that grows, drawn as a 2px line. */
.xb-ask, .xb-got, .xb-gate { position: relative; display: flex; align-items: center; min-width: 0; }
.xb-ask::before { content: ""; flex: 0 0 var(--s5); height: 2px; background: var(--hue); opacity: 0.45; }
.xb-ask::after { content: ""; flex: 1 1 auto; min-width: var(--s4); height: 2px; background: var(--hue); opacity: 0.8; }
.xb-ask code { flex: 0 1 auto; min-width: 0; border: 1px solid color-mix(in srgb, var(--hue) 60%, transparent); background: linear-gradient(180deg, color-mix(in srgb, var(--hue) 16%, transparent), color-mix(in srgb, var(--hue) 6%, transparent)); box-shadow: 0 0 18px color-mix(in srgb, var(--hue) 18%, transparent); }

.xb-gate { justify-content: center; align-self: stretch; }
.xb-gate::before, .xb-gate::after { content: ""; position: absolute; top: 50%; height: 2px; margin-top: -1px; width: 50%; }
.xb-gate::before { left: 0; background: var(--hue); opacity: 0.8; }
.xb-gate::after { right: 0; background: linear-gradient(90deg, var(--hue), var(--d-blue)); }
.xb-gate-i {
  position: relative; z-index: 1; display: inline-flex; align-items: center; justify-content: center;
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--d-blue); box-shadow: 0 0 12px var(--d-blue);
}
.xb-gate-i svg { width: 18px; height: 18px; display: none; }

.xb-got { justify-content: center; }
.xb-got::before { content: ""; flex: 1 1 auto; min-width: var(--s4); height: 2px; background: var(--d-blue); filter: drop-shadow(0 0 4px var(--d-blue)); }
.xb-got::after { content: ""; flex: 1 1 auto; min-width: 0; }
.xb-got-v { flex: none; max-width: calc(100% - var(--s4)); }
.xb-got-v code { border: 1px solid color-mix(in srgb, var(--d-blue) 60%, transparent); background: linear-gradient(180deg, color-mix(in srgb, var(--d-blue) 18%, transparent), color-mix(in srgb, var(--d-blue) 6%, transparent)); box-shadow: 0 0 18px color-mix(in srgb, var(--d-blue) 22%, transparent), inset 0 1px 0 color-mix(in srgb, var(--d-blue) 40%, transparent); }

/* A LANE THAT STOPS. The wire ends at the boundary on a ringed cross in the state colour, the far
   half of the gate and the answer line go dark, and the answer cell carries the word that says why. */
.xb-lane:not([data-outcome="inside"]) .xb-gate::after,
.xb-lane:not([data-outcome="inside"]) .xb-got::before { background: none; filter: none; }
.xb-lane:not([data-outcome="inside"]) .xb-gate-i {
  width: 30px; height: 30px; background: var(--paper); color: var(--no);
  border: 2px solid var(--no); box-shadow: 0 0 14px color-mix(in srgb, var(--no) 40%, transparent);
}
.xb-lane:not([data-outcome="inside"]) .xb-gate-i svg { display: block; }
.xb-lane[data-outcome="unreached"] .xb-ask::after,
.xb-lane[data-outcome="unreached"] .xb-gate::before { opacity: 0.35; }
.xb-got-v[data-state="no"] { font-size: var(--t-label); font-weight: 600; color: var(--no); }
.xb-lane:not([data-outcome="inside"]) .xb-got { justify-content: flex-start; padding-left: var(--s4); }
.xb-lane:not([data-outcome="inside"]) .xb-got::before,
.xb-lane:not([data-outcome="inside"]) .xb-got::after { display: none; }

/* THE LIGHT THAT TRAVELS. On a lane that crosses, a short bright pulse runs along the far half of
   the boundary gate, so the eye reads the direction. It stands still for a reader who asks for
   reduced motion, and no word depends on it. */
.xb-lane[data-outcome="inside"] .xb-gate::after {
  background: linear-gradient(90deg, var(--hue), var(--d-blue)), linear-gradient(90deg, transparent, var(--white), transparent);
  background-size: 100% 100%, 40% 100%;
  background-repeat: no-repeat;
  background-blend-mode: screen;
  animation: xb-pulse 2.6s linear infinite;
}
@keyframes xb-pulse { from { background-position: 0 0, -60% 0; } to { background-position: 0 0, 160% 0; } }
@media (prefers-reduced-motion: reduce) { .xb-lane[data-outcome="inside"] .xb-gate::after { animation: none; } }

/* ---- The source line ------------------------------------------------------------------------- */
.xb-derived { margin: 0; text-align: center; font-size: var(--t-label); color: var(--ink-2); }
.xb-src {
  display: inline-block; margin-right: var(--s2); border: 1px solid var(--hairline); border-radius: 999px;
  padding: 1px 8px; font-size: var(--t-label); font-weight: 600; color: var(--ink-2);
}

/* ---- The middle state -------------------------------------------------------------------------
   THE FOUR COLUMNS NEED 980px AT FULL SIZE. The card column, the ask chip with its lead in and the
   boundary column set that floor, measured on transfer.initiate, the widest type. Between 880 and
   1040 the card column and the boundary column step down, and the wall moves with the card column.
   An earlier version switched straight to the narrow state at 760 and clipped the right hand column
   from 824 to 1050, which no page overflow check saw because an ancestor clips. */
@container (max-width: 1040px) {
  .xb-stage { --c1: 16rem; --hopw: 220px; }
  /* THE CONTROL TAKES A ROW OF ITS OWN HERE. Your column is about 240px wide at 1024, so the three
     pills stacked three high in it and pushed every lane down 150px. Above the stage they sit on one
     line, and both territories start under them. */
  .xb-policy { grid-column: 1 / -1; grid-row: 1; justify-self: center; margin: 0; }
  .xb-policy-opts { flex-wrap: nowrap; }
  .xb-hop { grid-row: 2 / 4; }
  .xb-them-key { grid-row: 2; }
  .xb-head-them { grid-row: 3; }
  .xb-head-you { grid-row: 2 / 4; align-self: end; }
  .xb-zone { top: 104px; }
  .xb-wall { top: 144px; }
  .xb-card-ped { width: 64px; }
  .xb-ask::before { flex-basis: var(--s3); }
}

/* ---- The narrow state ------------------------------------------------------------------------
   THE CROSSING STILL READS LEFT TO RIGHT. Three columns: the type asked for, the boundary as a 48px
   wall, and your answer. The hop card and your head sit on top, each partner card becomes one row
   above its own lanes, and the wall moves to the centre. A type wider than its cell breaks after a
   dot, because the chip may shrink and the partial puts a break opportunity after each dot. */
@container (max-width: 880px) {
  .xb-stage { grid-template-columns: minmax(0, 1fr) 48px minmax(0, 1fr); row-gap: var(--s5); }
  .xb-wall { left: 50%; top: 0; }
  .xb-policy { grid-column: 1 / -1; grid-row: 1; justify-self: stretch; justify-items: center; margin: 0; padding-bottom: var(--s2); background-color: var(--paper); }
  .xb-policy-legend { margin: 0 auto var(--s2); text-align: center; }
  .xb-policy-opts { justify-content: center; }
  .xb-them-key { display: none; }
  .xb-head-them { grid-column: 1; grid-row: 3; padding-left: 0; }
  .xb-them-org { letter-spacing: 0.12em; }
  .xb-hop { grid-column: 1 / -1; grid-row: 2; justify-self: center; width: min(100%, 300px); margin: 0; }
  .xb-head-you { grid-column: 3; grid-row: 3; padding: 0 0 var(--s2); }
  /* THE TERRITORY PANEL IS DROPPED HERE: the hop card spans both columns, so a panel starting under
     it would need a measured top, and the answer column is already your hue. */
  .xb-zone { display: none; }
  .xb-head-you .xb-you-ped { display: none; }
  .xb-partner { grid-template-rows: auto auto; row-gap: var(--s4); }
  .xb-card { grid-column: 1 / -1; position: relative; z-index: 1; padding: var(--s3); gap: var(--s3); background-color: var(--paper); }
  .xb-card-ped { width: 56px; margin-left: 0; }
  .xb-lanes { grid-column: 1 / -1; }
  .xb-ask::before { flex-basis: 0; }
  .xb-ask code, .xb-got-v code { padding: 4px 6px; }
  .xb-lane:not([data-outcome="inside"]) .xb-got { padding-left: var(--s2); }
}

/* ---- Forced colours ---------------------------------------------------------------------------
   In a forced colour mode the browser drops backgrounds, and every wire here is a background. The
   wires are redrawn in the system text colour, the chosen setting gets a system highlight edge,
   and a lane that stops keeps its ringed cross. The words carry the meaning in every case. */
@media (forced-colors: active) {
  .xb-ask::before, .xb-ask::after, .xb-gate::before,
  .xb-lane[data-outcome="inside"] .xb-gate::after,
  .xb-lane[data-outcome="inside"] .xb-got::before { forced-color-adjust: none; background: CanvasText; animation: none; }
  .xb-wall { forced-color-adjust: none; background: repeating-linear-gradient(180deg, CanvasText 0 8px, transparent 8px 14px); }
  .xb-opt input:checked + .xb-opt-label { outline: 3px solid Highlight; outline-offset: 2px; }
  .xb-gate-i { forced-color-adjust: none; background: CanvasText; }
  .xb-lane:not([data-outcome="inside"]) .xb-gate-i { background: Canvas; color: CanvasText; border-color: CanvasText; }
}

/* ---- src/parts/ya.css ---- */
/* THE YOUR OWN ASSISTANT EVIDENCE FIGURES: packages/ui/partials/ya-seq.ejs, ya-chain.ejs and
 * ya-keys.ejs, drawn on /use-cases/your-own-assistant/evidence.
 *
 * THE TREATMENTS ARE components/diagram-section.tsx's, from the reference build: the pedestal, the
 * glowing wire with a filled arrowhead, the ambient pool and the ringed glyph. No reference artefact
 * draws a pairing sequence, a trust chain or a key, so the compositions are ours.
 *
 * IDENTITY HUES ONLY. Every element takes its hue from `--hue` on its own party. The route is
 * Available throughout and nothing on it is Observed, so --ok, --att and --no appear nowhere here.
 *
 * NO TEXT SITS IN A BOX. The words are labels on wires, under pedestals and beside nodes. The one
 * dashed shape is the empty ring beside a chain's slot, and it is dashed because it draws an empty
 * place.
 *
 * A GLYPH FROM uc-glyph ARRIVES WRAPPED IN .sc-glyph, which scenario.css sizes to 36px and whose svg
 * rule is later in the bundle than rw.css's pedestal rule. So every figure here sizes the wrapper as
 * well as the svg. Measured by the second reviewer before this: the bank glyph stood 8px higher than
 * its neighbours and every chain glyph drew at 36px rather than 44.
 *
 * THIS FILE SORTS AFTER rw.css, so a rule here that restyles an rw- class at equal weight wins.
 */

/* ================================================================
   ya-seq: lanes and the steps between them.
   ================================================================ */
.ya-seq { position: relative; margin: 0; container-type: inline-size; min-width: 0; --gut: 52px; }
.ya-seq-glow { top: 140px; }
.ya-seq .rw-ped-i .sc-glyph, .ya-seq .rw-ped-i svg { width: 32px; height: 32px; }
.ya-seq .ya-seq-node .sc-glyph, .ya-seq .ya-seq-node svg { width: 22px; height: 22px; }
.ya-seq > * { position: relative; z-index: 1; }
.ya-seq > .ya-seq-glow { position: absolute; z-index: 0; }

.ya-seq-heads, .ya-seq-steps { list-style: none; margin: 0; padding: 0; }
.ya-seq-heads {
  display: grid; grid-template-columns: var(--gut) repeat(var(--lanes), minmax(0, 1fr));
}
.ya-seq-head { display: flex; flex-direction: column; align-items: center; text-align: center; padding-inline: var(--s2); min-width: 0; }
.ya-seq-name { margin: var(--s2) 0 0; font-size: 17px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.ya-seq-line { margin: 2px 0 0; font-size: 14px; line-height: 1.45; color: var(--ink-2); }

/* THE LIFELINES. One per lane, under the centre of its column, in the lane's hue at low strength so
   the arrows over them read first. */
.ya-seq-body { position: relative; margin-top: var(--s4); padding-bottom: var(--s3); }
.ya-seq-life {
  position: absolute; top: 0; bottom: 0; width: 2px;
  left: calc(var(--gut) + (100% - var(--gut)) * (var(--i) + 0.5) / var(--lanes) - 1px);
  background: linear-gradient(180deg, var(--hue) 0%, transparent 100%); opacity: 0.35;
}

.ya-seq-step {
  position: relative;
  display: grid; grid-template-columns: var(--gut) repeat(var(--lanes), minmax(0, 1fr));
  align-items: end; min-height: 64px; padding-block: var(--s2);
}
.ya-seq-n {
  position: relative; z-index: 1;
  grid-column: 1; grid-row: 1; align-self: center;
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; margin-left: 12px; border-radius: 50%;
  border: 1.5px solid var(--hue); background: var(--paper);
  font-size: 14px; font-weight: 700; color: var(--ink);
}

/* AN ARROW. It spans the columns of its two lanes and is inset by half a column at each end, so it
   starts and ends on the lifelines. --k is the number of columns it spans. */
.ya-seq-msg {
  grid-row: 1; display: flex; flex-direction: column; align-items: center;
  padding-inline: calc(100% / var(--k) / 2); min-width: 0;
}
.ya-seq-w { display: flex; flex-direction: column; align-items: center; text-align: center; padding: 0 var(--s3) 6px; min-width: 0; }
.ya-seq-t { font-size: 15px; line-height: 1.35; font-weight: 600; color: var(--ink); }
.ya-seq-s { font-size: 14px; line-height: 1.4; color: var(--ink-2); }
.ya-seq-wire {
  position: relative; display: block; width: 100%; height: 2px;
  background: var(--hue); box-shadow: 0 0 6px var(--hue);
}
.ya-seq-wire::after,
.ya-seq-msg[data-both="true"] .ya-seq-wire::before {
  content: ""; position: absolute; top: -5px; width: 0; height: 0;
  border-top: 6px solid transparent; border-bottom: 6px solid transparent;
}
.ya-seq-msg[data-dir="right"] .ya-seq-wire::after { right: -2px; border-left: 10px solid var(--hue); }
.ya-seq-msg[data-dir="left"] .ya-seq-wire::after { left: -2px; border-right: 10px solid var(--hue); }
.ya-seq-msg[data-both="true"][data-dir="right"] .ya-seq-wire::before { left: -2px; border-right: 10px solid var(--hue); }
.ya-seq-msg[data-both="true"][data-dir="left"] .ya-seq-wire::before { right: -2px; border-left: 10px solid var(--hue); }

/* A MATCH. Dashed, with no head, because nothing travels: the two screens each show the same code.
   The code is the claim, so it is set large in tabular figures. */
.ya-seq-is-match .ya-seq-wire { height: 0; background: none; box-shadow: none; border-top: 2px dashed var(--hue); }
.ya-seq-is-match .ya-seq-wire::after { display: none; }
.ya-seq-code {
  margin-top: 4px; font-size: 22px; line-height: 1.2; font-weight: 700; letter-spacing: 0.12em;
  font-variant-numeric: tabular-nums; color: var(--ink);
}

/* A STEP ONE PARTY TAKES ALONE. A ringed glyph on the lifeline, the words beside it. */
.ya-seq-self { grid-row: 1; align-self: center; display: flex; align-items: center; gap: var(--s3); min-width: 0; padding-left: calc(50% - 20px); }
.ya-seq-self .ya-seq-w { align-items: flex-start; text-align: left; padding: 0; }
.ya-seq-node {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: 50%;
  border: 1.5px solid var(--hue); background: var(--paper);
  box-shadow: 0 0 12px color-mix(in srgb, var(--hue) 45%, transparent);
  color: var(--hue);
}
.ya-seq-node svg { width: 22px; height: 22px; }

/* THE CHECK MARKS. A bar down the gutter, left of the step number, in the hue of the party that
   checks the step, and a legend above the steps that names each hue. The hue is identity: it says
   WHO checks. It says nothing about whether a check passed, because the figure is not a run. */
.ya-seq-legend {
  list-style: none; margin: var(--s5) 0 0; padding: 0 0 0 var(--gut);
  display: flex; flex-wrap: wrap; gap: var(--s2) var(--s5);
}
.ya-seq-legend li { display: inline-flex; align-items: center; gap: var(--s2); font-size: 14px; line-height: 1.4; font-weight: 600; color: var(--ink); }
.ya-seq-legend-bar, .ya-seq-chk::before { background: var(--chk); box-shadow: 0 0 6px var(--chk); border-radius: 2px; }
.ya-seq-legend-bar { display: inline-block; width: 4px; height: 18px; }
.ya-seq-chk::before { content: ""; position: absolute; left: 0; top: 14px; bottom: 14px; width: 4px; }

/* THE WORDS SIT OVER THE LIFELINES, so each carries a soft halo of the ground. A panel behind them
   would be text in a box; the halo only lifts the letters off the line. Measured by the second
   reviewer at 390: the lines ran through the step words. */
.ya-seq-t, .ya-seq-s, .ya-seq-code { text-shadow: 0 0 4px var(--paper), 0 0 8px var(--paper), 0 0 12px var(--paper); }

/* THE NARROW STATE. The lanes stay side by side; the gutter shrinks; a self step's words go under
   its node so a 110px lane still holds them. */
@container (max-width: 640px) {
  .ya-seq { --gut: 38px; }
  .ya-seq-n { width: 24px; height: 24px; margin-left: 9px; }
  .ya-seq-name { font-size: 15px; }
  .ya-seq-t { font-size: 14px; }
  .ya-seq-w { padding-inline: var(--s1, 4px); }
  .ya-seq-self { flex-direction: column; align-items: center; gap: var(--s2); padding-left: 0; }
  .ya-seq-self .ya-seq-w { align-items: center; text-align: center; }
  .ya-seq-code { font-size: 18px; letter-spacing: 0.06em; }
  .ya-seq .rw-ped-sm { height: 56px; }
}

/* ================================================================
   ya-chain: parties left to right, a worded wire between each pair.
   ================================================================ */
.ya-ch { position: relative; margin: 0; padding-top: var(--s4); container-type: inline-size; min-width: 0; }
.ya-ch-glow { top: 40px; }
.ya-ch .rw-ped-i .sc-glyph, .ya-ch .rw-ped-i svg { display: block; width: 44px; height: 44px; }
.ya-ch > * { position: relative; z-index: 1; }
.ya-ch > .ya-ch-glow { position: absolute; z-index: 0; }

.ya-ch-row { list-style: none; margin: 0; padding: 0; display: flex; align-items: flex-start; }
.ya-ch-node { flex: 0 1 13rem; display: flex; flex-direction: column; align-items: center; text-align: center; min-width: 0; }
.ya-ch-n4 .ya-ch-node { flex-basis: 10rem; }
.ya-ch-name { margin: var(--s2) 0 0; font-size: 17px; line-height: 1.3; font-weight: 700; color: var(--ink); }
.ya-ch-line { margin: 4px 0 0; font-size: 14px; line-height: 1.45; color: var(--ink-2); text-wrap: balance; }

/* THE SLOT. An empty place under a party: a dashed empty ring in the party's hue, and beside it
   what the place is for and what is in it. No outline round the words. */
.ya-ch-slot {
  margin: var(--s4) 0 0; display: grid; grid-template-columns: auto minmax(0, auto); column-gap: var(--s3);
  align-items: center; text-align: left;
}
.ya-ch-slot::before {
  content: ""; grid-row: span 2; width: 30px; height: 30px; border-radius: 50%;
  border: 2px dashed color-mix(in srgb, var(--hue) 75%, transparent);
}
.ya-ch-slot-t { font-size: 14px; line-height: 1.4; color: var(--ink-2); }
.ya-ch-slot-v { font-size: 17px; line-height: 1.3; font-weight: 700; color: var(--ink); }

/* THE WIRE. Level with the pedestal's glyph, graded from one party's hue to the next, with a filled
   head in the hue of the party it reaches. Its words sit above it. */
/* THE WIRE IS LEVEL WITH EVERY GLYPH, whatever its words, because the words sit UNDER it. The
   pedestal is 92px tall and its glyph's centre is 54px from the top, so the wire is pushed down by
   53px and its 2px line straddles that centre. A label that wraps grows downward into empty ground.
   Measured before: labels above the wire in a 50px box grew upward, and at a 900px viewport a five
   line label covered the band's subtitle. */
.ya-ch-link { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; padding-top: 53px; }
.ya-ch-wire {
  position: relative; display: block; height: 2px; margin: 0 6px;
  background: linear-gradient(90deg, var(--from), var(--to));
  box-shadow: 0 0 6px color-mix(in srgb, var(--to) 60%, transparent);
}
.ya-ch-wire::after {
  content: ""; position: absolute; right: -4px; top: -5px;
  border-top: 6px solid transparent; border-bottom: 6px solid transparent; border-left: 10px solid var(--to);
}
.ya-ch-w { display: flex; flex-direction: column; align-items: center; text-align: center; padding: var(--s3) var(--s2) 0; min-width: 0; }
.ya-ch-t { font-size: 15px; line-height: 1.35; font-weight: 600; color: var(--ink); text-wrap: balance; }
.ya-ch-s { font-size: 14px; line-height: 1.4; color: var(--ink-2); text-wrap: balance; }
.ya-ch-note { margin: var(--s5) 0 0; text-align: center; font-size: 15px; line-height: 1.5; color: var(--ink-2); }

/* THE NARROW STATE: THE CHAIN RUNS DOWN, below 820px for any chain and below 1000px for four parties. Each party on a row, its pedestal on the left and its words
   beside it; each wire vertical, with its words beside the wire. */
@container (max-width: 820px) {
  .ya-ch .ya-ch-row { flex-direction: column; align-items: stretch; }
  .ya-ch .ya-ch-node {
    flex: none; display: grid; grid-template-columns: 96px minmax(0, 1fr); column-gap: var(--s3);
    align-items: center; text-align: left;
  }
  .ya-ch .ya-ch-node .rw-ped { grid-row: span 3; height: 76px; }
  .ya-ch .ya-ch-name { margin: 0; }
  .ya-ch .ya-ch-line { text-wrap: pretty; }
  .ya-ch .ya-ch-slot { grid-column: 2; align-items: flex-start; justify-self: start; margin-top: var(--s2); }
  .ya-ch .ya-ch-link { flex: none; flex-direction: row; justify-content: flex-start; align-items: stretch; padding: 0; min-height: 72px; }
  .ya-ch .ya-ch-wire {
    flex: 0 0 2px; width: 2px; height: auto; margin: 4px 46px 12px 47px;
    background: linear-gradient(180deg, var(--from), var(--to));
  }
  .ya-ch .ya-ch-wire::after {
    right: auto; left: -5px; top: auto; bottom: -4px;
    border-left: 6px solid transparent; border-right: 6px solid transparent; border-top: 10px solid var(--to); border-bottom: 0;
  }
  .ya-ch .ya-ch-w { align-items: flex-start; text-align: left; justify-content: center; padding: var(--s2) 0; }
  .ya-ch .ya-ch-note { text-align: left; }
}
@container (max-width: 1000px) {
  .ya-ch-n4 .ya-ch-row { flex-direction: column; align-items: stretch; }
  .ya-ch-n4 .ya-ch-node {
    flex: none; display: grid; grid-template-columns: 96px minmax(0, 1fr); column-gap: var(--s3);
    align-items: center; text-align: left;
  }
  .ya-ch-n4 .ya-ch-node .rw-ped { grid-row: span 3; height: 76px; }
  .ya-ch-n4 .ya-ch-name { margin: 0; }
  .ya-ch-n4 .ya-ch-line { text-wrap: pretty; }
  .ya-ch-n4 .ya-ch-slot { grid-column: 2; align-items: flex-start; justify-self: start; margin-top: var(--s2); }
  .ya-ch-n4 .ya-ch-link { flex: none; flex-direction: row; justify-content: flex-start; align-items: stretch; padding: 0; min-height: 72px; }
  .ya-ch-n4 .ya-ch-wire {
    flex: 0 0 2px; width: 2px; height: auto; margin: 4px 46px 12px 47px;
    background: linear-gradient(180deg, var(--from), var(--to));
  }
  .ya-ch-n4 .ya-ch-wire::after {
    right: auto; left: -5px; top: auto; bottom: -4px;
    border-left: 6px solid transparent; border-right: 6px solid transparent; border-top: 10px solid var(--to); border-bottom: 0;
  }
  .ya-ch-n4 .ya-ch-w { align-items: flex-start; text-align: left; justify-content: center; padding: var(--s2) 0; }
  .ya-ch-n4 .ya-ch-note { text-align: left; }
}

/* ================================================================
   ya-keys: two keys, each in its device, and how far it is vouched for.
   ================================================================ */
.ya-k { position: relative; margin: 0; container-type: inline-size; min-width: 0; }
.ya-k-glow { top: 40px; }
.ya-k > * { position: relative; z-index: 1; }
.ya-k > .ya-k-glow { position: absolute; z-index: 0; }

.ya-k-pair { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.ya-k-key { display: flex; flex-direction: column; align-items: center; min-width: 0; padding-inline: var(--s6); }
.ya-k-key + .ya-k-key { border-left: 1px solid var(--hairline); }

/* THE DEVICE. An outline lit from above in the holder's hue, the key glowing on its screen. The phone is
   tall, the laptop is a screen over a base. Both are pure CSS. */
.ya-k-dev { position: relative; display: flex; align-items: center; justify-content: center; }
.ya-k-screen {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--s2);
  border: 1.5px solid color-mix(in srgb, var(--hue) 70%, transparent);
  background: radial-gradient(90% 70% at 50% 0%, color-mix(in srgb, var(--hue) 22%, transparent) 0%, transparent 70%), var(--paper);
  box-shadow: 0 0 36px color-mix(in srgb, var(--hue) 25%, transparent), inset 0 1px 0 color-mix(in srgb, var(--hue) 45%, transparent);
}
.ya-k-phone .ya-k-screen { width: 150px; height: 220px; border-radius: 26px; }
.ya-k-laptop { flex-direction: column; }
.ya-k-laptop .ya-k-screen { width: 260px; height: 164px; border-radius: 12px 12px 4px 4px; }
.ya-k-laptop::after {
  content: ""; display: block; width: 312px; height: 12px; margin-top: 2px;
  border-radius: 2px 2px 10px 10px;
  background: linear-gradient(180deg, color-mix(in srgb, var(--hue) 45%, transparent), color-mix(in srgb, var(--hue) 12%, transparent));
}
.ya-k-laptop { height: 220px; justify-content: flex-end; }
.ya-k-key-i { display: inline-flex; color: var(--hue); filter: drop-shadow(0 0 12px var(--hue)); }
.ya-k-key-i svg, .ya-k-key-i .sc-glyph { width: 56px; height: 56px; }

.ya-k-name { margin: var(--s5) 0 0; font-size: 20px; line-height: 1.3; font-weight: 700; color: var(--ink); text-align: center; }
.ya-k-line { margin: 4px 0 0; font-size: 15px; line-height: 1.45; color: var(--ink-2); text-align: center; }

.ya-k-rows { margin: var(--s4) 0 0; width: 100%; max-width: 26rem; }
.ya-k-row { display: grid; grid-template-columns: minmax(0, 9rem) minmax(0, 1fr); gap: var(--s3); padding: 10px 0; border-top: 1px solid var(--hairline); }
.ya-k-row dt { font-size: 14px; line-height: 1.45; font-weight: 600; color: var(--ink-2); }
.ya-k-row dd { margin: 0; font-size: 15px; line-height: 1.45; color: var(--ink); }

/* WHO VOUCHES, on a ring in the voucher's own hue, then the meter filled in ink to the stated level. */
.ya-k-by { display: flex; align-items: center; gap: var(--s3); width: 100%; max-width: 26rem; margin-top: var(--s4); padding-top: var(--s4); border-top: 1px solid var(--hairline); }
.ya-k-by-i {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border-radius: 50%;
  border: 1.5px solid var(--by); color: var(--by);
  box-shadow: 0 0 12px color-mix(in srgb, var(--by) 40%, transparent);
}
.ya-k-by-i svg, .ya-k-by-i .sc-glyph { width: 22px; height: 22px; }
.ya-k-by-w { display: flex; flex-direction: column; min-width: 0; }
.ya-k-by-t { font-size: 15px; line-height: 1.35; font-weight: 700; color: var(--ink); }
.ya-k-by-l { font-size: 14px; line-height: 1.45; color: var(--ink-2); }

.ya-k-level { display: flex; align-items: center; gap: var(--s3); width: 100%; max-width: 26rem; margin-top: var(--s3); }
.ya-k-meter { display: flex; gap: 6px; flex: 1 1 auto; }
.ya-k-seg { flex: 1 1 0; height: 8px; border-radius: 4px; border: 1.5px solid var(--ink-2); }
.ya-k-seg[data-on="true"] { background: var(--ink); border-color: var(--ink); }
.ya-k-level-w { flex: 0 0 6.5rem; font-size: 15px; line-height: 1.3; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink); }

.ya-k-note { margin: var(--s6) 0 0; text-align: center; font-size: 15px; line-height: 1.5; color: var(--ink-2); }

/* THE NARROW STATE. Side by side while two keys fit, with the devices drawn smaller; stacked below
   480px, with a rule between the two keys. */
@container (max-width: 720px) {
  .ya-k-key { padding-inline: var(--s3); }
  .ya-k-phone .ya-k-screen { width: 96px; height: 150px; border-radius: 18px; }
  .ya-k-laptop { height: 150px; }
  .ya-k-laptop .ya-k-screen { width: 160px; height: 104px; }
  .ya-k-laptop::after { width: 196px; height: 9px; }
  .ya-k-key-i svg, .ya-k-key-i .sc-glyph { width: 40px; height: 40px; }
  .ya-k-row { grid-template-columns: minmax(0, 1fr); gap: 2px; }
}
@container (max-width: 480px) {
  .ya-k-pair { grid-template-columns: minmax(0, 1fr); row-gap: var(--s6); }
  .ya-k-key { padding-inline: 0; }
  .ya-k-key + .ya-k-key { border-left: 0; border-top: 1px solid var(--hairline); padding-top: var(--s6); }
}
