/* SSCS Bootstrapper — "Attestation Ledger" design system.
   Print-shop ledger: paper ground, surface cards with hard offset shadows,
   2px ink rules, inspection seals, hatched "unverified" as a first-class state.
   System-theme via prefers-color-scheme on custom properties. */

:root {
  --paper: #F2F4F1;
  --surface: #FDFEFC;
  --ink: #16211F;
  --ink-dim: #3E4A46;
  --muted: #6E7573;
  --line: #C6CCC8;
  --line-strong: #16211F;
  --stamp: #2C51D8;
  --stamp-ink: #F2F4F1;   /* text on stamp-filled surfaces */
  --pass: #2F9E77;
  --fail: #8C2E1B;
  --warn: #8C6D1F;
  --seal-d: #A3541E;
  --hatch-a: #9AA19D;
  --hatch-b: #E4E7E3;
  --shadow: 8px 8px 0 rgba(22, 33, 31, 0.12);
  --inkblock-bg: #16211F;
  --inkblock-ink: #F2F4F1;
  --inkblock-edge: #16211F;
  --font-display: "Archivo", "Helvetica Neue", Arial, sans-serif;
  --font-body: "Public Sans", -apple-system, "Segoe UI", system-ui, sans-serif;
  --font-mono: "Spline Sans Mono", ui-monospace, "SF Mono", "Cascadia Code", Menlo, monospace;

  /* Fluid type. One scale, viewport-interpolated, so the four narrow
     breakpoints this site is checked at (320/360/390/414 portrait, 667×375
     and 844×390 landscape) are covered by the ramp rather than by four sets
     of overrides. Floors are chosen so nothing lands under 12.5px and body
     copy never drops below 16px — under 16px, iOS Safari zooms the page when
     a form control takes focus, and the page is then wider than the screen. */
  --step--2: clamp(0.78rem, 0.755rem + 0.13vw, 0.8125rem);  /* 12.5 → 13 */
  --step--1: clamp(0.875rem, 0.85rem + 0.13vw, 0.9375rem);  /* 14 → 15 */
  --step-0:  clamp(1rem, 0.98rem + 0.1vw, 1.0625rem);       /* 16 → 17 */
  --step-1:  clamp(1.0625rem, 1.02rem + 0.23vw, 1.1875rem); /* 17 → 19 */
  --step-2:  clamp(1.1875rem, 1.09rem + 0.48vw, 1.4375rem); /* 19 → 23 */
  --step-3:  clamp(1.4375rem, 1.24rem + 0.97vw, 1.875rem);  /* 23 → 30 */
  --step-4:  clamp(1.75rem, 1.32rem + 2.14vw, 2.875rem);    /* 28 → 46 */
  --step-5:  clamp(1.9375rem, 1.35rem + 2.94vw, 3.625rem);  /* 31 → 58 */

  /* The smallest thing a finger is expected to hit. */
  --tap: 44px;
  /* Page gutter — 16px at 320, 32px from ~800 up. */
  --gutter: clamp(1rem, 0.6rem + 2vw, 2rem);
}
@media (prefers-color-scheme: dark) {
  :root {
    --paper: #0F1416;
    --surface: #161C1E;
    --ink: #E8EDE9;
    --ink-dim: #B4BBB6;
    --muted: #8A918D;
    --line: #2A3134;
    --line-strong: #E8EDE9;
    --stamp: #7C9BFF;
    --stamp-ink: #0F1416;
    --pass: #45B08C;
    --fail: #D96C52;
    --warn: #C9A24C;
    --seal-d: #C77B3F;
    --hatch-a: #5A615D;
    --hatch-b: #232A2C;
    --shadow: 8px 8px 0 rgba(232, 237, 233, 0.10);
    --inkblock-edge: #2A3134;
  }
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: 1.6;
  /* `dvh`, not `vh`: on a phone the URL bar and toolbar come and go, and 100vh
     is the LARGEST of those states — so a `vh`-sized page overflows the screen
     the moment the chrome is showing. The dynamic unit tracks the real box.
     Column layout so a short page still pins its footer to the bottom. */
  min-block-size: 100dvh;
  display: flex;
  flex-direction: column;
  /* Nothing may push the page sideways. Long unbroken tokens (a 60-character
     repository name, a signing identity) are the usual culprit; they wrap
     instead. */
  overflow-wrap: break-word;
}
a { color: var(--stamp); }
code, pre, .mono { font-family: var(--font-mono); }
:focus-visible { outline: 2px solid var(--stamp); outline-offset: 2px; }

main {
  max-inline-size: 1200px;
  margin-inline: auto;
  inline-size: 100%;
  padding: 0 var(--gutter) 72px;
  flex: 1;
}

/* Clearance for the FIXED design switcher.
   It belongs on <body>, not on <main>: the switcher is fixed to the viewport,
   so scrolled to the end of the page it sits over whatever is last — and what
   is last is the FOOTER, which lives outside main. Padding on main reserved
   116px in the wrong place and the footer's two spans were still covered at
   390x844 (measured: switcher top 778, footer spans 770-790 and 806-826).
   The switcher's own script measures it and sets --switcher-clearance, because
   its height is not a constant: 56px at 390px wide, 102px at 320px where the
   links wrap onto three rows. The literal here is the no-JS fallback, sized
   for that 320px worst case. */
body { padding-block-end: var(--switcher-clearance, 132px); }

/* Accessibility floor, deliberately !important. Under 16px, iOS Safari zooms
   the viewport when a text field or select takes focus, and the page is then
   wider than the screen — the exact horizontal-overflow bug this whole pass
   exists to remove. A design may restyle these controls any way it likes; it
   may not put them back under 16px. Measured live: console #dir-filter was
   14px and #dir-sort 11px, chain 14.5px and 11px, manual #dir-sort 13.5px.
   Checkboxes are exempt — they carry no text and do not trigger the zoom. */
input:not([type="checkbox"]):not([type="radio"]), select, textarea {
  font-size: max(16px, 1em) !important;
}

/* Anything that cannot be made narrow scrolls INSIDE its own box. The rule
   the reference sites get wrong: scorecard.dev overflows at 390px
   (scrollWidth 438) because its check tables sit in an overflow-visible
   parent, so the whole document scrolls sideways instead of the table. */
.table-scroll, pre, .inkblock, .install-cmd, .trust pre, .exposure pre {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.hatch {
  background: repeating-linear-gradient(45deg, var(--hatch-a) 0 3px, var(--hatch-b) 3px 6px);
}

/* ---------- chrome ---------- */
.topbar { border-bottom: 2px solid var(--line-strong); }
.topbar-in {
  max-inline-size: 1200px; margin-inline: auto; padding: 14px var(--gutter);
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px 24px; flex-wrap: wrap;
}
.wordmark {
  font-family: var(--font-mono); font-weight: 700; font-size: 17px;
  letter-spacing: 0.02em; color: var(--ink); text-decoration: none;
}
.wordmark .caret { color: var(--stamp); }
/* Tap targets. Every nav link is at least 44px tall, which also fixes the
   observed defect where the wrapped second row ("GitHub ↗") sat indented
   under the first rather than aligned to an edge: the nav now starts at the
   inline start once it wraps. */
.topnav {
  display: flex; gap: 4px 20px; font-size: var(--step--1); font-weight: 500;
  flex-wrap: wrap; align-items: center;
}
.topnav a {
  color: var(--ink); text-decoration: none;
  display: inline-flex; align-items: center;
  min-block-size: var(--tap); padding-inline: 2px;
}
.topnav a:hover { color: var(--stamp); }
.topnav a.active { border-bottom: 3px solid var(--stamp); padding-bottom: 2px; }
.topnav a.ext { color: var(--stamp); }

.site-footer { border-top: 2px solid var(--line-strong); }
.footer-in {
  max-inline-size: 1200px; margin-inline: auto; padding: 18px var(--gutter);
  display: flex; justify-content: space-between; align-items: baseline; gap: 16px; flex-wrap: wrap;
  font-size: var(--step--2); color: var(--ink-dim);
}
.footer-in .domain { font-family: var(--font-mono); font-size: var(--step--2); }

/* ---------- shared atoms ---------- */
.eyebrow {
  font-family: var(--font-mono); font-size: var(--step--2); font-weight: 500;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--stamp);
}
.display-hl {
  font-family: var(--font-display); font-weight: 900;
  font-size: var(--step-5); line-height: 1.02;
  letter-spacing: -0.015em; text-transform: uppercase; margin: 0;
}
.page-title {
  font-family: var(--font-display); font-weight: 900;
  font-size: var(--step-4); line-height: 1.05;
  letter-spacing: -0.015em; text-transform: uppercase; margin: 0;
}
.h2-display {
  font-family: var(--font-display); font-weight: 900; font-size: var(--step-3);
  letter-spacing: -0.01em; margin: 0;
}
.lede { font-size: var(--step-1); line-height: 1.6; color: var(--ink-dim); max-inline-size: 58ch; margin: 0; }

.card {
  background: var(--surface);
  border: 2px solid var(--line-strong);
  box-shadow: var(--shadow);
  /* A card is often a grid/flex item; without this its content's intrinsic
     minimum becomes the track's minimum. */
  min-inline-size: 0;
}
.card-head {
  display: flex; justify-content: space-between; align-items: center; gap: 16px;
  border-bottom: 2px dashed var(--line); padding: 14px 22px;
  font-family: var(--font-mono);
}

.btn {
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--stamp); color: var(--stamp-ink);
  min-block-size: var(--tap); padding: 10px 20px;
  font-weight: 600; font-size: var(--step--1); text-decoration: none;
  border: 2px solid var(--stamp);
}
.btn:hover { filter: brightness(1.08); }
button.btn { font-family: var(--font-body); cursor: pointer; }
button.btn:disabled { opacity: 0.55; cursor: default; filter: none; }
.btn-outline {
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; color: var(--ink);
  min-block-size: var(--tap); padding: 10px 20px;
  font-weight: 600; font-size: var(--step--1); text-decoration: none;
  border: 2px solid var(--line-strong);
}
.btn-row { display: flex; gap: 14px; flex-wrap: wrap; }

.inkblock {
  background: var(--inkblock-bg); color: var(--inkblock-ink);
  border: 1px solid var(--inkblock-edge);
  font-family: var(--font-mono); font-size: var(--step--1); line-height: 1.9;
  padding: 20px 24px; margin: 0;
}

.arrow-link {
  display: inline-flex; align-items: center; min-block-size: var(--tap);
  font-weight: 600; font-size: var(--step--1); color: var(--ink);
  text-decoration: underline; text-underline-offset: 4px;
}

/* ---------- inspection seals ---------- */
.seal {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  width: 84px; height: 84px; flex-shrink: 0; border-radius: 50%;
  border: 3px solid var(--seal-color, var(--muted));
  color: var(--seal-color, var(--muted));
  font-family: var(--font-mono); font-weight: 700; font-size: 34px;
  transform: rotate(var(--seal-rot, 0deg));
}
.seal .seal-ring {
  position: absolute; inset: 4px; border-radius: 50%;
  border: 1.5px solid var(--seal-color, var(--muted));
}
.seal-74 { width: 74px; height: 74px; font-size: 30px; }
.seal-64 { width: 64px; height: 64px; font-size: 23px; }
.seal-44 { width: 44px; height: 44px; font-size: 17px; border-width: 2.5px; }
.seal-44 .seal-ring { inset: 3px; border-width: 1px; }
.seal-aplus, .seal-a, .seal-b { --seal-color: var(--pass); }
.seal-c { --seal-color: var(--warn); }
.seal-d { --seal-color: var(--seal-d); }
.seal-f { --seal-color: var(--fail); }
.seal-na { --seal-color: var(--muted); }
.provisional {
  display: inline-block; font-size: 11px; color: var(--warn);
  text-transform: uppercase; letter-spacing: 0.08em; margin-left: 8px;
}

/* ---------- phase bars ---------- */
.phase-bars { display: grid; gap: 7px; margin: 10px 0; }
/* The label column is the thing that will not fit on a phone, so it is
   fluid rather than fixed at 170px. */
.phase-row {
  display: grid; grid-template-columns: clamp(96px, 26%, 170px) minmax(0, 1fr) 48px;
  gap: 10px; align-items: center; font-size: var(--step--2);
}
.phase-bars-compact .phase-row { grid-template-columns: 34px minmax(0, 1fr) 48px; }
.phase-name { color: var(--muted); font-family: var(--font-mono); font-size: var(--step--2); }
.phase-pct {
  font-family: var(--font-mono); font-size: var(--step--2); text-align: end;
  font-variant-numeric: tabular-nums;
}
.bar { display: flex; gap: 2px; height: 10px; }
.bar-empty { font-size: 10px; color: var(--ink-dim); height: auto; font-family: var(--font-mono); }
.seg { height: 100%; }
.seg-pass { background: var(--pass); }
.seg-fail { background: var(--fail); }

/* ---------- home ---------- */
.hero {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(28px, 5vw, 56px);
  align-items: center; padding-block: clamp(32px, 6vw, 64px) clamp(32px, 5vw, 56px);
}
.hero-copy { display: flex; flex-direction: column; gap: 28px; }
.hero-cta { display: flex; gap: 16px; align-items: center; flex-wrap: wrap; }
/* `<pre>` defaults to white-space:pre, so a command one character longer than
   the box used to push the whole document sideways. It scrolls itself now. */
.install-cmd {
  background: var(--inkblock-bg); color: var(--inkblock-ink);
  border: 2px solid var(--inkblock-edge);
  font-family: var(--font-mono); font-size: var(--step--1);
  padding: 14px 18px; margin: 0; max-inline-size: 100%;
}

.receipt-head-title { font-size: var(--step--2); font-weight: 700; }
.receipt-head-ver { font-size: var(--step--2); color: var(--muted); }
/* The receipt is a terminal transcript: it may not wrap mid-line, so it keeps
   its own scroller rather than reflowing into nonsense.
   But it is also the page's PROOF ELEMENT, and a reader should not have to
   discover that a scroller exists to read it. Measured at 390px it was 351
   wide against 373 of content — 22px of the right-hand edge simply hidden,
   with nothing on screen saying so; at 320px, 86px hidden. So the type scales
   down on narrow viewports until the longest line fits, and the scroller stays
   only as the backstop it was meant to be. The `min()` cap means nothing
   changes from 414px up, where it already fit.
   Longest line is 40 characters; at ~0.6em per character that needs
   40 × 0.6 × font-size ≤ (viewport − page gutters − this padding). */
.receipt-body {
  font-family: var(--font-mono);
  font-size: min(var(--step--2), 3.45vw);
  line-height: 2.05;
  padding: 18px; overflow-x: auto;
}
@media (max-width: 400px) { .receipt-body { padding: 14px 12px; } }
.receipt-body > div { white-space: nowrap; }
.receipt-body .r-pass { color: var(--pass); font-weight: 700; }
.receipt-body .r-fail { color: var(--fail); font-weight: 700; }
.receipt-body .r-skip { color: var(--muted); font-weight: 700; }
.receipt-body .r-dim { color: var(--muted); }
.receipt-sum { border-top: 2px dashed var(--line); margin-top: 10px; padding-top: 10px; }
@media (prefers-reduced-motion: no-preference) {
  .receipt-body > div { opacity: 0; animation: receipt-print 0.45s ease-out forwards; }
  .receipt-body > div:nth-child(1) { animation-delay: 0.08s; }
  .receipt-body > div:nth-child(2) { animation-delay: 0.16s; }
  .receipt-body > div:nth-child(3) { animation-delay: 0.24s; }
  .receipt-body > div:nth-child(4) { animation-delay: 0.32s; }
  .receipt-body > div:nth-child(5) { animation-delay: 0.40s; }
  .receipt-body > div:nth-child(6) { animation-delay: 0.48s; }
  .receipt-body > div:nth-child(7) { animation-delay: 0.56s; }
  .receipt-body > div:nth-child(8) { animation-delay: 0.64s; }
}
@keyframes receipt-print {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}

.phase-strip {
  display: flex; border-top: 2px solid var(--line-strong);
  border-bottom: 2px solid var(--line-strong);
}
.phase-cell {
  flex: 1 1 0; padding: clamp(16px, 3vw, 30px) clamp(14px, 2.4vw, 28px);
  border-inline-end: 1px solid var(--line);
}
.phase-cell:last-child { border-inline-end: none; }
.phase-cell-eyebrow {
  font-family: var(--font-mono); font-size: var(--step--2); font-weight: 500;
  letter-spacing: 0.12em; color: var(--stamp);
}
.phase-cell-title {
  font-family: var(--font-display); font-weight: 700; font-size: var(--step-1);
  margin-block-start: 8px;
}
.phase-cell-copy { font-size: var(--step--1); color: var(--ink-dim); margin-block-start: 6px; line-height: 1.5; }

.twocol {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(28px, 5vw, 56px);
  padding-block: clamp(32px, 5vw, 56px) 16px; align-items: start;
}
.col-block { display: flex; flex-direction: column; gap: 16px; }
.col-block .body-copy { font-size: var(--step-0); line-height: 1.65; color: var(--ink-dim); margin: 0; }
.seal-demo { display: flex; align-items: center; gap: 18px; margin-top: 6px; }
.seal-demo-copy { font-size: var(--step--1); color: var(--ink-dim); line-height: 1.5; }
.code-chip {
  font-family: var(--font-mono); font-size: var(--step--1);
  background: var(--hatch-b); padding: 2px 7px; overflow-wrap: anywhere;
}

/* ---------- directory ---------- */
.page-head {
  padding-block: clamp(28px, 5vw, 52px) 24px;
  display: flex; justify-content: space-between; align-items: flex-end; gap: 40px; flex-wrap: wrap;
}
.page-head-copy { display: flex; flex-direction: column; gap: 14px; }
.page-head-copy .body-copy { font-size: var(--step-0); color: var(--ink-dim); max-inline-size: 60ch; line-height: 1.6; margin: 0; }

.dir-controls { margin: 8px 0 20px; }
.dir-controls-label {
  display: block; margin: 0 0 8px;
  font-family: var(--font-mono); font-size: var(--step--2); font-weight: 500;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted);
}
/* 16px is not a taste call: below it, iOS Safari zooms the viewport when the
   field takes focus and the page is then wider than the screen. */
#dir-filter {
  inline-size: 100%; max-inline-size: 520px; padding: 12px 16px;
  min-block-size: var(--tap);
  border: 2px solid var(--line-strong); background: var(--surface); color: var(--ink);
  font-family: var(--font-mono); font-size: 16px; border-radius: 0;
}
#dir-filter::placeholder { color: var(--muted); }

/* Scan-intake callout: revealed by filter.js when the query is a repo slug
   with no directory entry. Quiet — dashed rule, no shadow, not a hero. */
.dir-scan {
  max-inline-size: 520px; margin-block-start: 14px; padding: 18px;
  background: var(--surface); border: 2px dashed var(--line-strong);
}
.dir-scan-copy {
  margin: 0 0 14px; font-size: var(--step--1); color: var(--ink-dim);
  line-height: 1.55; max-inline-size: 52ch;
}
.dir-scan-status {
  margin-block-start: 12px; font-family: var(--font-mono); font-size: var(--step--2);
  color: var(--ink-dim); line-height: 1.6;
}
.dir-scan-status a { color: var(--stamp); }

.table-scroll { overflow-x: auto; }
table { border-collapse: collapse; width: 100%; }
th, td { text-align: left; padding: 12px 14px; vertical-align: top; }
thead th {
  font-family: var(--font-mono); font-size: var(--step--2); font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.1em; color: var(--ink-dim);
  border-bottom: 2px solid var(--line-strong); padding: 12px 14px;
}
tbody td { border-bottom: 1px solid var(--line); }

table.directory tbody tr { background: var(--surface); }
table.directory tbody td { padding: clamp(14px, 2.4vw, 24px) 12px; vertical-align: middle; }
.repo-cell { min-inline-size: 200px; }
.repo-name {
  font-family: var(--font-mono); font-size: var(--step-1); font-weight: 700;
  color: var(--ink); text-decoration: none;
  display: inline-flex; align-items: center; min-block-size: var(--tap);
}
.repo-name:hover { color: var(--stamp); }
.desc { display: block; font-size: var(--step--1); color: var(--muted); margin-block-start: 5px; }
.meta-line {
  display: block; font-family: var(--font-mono); font-size: var(--step--2);
  color: var(--ink-dim); margin-block-start: 5px;
}
.prov-flag { font-style: normal; color: var(--warn); }
.bars-cell { min-inline-size: 220px; }
.lane {
  display: inline-block; font-family: var(--font-mono); font-size: var(--step--2);
  padding: 5px 10px; text-align: center; white-space: nowrap;
}
.lane-ext { border: 1.5px solid var(--line-strong); color: var(--ink); }
.lane-auth { border: 1.5px solid var(--stamp); color: var(--stamp); font-weight: 700; }
.date-cell { font-family: var(--font-mono); font-size: var(--step--2); color: var(--ink-dim); white-space: nowrap; }

.key-row {
  display: flex; gap: 14px 26px; padding: 18px 0; align-items: center; flex-wrap: wrap;
  font-size: var(--step--2); color: var(--ink-dim);
}
.key-label { font-family: var(--font-mono); font-size: var(--step--2); color: var(--muted); }
.key-item { display: inline-flex; align-items: center; gap: 7px; }
.key-swatch { width: 22px; height: 9px; display: inline-block; }
.key-pass { background: var(--pass); }
.key-fail { background: var(--fail); }

/* ---------- repo detail ---------- */
.crumbs { margin-block-start: 28px; font-size: var(--step--1); font-family: var(--font-mono); }
.crumbs a { display: inline-flex; align-items: center; min-block-size: var(--tap); }
.repo-hero { display: flex; align-items: center; gap: 24px; margin: 28px 0 10px; flex-wrap: wrap; }
.repo-title {
  font-family: var(--font-display); font-weight: 900;
  font-size: var(--step-4); letter-spacing: -0.01em; margin: 0;
  overflow-wrap: anywhere;
}
.repo-meta { font-family: var(--font-mono); font-size: var(--step--2); color: var(--ink-dim); line-height: 1.9; overflow-wrap: anywhere; }
.score-line { font-size: var(--step-0); color: var(--ink-dim); }
.nudge {
  background: var(--surface); border: 2px solid var(--line-strong);
  box-shadow: var(--shadow); padding: clamp(18px, 3.5vw, 30px); margin-block: 36px;
}
.nudge-title { font-family: var(--font-display); font-weight: 900; font-size: var(--step-2); margin: 0 0 10px; }
.nudge .body-copy { color: var(--ink-dim); margin: 0 0 18px; }
.transparency-note { font-size: var(--step--1); color: var(--ink-dim); }
.controls-title { font-family: var(--font-display); font-weight: 900; font-size: var(--step-3); margin: 40px 0 12px; }
table.controls tbody tr { background: var(--surface); }
.oc-fail .outcome, .oc-gap .outcome { color: var(--fail); font-weight: 600; }
.oc-pass .outcome { color: var(--pass); font-weight: 600; }
.oc-unverified .outcome { color: var(--muted); }
.outcome { font-family: var(--font-mono); font-size: var(--step--1); white-space: nowrap; }
.out-of-scope { opacity: 0.55; }
.oos, .raw { font-size: var(--step--2); color: var(--muted); font-family: var(--font-mono); }
.reason { font-size: var(--step--2); color: var(--ink-dim); }
details summary {
  cursor: pointer; font-size: var(--step--1); color: var(--stamp);
  min-block-size: var(--tap); display: flex; align-items: center;
}
details ul { font-size: var(--step--2); color: var(--ink-dim); }

/* ---------- methodology ---------- */
.method-grid { display: grid; grid-template-columns: minmax(200px, 260px) minmax(0, 1fr); gap: 0; }
.rail { border-inline-end: 2px solid var(--line-strong); padding: 56px 24px 56px 0; }
.rail-sticky { position: sticky; top: 24px; }
.rail-head {
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.12em;
  color: var(--muted); padding-bottom: 16px;
}
.rail-item {
  display: flex; align-items: center; gap: 12px; padding-block: 10px;
  min-block-size: var(--tap);
  font-family: var(--font-mono); font-size: var(--step--1); color: var(--ink-dim);
  text-decoration: none;
}
.rail-item:hover { color: var(--stamp); }
.rail-item-first { font-weight: 700; color: var(--ink); }
.rail-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--stamp); flex-shrink: 0; }
.rail-item-sub { border-left: 2px solid var(--line); margin-left: 4px; padding-left: 20px; }
.method-main {
  padding: 56px 0 56px clamp(20px, 3.5vw, 48px); max-inline-size: 860px;
  min-inline-size: 0; display: flex; flex-direction: column; gap: 40px;
}
.method-section { display: flex; flex-direction: column; gap: 14px; }
.method-section-label {
  font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.12em;
  color: var(--stamp); font-weight: 500; text-transform: uppercase;
}
.honesty-body { padding: 20px; font-size: var(--step-0); line-height: 1.7; color: var(--ink-dim); }
.honesty-body strong { color: var(--ink); }
.seal-row { display: flex; gap: 18px; align-items: center; flex-wrap: wrap; }
.grade-copy { font-size: var(--step--1); color: var(--ink-dim); line-height: 1.65; }
.mv { font-size: 14px; color: var(--muted); font-family: var(--font-mono); text-transform: none; letter-spacing: 0; }

.prose { color: var(--ink-dim); }
.prose h2 {
  font-family: var(--font-display); font-weight: 900; font-size: var(--step-2);
  color: var(--ink); margin: 0 0 12px;
}
.prose p, .prose ol, .prose ul { margin: 0 0 14px; }
.prose strong { color: var(--ink); }
.prose li { margin-bottom: 6px; }
.method-table td { font-size: var(--step--1); color: var(--ink-dim); }
.method-table { min-inline-size: 560px; }
.method-table code { font-size: 12.5px; }
.method-table strong { color: var(--ink); }

/* ---------- responsive ----------
   Most of the adaptation is already done by the fluid scale and the logical
   properties above; these are the layout changes a ramp cannot express.
   Checked at 320 / 360 / 390 / 414 portrait and 667×375 / 844×390 landscape —
   `document.documentElement.scrollWidth` must equal the viewport width at
   every one of them. */
@media (max-width: 900px) {
  /* `minmax(0, 1fr)`, not `1fr`: a bare `1fr` track carries an implicit
     min-width:auto, so the receipt card's non-wrapping transcript lines set
     the column's floor and pushed the whole document 88px wide at 320. */
  .hero, .twocol { grid-template-columns: minmax(0, 1fr); gap: 32px; }
  /* The phase strip wraps rather than stacking into five full-width rows: at
     390px five stacked cells is 5 screens of scrolling for five words each. */
  .phase-strip { flex-wrap: wrap; }
  .phase-cell { flex: 1 1 clamp(140px, 44%, 240px); border-block-end: 1px solid var(--line); }
  .phase-cell:last-child { border-inline-end: none; }
  .method-grid { grid-template-columns: 1fr; }
  .rail { border-inline-end: none; border-block-end: 2px solid var(--line-strong); padding: 24px 0 16px; }
  .rail-sticky { position: static; }
  .method-main { padding: 32px 0; }
}

/* Landscape phones (667×375, 844×390): the constraint is HEIGHT, not width.
   A hero sized for a tall viewport pushes everything below the fold. */
@media (max-height: 460px) and (orientation: landscape) {
  .hero { padding-block: 20px 24px; }
  .display-hl { font-size: clamp(1.5rem, 3.4vh + 1rem, 2.25rem); }
  .page-head { padding-block: 18px 14px; }
  .rail-sticky { position: static; }
}

@media (max-width: 640px) {
  /* The seal and its caption stop competing for a 320px line. */
  .seal-demo { flex-direction: column; align-items: flex-start; gap: 12px; }
  .repo-hero { gap: 14px; }
  .key-row { gap: 10px 18px; }
  .dir-count { margin-inline-start: 0; }
  /* The switcher is a trial artifact and it sat ON TOP of the receipt card at
     phone width. Centred and full-width-capped, it now behaves like a bar. */
  .design-switcher {
    inset-inline: 10px auto; inset-block-end: 10px;
    max-inline-size: calc(100vw - 20px);
  }
}

/* Reduced motion: the receipt's line-by-line print is decorative. The
   `no-preference` rule above already gates it, and this makes the intent
   explicit for anything added later. */
@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;
  }
  .receipt-body > div { opacity: 1; }
}

/* ---------- home: search, panels, cards ---------- */
.hero-copy .hp-search { margin-block: 4px; }
.hp-search-label {
  display: block; margin-block-end: 8px;
  font-family: var(--font-mono); font-size: var(--step--2); font-weight: 500;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted);
}
.hp-search-input {
  inline-size: 100%; max-inline-size: 520px; padding: 12px 16px;
  min-block-size: var(--tap);
  border: 2px solid var(--line-strong); background: var(--surface); color: var(--ink);
  font-family: var(--font-mono); font-size: 16px; border-radius: 0;
}
.hp-search-input::placeholder { color: var(--muted); }
.hp-chips {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  margin-block: 10px 0; font-size: var(--step--2);
}
.hp-chips-label {
  font-family: var(--font-mono); font-size: var(--step--2);
  text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted);
}
.hp-chip {
  display: inline-flex; align-items: center; min-block-size: 36px;
  padding: 4px 10px; border: 1.5px solid var(--line);
  font-family: var(--font-mono); font-size: var(--step--2);
  color: var(--ink); text-decoration: none; background: var(--surface);
}
.hp-chip:hover { border-color: var(--stamp); color: var(--stamp); }
/* Results and prompts render as a relative block that pushes the page down,
   never as a floating dropdown — an overlay is the difference between usable
   and unusable on a phone. */
.dir-found {
  display: flex; flex-wrap: wrap; align-items: center; gap: 12px;
  max-inline-size: 520px; margin-block-start: 14px; padding: 14px 16px;
  background: var(--surface); border: 2px solid var(--pass);
}
.dir-found-copy { margin: 0; font-size: var(--step--1); color: var(--ink-dim); }
/* `display: flex` on a class beats the user-agent's `[hidden] { display: none }`,
   so without this the "already listed" block is visible on every page load —
   it announced a match before anything had been typed. */
.dir-found[hidden], .dir-scan[hidden], [hidden] { display: none !important; }

.hero-count { font-size: var(--step--1); color: var(--ink-dim); margin: 0; }

.hp-panels {
  display: grid; gap: clamp(28px, 5vw, 48px);
  padding-block: clamp(32px, 5vw, 56px);
}
.hp-panel, .tx-strip { container-type: inline-size; min-inline-size: 0; }
.hp-panel-eyebrow {
  font-family: var(--font-mono); font-size: var(--step--2); font-weight: 500;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--stamp);
  margin: 0 0 6px;
}
.hp-panel-title {
  font-family: var(--font-display); font-weight: 900; font-size: var(--step-3);
  letter-spacing: -0.01em; margin: 0;
}
.hp-panel-line {
  font-size: var(--step-0); color: var(--ink-dim); margin: 8px 0 20px;
  max-inline-size: 60ch;
}

/* Container queries, not media queries: how many cards fit is a property of
   the PANEL's width, not the window's. The same panel dropped into a narrow
   column later will collapse correctly without a new breakpoint. */
.hp-cards { display: grid; grid-template-columns: 1fr; gap: 16px; }
@container (min-width: 640px) {
  .hp-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@container (min-width: 900px) {
  .hp-cards { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; }
}

/* Fixed height, clamped text. A 60-character name and a 400-character
   description have to produce the same grid, or the first unusual listing
   reflows the panel into a mess. */
.hp-card {
  display: grid; grid-template-rows: auto auto 1fr auto auto; gap: 8px;
  min-block-size: 224px;
  padding: 16px; text-decoration: none; color: var(--ink);
  background: var(--surface); border: 2px solid var(--line-strong);
  box-shadow: 6px 6px 0 rgba(22, 33, 31, 0.10);
}
@media (prefers-color-scheme: dark) {
  .hp-card { box-shadow: 6px 6px 0 rgba(232, 237, 233, 0.08); }
}
.hp-card:hover { border-color: var(--stamp); }
.hp-card-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.hp-grade {
  display: inline-flex; align-items: center; justify-content: center;
  inline-size: 40px; block-size: 40px; border-radius: 50%; flex-shrink: 0;
  border: 2.5px solid var(--seal-color, var(--muted)); color: var(--seal-color, var(--muted));
  font-family: var(--font-mono); font-weight: 700; font-size: var(--step--1);
}
.hp-grade-aplus, .hp-grade-a, .hp-grade-b { --seal-color: var(--pass); }
.hp-grade-c { --seal-color: var(--warn); }
.hp-grade-d { --seal-color: var(--seal-d); }
.hp-grade-f { --seal-color: var(--fail); }
.hp-grade-na { --seal-color: var(--muted); }
.hp-src {
  font-family: var(--font-mono); font-size: var(--step--2); color: var(--ink-dim);
  text-align: end; line-height: 1.3;
}
.hp-card-name {
  font-family: var(--font-mono); font-size: var(--step-0); font-weight: 700;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.hp-card-desc {
  font-size: var(--step--1); color: var(--muted); line-height: 1.45;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  line-clamp: 2; overflow: hidden;
}
.hp-card-facts {
  display: flex; flex-wrap: wrap; gap: 4px 12px;
  font-family: var(--font-mono); font-size: var(--step--2); color: var(--ink-dim);
  border-block-start: 1px dashed var(--line); padding-block-start: 8px;
}
.hp-fact-date { margin-inline-start: auto; }
.hp-card-note {
  font-size: var(--step--2); color: var(--warn); line-height: 1.4;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  line-clamp: 2; overflow: hidden;
}

/* A panel below its threshold says what it is waiting for, out loud. A panel
   that silently starts meaning something is worse than one that explains its
   own emptiness — nobody could audit when the ranking switched on. */
.hp-waiting {
  padding: clamp(16px, 3vw, 24px);
  background: var(--surface); border: 2px dashed var(--line-strong);
  display: flex; flex-direction: column; gap: 12px; align-items: flex-start;
}
.hp-waiting-copy {
  margin: 0; font-size: var(--step--1); color: var(--ink-dim);
  line-height: 1.55; max-inline-size: 62ch;
}
.hp-waiting-link {
  font-weight: 600; font-size: var(--step--1); color: var(--ink);
  text-decoration: underline; text-underline-offset: 4px;
  display: inline-flex; align-items: center; min-block-size: var(--tap);
}

.hp-unans { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.hp-unans-row {
  display: grid; gap: 4px 12px; align-items: center;
  grid-template-columns: minmax(0, 1fr);
  padding-block-end: 10px; border-block-end: 1px solid var(--line);
}
@container (min-width: 620px) {
  .hp-unans-row {
    grid-template-columns: minmax(140px, 1fr) minmax(80px, 2fr) auto minmax(0, 2fr);
  }
}
.hp-unans-id { font-family: var(--font-mono); font-size: var(--step--1); overflow-wrap: anywhere; }
.hp-unans-q { font-size: var(--step--1); color: var(--ink); line-height: 1.4; }
.hp-unans-q .hp-unans-id {
  display: block; font-family: var(--font-mono); font-size: var(--step--2);
  color: var(--muted); margin-block-start: 2px;
}
.tx-questions { margin-block-start: 24px; }
.tx-q-table { min-inline-size: 640px; }
.tx-q-groups { font-family: var(--font-mono); white-space: nowrap; }

.hp-unans-track { display: block; block-size: 8px; background: var(--hatch-b); }
.hp-unans-fill {
  display: block; block-size: 100%;
  background: repeating-linear-gradient(45deg, var(--hatch-a) 0 3px, var(--hatch-b) 3px 6px);
}
.hp-unans-count {
  font-family: var(--font-mono); font-size: var(--step--2); color: var(--ink-dim);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.hp-unans-why { font-size: var(--step--2); color: var(--muted); }
.hp-unans-foot {
  font-size: var(--step--1); color: var(--ink-dim); line-height: 1.55;
  max-inline-size: 68ch; margin-block-start: 16px;
}
.hp-more {
  display: inline-flex; align-items: center; min-block-size: var(--tap);
  font-weight: 600; font-size: var(--step--1); color: var(--ink);
  text-decoration: underline; text-underline-offset: 4px;
}

/* ---------- the attack-class taxonomy ---------- */
.tx-strip { padding-block: clamp(24px, 4vw, 40px); border-block-start: 2px solid var(--line-strong); }
.tx-chips { display: grid; grid-template-columns: 1fr; gap: 8px; margin-block-end: 18px; }
@container (min-width: 560px) { .tx-chips { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@container (min-width: 880px) { .tx-chips { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.tx-chip {
  display: flex; align-items: center; gap: 10px;
  min-block-size: var(--tap); padding: 8px 12px;
  background: var(--surface); border: 1.5px solid var(--line);
  color: var(--ink); text-decoration: none; font-size: var(--step--1);
}
.tx-chip:hover { border-color: var(--stamp); color: var(--stamp); }
.tx-chip-id {
  font-family: var(--font-mono); font-weight: 700; font-size: var(--step--2);
  color: var(--stamp); flex-shrink: 0;
}
.tx-classes { display: grid; gap: 20px; }
.tx-class {
  padding: 16px; background: var(--surface);
  border-inline-start: 3px solid var(--line-strong);
}
.tx-class-title {
  font-family: var(--font-display); font-weight: 900; font-size: var(--step-1);
  margin: 0 0 6px; color: var(--ink);
}
.tx-class-line { margin: 0 0 8px; font-size: var(--step-0); color: var(--ink); }
.tx-class-controls { margin: 0 0 8px; font-size: var(--step--1); overflow-wrap: anywhere; }
.tx-label {
  font-family: var(--font-mono); font-size: var(--step--2);
  text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted);
  margin-inline-end: 6px;
}
.tx-lineage {
  margin: 8px 0 0; font-family: var(--font-mono); font-size: var(--step--2);
  color: var(--muted);
}
.tx-incidents { list-style: none; margin: 10px 0 0; padding: 0; display: grid; gap: 12px; }
.tx-incident { display: grid; gap: 3px; font-size: var(--step--1); }
.tx-incident-when { font-family: var(--font-mono); font-size: var(--step--2); color: var(--muted); }
.tx-incident-what { color: var(--ink-dim); line-height: 1.5; }
.tx-reported {
  display: inline-block; font-family: var(--font-mono); font-size: var(--step--2);
  color: var(--warn); border: 1px solid var(--warn); padding: 0 6px;
  margin-inline-start: 6px;
}
.tx-sourcing { font-size: var(--step--1); color: var(--ink-dim); }
.tx-defs { font-size: var(--step-0); color: var(--ink-dim); line-height: 1.6; }
.tx-class-posture { border-inline-start-color: var(--muted); border-inline-start-style: dashed; }

/* ---------- per-repository exposure panel ---------- */
.exposure {
  margin-block: 32px; padding: clamp(16px, 3vw, 26px);
  background: var(--surface); border: 2px solid var(--line-strong);
}
.exposure .body-copy { color: var(--ink-dim); font-size: var(--step--1); line-height: 1.55; margin: 0 0 18px; }
.ex-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; }
.ex-row {
  display: grid; gap: 5px;
  padding-inline-start: 12px; border-inline-start: 3px solid var(--line);
}
/* Deliberately NOT a severity ramp. The scan measured whether checks are
   present, not how likely or costly an attack is, so it has no basis for
   calling one group scarier than another. These mark the EVIDENCE state. */
.ex-none-found { border-inline-start-color: var(--fail); }
.ex-partial { border-inline-start-color: var(--warn); }
.ex-evidenced { border-inline-start-color: var(--pass); }
.ex-not-observed { border-inline-start-color: var(--muted); border-inline-start-style: dashed; }
.ex-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 6px 14px; }
.ex-name {
  font-weight: 600; font-size: var(--step-0); color: var(--ink); text-decoration: none;
  display: inline-flex; align-items: center; gap: 8px; min-block-size: 32px;
}
.ex-name:hover { color: var(--stamp); }
.ex-state {
  font-family: var(--font-mono); font-size: var(--step--2);
  text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted);
}
.ex-line { font-size: var(--step--1); color: var(--ink-dim); }
.ex-detail { font-size: var(--step--2); color: var(--ink-dim); line-height: 1.5; overflow-wrap: anywhere; }
.ex-detail-quiet { color: var(--muted); }
.ex-detail-label {
  font-family: var(--font-mono); text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--muted); margin-inline-end: 6px;
}
.ex-foot {
  margin-block-start: 18px; font-size: var(--step--2); color: var(--muted);
  line-height: 1.55; overflow-wrap: anywhere;
}


/* ---------- tap targets, measured ----------
   Every one of these was under 44px in a real 390px render and is a standalone
   control, not a link inside a sentence (WCAG 2.5.8 exempts those). */
.wordmark {
  display: inline-flex; align-items: center; min-block-size: var(--tap);
}
.dir-controls-label, .hp-search-label {
  display: flex; align-items: flex-end; min-block-size: var(--tap);
  padding-block-end: 6px;
}
/* A 20px checkbox needs its label to supply the target. */
.dir-check, .dir-sortbar label { min-block-size: var(--tap); display: inline-flex; align-items: center; }
.design-switcher a { min-block-size: var(--tap); }
.hp-chip { min-block-size: var(--tap); }

/* ---------- inline term definitions ---------- */
.term { color: var(--ink); }
.term-def { color: var(--muted); font-style: italic; }
.key-note {
  font-size: var(--step--1); color: var(--ink-dim); line-height: 1.6;
  max-inline-size: 70ch; margin-block: 6px 24px;
}

/* ---------- provenance: lane markers + trust section ---------- */
.lane-verified { background: color-mix(in srgb, var(--pass) 18%, transparent); color: var(--pass); }
.lane-unsigned-action { background: color-mix(in srgb, #D9A441 24%, transparent); color: #8A5A00; }
.lane-external { background: color-mix(in srgb, var(--muted) 18%, transparent); color: var(--muted); }
/* Local lane: deliberately quieter than the verified mark — attributable, but
   weaker evidence than a record the repository's own CI produced. */
.lane-local {
  background: color-mix(in srgb, var(--ink-dim) 12%, transparent);
  color: var(--ink-dim); border: 1px dashed var(--line-strong);
}
.lane-local-overlay {
  margin-left: 6px; font-size: 11px; padding: 4px 7px;
  background: transparent; color: var(--ink-dim); border: 1px dashed var(--line-strong);
}
.repo-hero .lane { align-self: center; }
.trust { border-left: 3px solid var(--pass); padding: 6px 20px; margin: 32px 0; }
.trust-unsigned { border-left-color: #D9A441; }
.trust-local { border-left-style: dashed; border-left-color: var(--ink-dim); }
.trust-coverage { border-left-color: var(--warn); }
.trust pre { overflow-x: auto; font-family: var(--font-mono); font-size: 13px; background: var(--surface); padding: 12px 14px; }
.cov-note {
  display: block; margin-block-start: 6px; font-size: var(--step--2); line-height: 1.5;
  color: var(--warn); max-inline-size: 62ch;
}
.cov-note code {
  font-family: var(--font-mono); font-size: var(--step--2);
  background: var(--surface); padding: 1px 5px; overflow-wrap: anywhere;
}
.dir-sortbar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px;
  margin-block-start: 12px; font-size: var(--step--2); color: var(--ink-dim);
}
.dir-sortbar label { font-family: var(--font-mono); font-size: var(--step--2); color: var(--muted); }
/* 16px again — a <select> under 16px zooms iOS on focus exactly like an input. */
.dir-sortbar select {
  font-family: var(--font-body); font-size: 16px;
  min-block-size: var(--tap); padding: 6px 10px;
  border: 1.5px solid var(--line-strong);
  background: var(--surface); color: var(--ink); max-inline-size: 100%;
}
.dir-check {
  display: inline-flex; align-items: center; gap: 8px; cursor: pointer;
  min-block-size: var(--tap); font-size: var(--step--2);
}
.dir-check input[type="checkbox"] { inline-size: 20px; block-size: 20px; flex-shrink: 0; }
.dir-count { margin-inline-start: auto; font-family: var(--font-mono); font-size: var(--step--2); color: var(--muted); }
@media (prefers-color-scheme: dark) {
  .lane-unsigned-action { color: #E3B96A; }
  .trust-unsigned { border-left-color: #E3B96A; }
}

/* ── Design switcher (four-up trial) ─────────────────────────────────── */
.design-switcher {
  position: fixed; inset-inline-end: 18px; inset-block-end: 18px; z-index: 50;
  display: flex; align-items: center; gap: 2px; flex-wrap: wrap;
  max-inline-size: calc(100vw - 20px);
  background: var(--surface); border: 2px solid var(--ink);
  box-shadow: 4px 4px 0 rgba(22, 33, 31, 0.12);
  padding: 4px 6px; font-family: var(--font-mono); font-size: var(--step--2);
}
.design-switcher .ds-label {
  color: var(--muted); letter-spacing: 0.08em; text-transform: uppercase;
  font-size: var(--step--2); margin-inline-end: 6px;
}
.design-switcher a {
  color: var(--ink); text-decoration: none; padding: 6px 10px;
  display: inline-flex; align-items: center; min-block-size: var(--tap);
}
.design-switcher a:hover { color: var(--stamp); }
.design-switcher a[aria-current="true"] {
  background: var(--ink); color: var(--paper);
}
@media (max-width: 640px) { .design-switcher { right: 10px; bottom: 10px; } }

/* --- Scorecard comparison -------------------------------------------------
   Coverage is carried by a WORD ("Also checked" / "Partly" / "Not checked"),
   with colour only reinforcing it — the same rule the rest of the site
   follows, so the table survives being read aloud or printed in mono. */
.cmp-table { min-inline-size: 720px; }
.cmp-risk { color: var(--muted); font-size: 11.5px; text-transform: uppercase; letter-spacing: 0.06em; }
.cmp-mark { font-size: 12px; font-weight: 600; white-space: nowrap; }
.cmp-mark.cmp-covered { color: var(--pass); }
.cmp-mark.cmp-partial { color: var(--warn); }
.cmp-mark.cmp-none    { color: var(--muted); }
.cmp-note { margin-block-start: 0.35rem; color: var(--muted); font-size: 12px; line-height: 1.45; }
.cmp-footnote { color: var(--muted); font-size: 12px; }
.cmp-section td .cmp-none { font-variant-numeric: tabular-nums; }
