/* Shared foundation for the sub-pages (security, changelog).
   index.html still carries its own copy inline; that duplication is deliberate for now
   rather than refactoring a page that is already live. If a third page appears, move
   index.html onto this file and delete its inline base. */

@font-face {
  font-family: Outfit; src: url('/fonts/Outfit-var.woff2') format('woff2');
  font-weight: 300 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'JetBrains Mono'; src: url('/fonts/JetBrainsMono-var.woff2') format('woff2');
  font-weight: 400 500; font-style: normal; font-display: swap;
}

:root {
  --bg: #080808;
  --fg: #f2f2f2;
  --f72: rgba(242,242,242,0.72);
  --f60: rgba(242,242,242,0.6);
  --f55: rgba(242,242,242,0.55);
  --f45: rgba(242,242,242,0.54);
  --f40: rgba(242,242,242,0.5);
  --f35: rgba(242,242,242,0.5);
  --hair: rgba(255,255,255,0.05);
  --ring: rgba(255,255,255,0.07);
  --ok: #5fd88a;
  --warn: #e0b155;
  --sans: Outfit, system-ui, -apple-system, sans-serif;
  --mono: 'JetBrains Mono', ui-monospace, Menlo, monospace;
}

* { box-sizing: border-box; }
/* Must precede every rule that sets `display`: the UA enforces the `hidden` attribute
   with `[hidden]{display:none}`, and ANY author `display` declaration outranks it
   regardless of specificity. `.cpanel` declares display:flex, so without this the
   contact panel sat in the layout on every sub-page: off-screen via translateX, but
   still tabbable and still announced as an open dialog. app.css carries the same rule
   for the same reason. */
[hidden] { display: none !important; }
html { scroll-behavior: smooth; }
body {
  margin: 0; background: var(--bg); color: var(--fg);
  font-family: var(--sans); -webkit-font-smoothing: antialiased;
}
a { color: var(--fg); text-decoration-color: rgba(242,242,242,0.4); }
a:hover { color: #fff; text-decoration-color: #fff; }
h1, h2, h3 { margin: 0; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

/* Audit W7. The first thing Tab reaches on every page: off-screen until focused, then on
   top of the header. <main tabindex="-1"> takes the focus it hands over, and draws no
   ring for it, because a ring round the whole page says nothing. */
.skip {
  position: absolute; left: 16px; top: -100px; z-index: 100;
  background: #fbfbfb; color: #0a0a0a; font-size: 14px; font-weight: 600;
  padding: 10px 16px; border-radius: 9px; text-decoration: none;
}
.skip:focus { top: 16px; }
main:focus { outline: none; }
/* Read by a screen reader, not drawn: table captions whose job the heading above
   already does for sighted readers. */
.vh {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.wrap { max-width: 860px; margin: 0 auto; padding: 0 40px; }

/* ── top bar ───────────────────────────────────────────── */
.top {
  display: flex; align-items: center; justify-content: space-between;
  gap: 24px; flex-wrap: wrap; padding: 34px 40px 0;
  max-width: 1180px; margin: 0 auto;
}
/* The logo is two 8px bars, so the link was 69x8 and far under the 24px minimum
   target (WCAG 2.5.8, audit W9). The padding makes the hit area 28px tall; the negative
   margin keeps the header exactly where it was. */
.mark { display: flex; align-items: center; gap: 5px; text-decoration: none; padding: 10px 0; margin: -10px 0; }
.mark i { display: block; height: 8px; background: var(--fg); flex: none; }
.mark i:first-child { width: 8px; }
.mark i:last-child { width: 56px; }
/* Wraps rather than pushing the page sideways at 320px (audit W6). */
.topnav { display: flex; flex-wrap: wrap; gap: 10px 24px; font-size: 14px; }
.topnav a, .topnav button { color: var(--f55); text-decoration: none; font-size: 14px; }
.topnav a:hover, .topnav button:hover, .topnav a[aria-current] { color: var(--fg); }

/* ── page head ─────────────────────────────────────────── */
.phead { padding: 90px 0 0; }
.phead h1 {
  font-size: clamp(34px, 5vw, 52px); line-height: 1.1; font-weight: 600;
  letter-spacing: -0.025em; text-wrap: pretty;
}
.phead p { margin: 20px 0 0; font-size: 17px; line-height: 1.62; color: var(--f72); text-wrap: pretty; }
.updated { margin-top: 18px; font-family: var(--mono); font-size: 11px; letter-spacing: 0.08em; color: var(--f40); }

/* ── content ───────────────────────────────────────────── */
.sec { padding: 64px 0 0; }
.sec h2 { font-size: 27px; line-height: 1.2; font-weight: 600; letter-spacing: -0.02em; text-wrap: pretty; }
.sec h3 { margin-top: 34px; font-size: 18px; font-weight: 600; letter-spacing: -0.01em; }
.sec p { margin: 16px 0 0; font-size: 16px; line-height: 1.7; color: var(--f72); text-wrap: pretty; }
.sec p.dim { color: var(--f55); font-size: 15px; }
.sec ul { margin: 16px 0 0; padding-left: 0; list-style: none; }
.sec ul li {
  position: relative; padding-left: 20px; margin-bottom: 12px;
  font-size: 16px; line-height: 1.65; color: var(--f72);
}
.sec ul li::before {
  content: ''; position: absolute; left: 2px; top: 11px;
  width: 5px; height: 5px; border-radius: 3px; background: #3a3a3a;
}
.sec b, .sec strong { color: var(--fg); font-weight: 600; }
code, .mono { font-family: var(--mono); font-size: 0.9em; }
code { color: var(--fg); background: rgba(255,255,255,0.05); padding: 2px 6px; border-radius: 5px; }

.rule { height: 1px; background: rgba(255,255,255,0.08); margin-top: 64px; }

/* A statement worth reading twice, not a decorated aside. */
.claim {
  margin-top: 26px; border-radius: 14px; background: rgba(255,255,255,0.028);
  box-shadow: inset 0 0 0 1px var(--ring); padding: 24px 26px;
}
.claim p:first-child { margin-top: 0; }
.claim.warn { box-shadow: inset 0 0 0 1px rgba(224,177,85,0.34); background: rgba(224,177,85,0.05); }
.claim.warn b { color: var(--warn); }

/* Ordered steps for a mechanism the reader is meant to follow. */
ol.steps { margin: 22px 0 0; padding: 0; list-style: none; counter-reset: s; }
ol.steps li {
  counter-increment: s; position: relative; padding-left: 42px; margin-bottom: 20px;
  font-size: 16px; line-height: 1.65; color: var(--f72);
}
ol.steps li::before {
  content: counter(s); position: absolute; left: 0; top: -1px;
  width: 26px; height: 26px; border-radius: 50%; box-shadow: inset 0 0 0 1px var(--ring);
  display: grid; place-items: center; font-family: var(--mono); font-size: 12px; color: var(--f55);
}

table.facts { width: 100%; border-collapse: collapse; margin-top: 22px; }
table.facts th, table.facts td {
  text-align: left; padding: 15px 0; border-bottom: 1px solid rgba(255,255,255,0.07);
  font-size: 15px; line-height: 1.5; font-weight: 400; vertical-align: top;
}
table.facts th { color: var(--f72); padding-right: 24px; }
table.facts td { width: 190px; color: var(--f45); }
table.facts td.no { color: var(--ok); }
table.facts td.yes { color: var(--warn); }

pre.term {
  margin: 22px 0 0; border-radius: 12px; background: #0d0d0d;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.08); padding: 20px 22px;
  font-family: var(--mono); font-size: 12.5px; line-height: 1.9; color: var(--f72);
  overflow-x: auto;
}
pre.term .c { color: var(--f40); }
pre.term:focus-visible { outline: 2px solid #4a6cf7; outline-offset: 2px; }

/* ── changelog ─────────────────────────────────────────── */
.rel { padding-top: 42px; }
.rel-head { display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap; }
.rel-head h2 { font-size: 24px; }
.rel-date { font-family: var(--mono); font-size: 12px; color: var(--f40); }
.chip {
  font-size: 11px; font-weight: 500; color: var(--ok); padding: 3px 10px;
  border-radius: 999px; box-shadow: inset 0 0 0 1px rgba(95,216,138,0.55);
}

/* ── footer ────────────────────────────────────────────── */
.foot { max-width: 1180px; margin: 0 auto; padding: 110px 40px 46px; }
.foot-bar {
  display: flex; align-items: center; justify-content: space-between; gap: 20px; flex-wrap: wrap;
  padding-top: 26px; border-top: 1px solid rgba(255,255,255,0.08);
  font-size: 13.5px; color: var(--f45);
}
.foot-links { display: flex; gap: 26px; flex-wrap: wrap; }
.foot-links a, .foot-links button { text-decoration: none; color: var(--f45); font-size: 13.5px; }
.foot-links a:hover, .foot-links button:hover { color: var(--fg); }

/* ── contact panel ─────────────────────────────────────── */
.cscrim {
  position: fixed; inset: 0; background: rgba(4,4,4,0.6); z-index: 60;
  opacity: 0; pointer-events: none; transition: opacity 0.3s ease;
}
.cscrim.open { opacity: 1; pointer-events: auto; }
.cpanel {
  position: fixed; top: 0; right: 0; bottom: 0; width: min(440px, 100%); z-index: 61;
  background: #101010; box-shadow: -24px 0 60px rgba(0,0,0,0.55), inset 1px 0 0 rgba(255,255,255,0.08);
  transform: translateX(100%); transition: transform 0.42s cubic-bezier(0.22,0.8,0.2,1);
  display: flex; flex-direction: column; overflow-y: auto;
}
.cpanel.open { transform: none; }
@media (prefers-reduced-motion: reduce) { .cpanel, .cscrim { transition: none; } }
.cpanel-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; padding: 30px 30px 0; }
.cpanel-head h2 { font-size: 24px; font-weight: 600; letter-spacing: -0.02em; }
.cpanel-head p { margin: 8px 0 0; font-size: 14px; line-height: 1.6; color: var(--f55); }
.cclose {
  flex: none; width: 32px; height: 32px; border-radius: 8px; display: grid; place-items: center;
  color: var(--f45); transition: background 0.2s ease, color 0.2s ease;
}
.cclose:hover { background: rgba(255,255,255,0.07); color: var(--fg); }
.cform { padding: 26px 30px 34px; display: flex; flex-direction: column; gap: 18px; }
.clabel { display: block; font-family: var(--mono); font-size: 12px; letter-spacing: 0.16em; color: var(--f35); margin-bottom: 9px; }
.creq { margin: 0; font-size: 13px; color: var(--f55); }
/* The field edge is the only thing that says "type here", so it needs 3:1 against
   both the panel and the field's own fill (WCAG 1.4.11, audit W9). 0.09 was 1.26:1. */
.cinput, .ctext {
  width: 100%; font: 400 14px/1.5 var(--sans); color: var(--fg);
  background: rgba(255,255,255,0.04); border: 0; border-radius: 9px; padding: 11px 13px;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.42); outline: 0; transition: box-shadow 0.2s ease;
}
.ctext { resize: vertical; min-height: 132px; }
.cinput::placeholder, .ctext::placeholder { color: rgba(242,242,242,0.5); }
.cinput:focus, .ctext:focus { box-shadow: inset 0 0 0 1.5px #4a6cf7; }
/* Only after somebody has tried to send, not while they are still typing. */
.cinput:user-invalid, .ctext:user-invalid { box-shadow: inset 0 0 0 1.5px #ef6a5a; }
.csend {
  width: 100%; background: #fbfbfb; color: #0a0a0a; font-size: 15px; font-weight: 600;
  padding: 13px 24px; border-radius: 999px; transition: opacity 0.2s ease;
}
.csend:hover { opacity: 0.88; }
.cnote { font-size: 12.5px; line-height: 1.6; color: var(--f40); }
.cnote a { color: var(--f55); }

@media (max-width: 700px) {
  .wrap { padding: 0 24px; }
  .top { padding: 24px 24px 0; }
  .foot { padding: 80px 24px 40px; }
  .phead { padding-top: 56px; }
  table.facts td { width: 120px; }
}

/* ══ scroll reveals ═══════════════════════════════════════════════════════════
   Same arrangement as index.html, and for the same reason: the design drove these
   with animation-timeline:view(), which Safari does not support, and this site sells
   a Mac app. Every section would have been stuck at opacity 0 for most visitors.

   Gated behind html.js, which site.js adds as its first act, so the page never hides
   content it has no way to bring back. Visible is the default; the animation is the
   enhancement. .is-in carries opacity:1 itself and the animation has no fill-mode, so
   if the animation never runs the element is simply there. */
[data-reveal], [data-in] { opacity: 1; }
html.js [data-reveal] { opacity: 0; }
html.js [data-reveal].is-in { opacity: 1; animation: rise 0.9s cubic-bezier(0.2,0.75,0.2,1); }
html.js [data-in] { animation: rise 1s cubic-bezier(0.2,0.75,0.2,1) both; }
@keyframes rise { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: none; } }
@keyframes sweep { from { transform: translateX(-120%); } to { transform: translateX(340%); } }

[data-lift] { transition: box-shadow 0.28s ease, transform 0.28s ease; }
[data-lift]:hover { transform: translateY(-3px); box-shadow: inset 0 0 0 1px rgba(255,255,255,0.2); }

@media (prefers-reduced-motion: reduce) {
  [data-reveal], [data-reveal].is-in, [data-in],
  html.js [data-reveal], html.js [data-reveal].is-in, html.js [data-in] { animation: none; opacity: 1; }
  .sweep { animation: none !important; }
}

/* ══ security page ════════════════════════════════════════════════════════════
   Note the .shell prefix on several rules below. `.shell .sec p` and `.shell .sec h2`
   are 0-2-1, so a plain `.trade-lead` or `.ncard h3` inside the shell loses to them and
   renders as body text without anything looking wrong in the markup. Anything that
   restyles prose inside the column has to match that weight. */
/* ══ security page ════════════════════════════════════════════════════════════ */

/* Wider than .wrap, and matched to .top and .foot rather than to a number of its own,
   so the logo, the table of contents and the footer share one left edge. */
.wide { max-width: 1180px; margin: 0 auto; padding: 0 40px; }

/* The short version, before the two-column shell starts. Four cards on one hairline
   grid: the 1px gap over a light background IS the divider. */
.sv {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 1px; background: rgba(255,255,255,0.08);
  border-radius: 14px; overflow: hidden; margin-top: 56px;
}
.sv-card { background: #0b0b0b; padding: 26px 26px 30px; }
.sv-text { font-size: 16px; line-height: 1.55; color: rgba(242,242,242,0.82); margin-top: 14px; text-wrap: pretty; }
.sv-text a { color: inherit; }
.sv-note { font-size: 15px; line-height: 1.6; color: var(--f55); margin-top: 20px; max-width: 640px; }

/* The mono label that replaced the h3s. Still a heading in the markup: it is the only
   thing naming what follows, and a screen reader needs the outline. */
.eyebrow {
  font-family: var(--mono); font-size: 10px; font-weight: 500;
  letter-spacing: 0.2em; color: var(--f35); text-transform: uppercase;
}
.sv-card .eyebrow { color: var(--ok); }
.sv-card .eyebrow.plain { color: var(--f40); }
.sec .eyebrow { margin-top: 46px; }
.sec .eyebrow + p { margin-top: 16px; }

/* Two columns from 940px up, one below. The list is sticky, so it stays put through a
   long page without following the reader down a short one. */
.shell { display: grid; grid-template-columns: minmax(0, 1fr); gap: 56px; align-items: start; margin-top: 24px; }
.shell > .col { min-width: 0; }
.toc { position: sticky; top: 110px; align-self: start; }
.toc-list { display: flex; flex-direction: column; margin-top: 18px; }
.toc-list a {
  font-size: 14.5px; line-height: 1.4; padding: 9px 0 9px 16px;
  border-left: 1.5px solid rgba(255,255,255,0.12);
  color: var(--f55); text-decoration: none;
  transition: color 0.2s ease, border-color 0.2s ease;
}
.toc-list a:hover { color: var(--fg); border-left-color: rgba(255,255,255,0.45); }
@media (min-width: 940px) {
  .shell { grid-template-columns: 240px minmax(0, 1fr); gap: 72px; }
  .shell > .toc { margin-top: 44px; }
}
/* Below 940px the list is a duplicate of the headings a phone reader is about to
   scroll past anyway, and a sticky block eating the top of a narrow screen is worse
   than no list at all. */
@media (max-width: 939px) { .toc { display: none; } }

/* Sections in the right column set their own rhythm; .sec's 64px is for the narrow
   single-column pages. */
.shell .sec { padding-top: 110px; }
.shell .sec:first-child { padding-top: 40px; }
.shell .sec h2 { font-size: clamp(26px, 3.2vw, 34px); line-height: 1.16; max-width: 640px; }
.shell .sec p, .shell .sec ul li { max-width: 660px; }

/* Numbered mechanics, as a stack of rows rather than a list of paragraphs: the reader
   is meant to follow it in order. */
.psteps {
  display: flex; flex-direction: column; gap: 1px; margin-top: 18px;
  background: rgba(255,255,255,0.08); border-radius: 14px; overflow: hidden;
  padding: 0; list-style: none; counter-reset: ps;
}
.psteps li {
  counter-increment: ps; display: grid; grid-template-columns: auto minmax(0, 1fr);
  gap: 20px; align-items: start; background: #0b0b0b; padding: 22px 26px;
  font-size: 16px; line-height: 1.55; color: rgba(242,242,242,0.78); text-wrap: pretty;
}
/* The row's content is wrapped in one div on purpose. Every ELEMENT child of a grid
   container is its own grid item, so a bare <b> or <code> in the sentence landed in a
   cell of its own and pushed the row past the page. Caught by the 390px overflow
   measurement, not by looking at it. */
.psteps li > div, .klims li > div { min-width: 0; }
.psteps li::before { content: counter(ps, decimal-leading-zero); font-family: var(--mono); font-size: 13px; color: var(--f40); padding-top: 2px; }

/* The one panel on the page that is an admission rather than a claim. */
.trade {
  margin-top: 46px; border-radius: 16px; background: rgba(224,177,85,0.05);
  box-shadow: inset 0 0 0 1px rgba(224,177,85,0.22); padding: 30px 30px 32px;
}
.trade .eyebrow { color: var(--warn); margin-top: 0; }
.shell .trade p.trade-lead {
  font-size: clamp(19px, 2.2vw, 24px); line-height: 1.32; font-weight: 500;
  letter-spacing: -0.015em; margin-top: 16px; max-width: 600px; text-wrap: pretty; color: var(--fg);
}
.shell .trade p { margin-top: 16px; font-size: 16.5px; line-height: 1.6; color: rgba(242,242,242,0.68); max-width: 640px; }
.shell .trade p.trade-cue { font-size: 15px; color: var(--f55); margin-top: 26px; }
.shell .trade ul { margin-top: 16px; }
.shell .trade ul li { color: rgba(242,242,242,0.75); margin-bottom: 12px; }
.shell .trade ul li::before { background: var(--warn); border-radius: 50%; width: 5px; height: 5px; }
.shell .trade p.trade-foot {
  font-size: 16.5px; line-height: 1.55; margin-top: 26px; padding-top: 22px;
  border-top: 1px solid rgba(224,177,85,0.2); color: var(--fg); text-wrap: pretty;
}

/* The breach table. Still a table: it is two columns of paired facts, and the row is
   the unit of meaning. The green tint marks the two rows that are the whole point. */
table.brt { width: 100%; border-collapse: collapse; margin-top: 32px; border-radius: 14px; overflow: hidden; box-shadow: inset 0 0 0 1px rgba(255,255,255,0.08); }
table.brt th, table.brt td { text-align: left; font-weight: 400; padding: 18px 24px; border-bottom: 1px solid rgba(255,255,255,0.055); }
table.brt tr:last-child th, table.brt tr:last-child td { border-bottom: 0; }
table.brt th { font-size: 16px; line-height: 1.45; color: rgba(242,242,242,0.8); text-wrap: pretty; }
table.brt td { width: 220px; font-size: 14px; color: var(--warn); white-space: nowrap; }
table.brt td i { display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: var(--warn); margin-right: 9px; vertical-align: middle; }
table.brt tr.safe { background: rgba(95,216,138,0.045); }
table.brt tr.safe th { color: var(--fg); }
table.brt tr.safe td { color: var(--ok); }
table.brt tr.safe td i { background: var(--ok); }

/* Four things this does not protect against, as cards. Each is self-contained, which
   is why they are not a list: no order, no dependency between them. */
/* Four cards, two by two. An odd count leaves a hole in the grid, and the hole reads
   as a card that failed to render. */
.ncards { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 14px; margin-top: 32px; }
.ncard { border-radius: 14px; box-shadow: inset 0 0 0 1px rgba(255,255,255,0.08); padding: 26px 26px 28px; }
.shell .ncard h3 { margin-top: 0; font-size: 18px; font-weight: 600; letter-spacing: -0.012em; }
.shell .ncard p { margin-top: 12px; font-size: 15.5px; line-height: 1.55; color: var(--f60); text-wrap: pretty; }
.ncard.warn { background: rgba(224,177,85,0.05); box-shadow: inset 0 0 0 1px rgba(224,177,85,0.22); }
.ncard.warn h3 { color: var(--warn); }

/* Term on the left, explanation on the right. A definition list would be the honest
   element, but dl's grid behaviour across dt/dd pairs is not worth the trouble here. */
.pieces { margin-top: 32px; }
.piece {
  display: grid; grid-template-columns: minmax(180px, 0.62fr) minmax(0, 1fr);
  gap: 32px; align-items: start; padding: 26px 0; border-top: 1px solid rgba(255,255,255,0.07);
}
.shell .piece h3 { margin-top: 0; font-size: 18px; font-weight: 600; letter-spacing: -0.012em; text-wrap: pretty; }
.shell .piece p { margin: 0 0 16px; font-size: 16px; line-height: 1.6; color: rgba(242,242,242,0.68); }
.shell .piece p:last-child { margin-bottom: 0; }
@media (max-width: 700px) { .piece { grid-template-columns: minmax(0, 1fr); gap: 12px; } }

/* Numbered because there are six and they get referred to by number. */
.klims { margin-top: 32px; padding: 0; list-style: none; counter-reset: kl; }
.klims li {
  counter-increment: kl; display: grid; grid-template-columns: auto minmax(0, 1fr);
  gap: 20px; align-items: start; padding: 22px 0; border-top: 1px solid rgba(255,255,255,0.07);
  font-size: 15.5px; line-height: 1.58; color: var(--f60); text-wrap: pretty;
}
.klims li::before { content: counter(kl, decimal-leading-zero); font-family: var(--mono); font-size: 11px; color: rgba(242,242,242,0.3); padding-top: 5px; }
.klims li b { display: block; font-size: 16.5px; letter-spacing: -0.01em; margin-bottom: 8px; }

/* Window chrome around the test commands. It is a real terminal transcript, so it gets
   to look like one. */
.mac { margin-top: 30px; border-radius: 14px; background: #0c0c0c; box-shadow: inset 0 0 0 1px rgba(255,255,255,0.08); overflow: hidden; }
.mac-bar { display: flex; align-items: center; gap: 8px; padding: 13px 20px; border-bottom: 1px solid rgba(255,255,255,0.06); }
.mac-bar i { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.mac-bar i:nth-child(1) { background: #ff5f57; }
.mac-bar i:nth-child(2) { background: #febc2e; }
.mac-bar i:nth-child(3) { background: #28c840; }
.mac pre.term { margin: 0; border-radius: 0; box-shadow: none; background: none; padding: 22px 24px; }
.mac-body { position: relative; overflow: hidden; }
/* One pass, under five seconds, when the block comes into view (audit W2). It used to
   loop for ever, and anything that moves for more than five seconds beside text needs a
   way to stop it (WCAG 2.2.2). A single sweep needs none. `both` parks it past the right
   edge afterwards, where the overflow hides it. */
.sweep {
  position: absolute; inset: 0 auto 0 0; width: 16%; pointer-events: none;
  background: linear-gradient(90deg, rgba(255,217,61,0) 0%, rgba(255,180,120,0.12) 50%, rgba(200,109,215,0) 100%);
  animation: sweep 4.5s cubic-bezier(0.5,0,0.5,1) 1 both;
}
html.js [data-reveal]:not(.is-in) .sweep { animation: none; }

/* Deliberately NOT also a .sec: `.shell .sec` sets padding-top:110px and outranks this
   rule's own padding, which pushed the heading half way down its own box. */
.found { margin-top: 120px; padding: 34px 34px 36px; border-radius: 16px; box-shadow: inset 0 0 0 1px rgba(255,255,255,0.1); }
.shell .found h2 { font-size: 24px; font-weight: 600; letter-spacing: -0.018em; }
.shell .found p { margin-top: 14px; font-size: 16.5px; line-height: 1.6; color: rgba(242,242,242,0.68); max-width: 560px; }

@media (max-width: 700px) {
  .wide { padding: 0 24px; }
  .sv { margin-top: 40px; }
  .shell .sec { padding-top: 76px; }
  .trade { padding: 24px 22px 26px; }
  .psteps li { padding: 20px 20px; gap: 14px; }
  table.brt th, table.brt td { padding: 15px 16px; }
  table.brt td { width: 150px; white-space: normal; }
}

/* The page head sits in .wide, so it needs its own measure: 1100px of prose is not a
   line anybody reads. */
.wide .phead { padding-top: 100px; }
.wide .phead h1 { font-size: clamp(38px, 6vw, 62px); line-height: 1.08; letter-spacing: -0.03em; }
.wide .phead p { max-width: 760px; font-size: clamp(18px, 2.1vw, 23px); line-height: 1.45; font-weight: 300; color: rgba(242,242,242,0.78); }

/* ── comparison pages ─────────────────────────────────────────────────────────
   index.html defines its own .cmp grid inside an inline <style>. These are separate
   classes rather than a move of those rules into this file: site.css loads BEFORE
   the homepage's inline block, so hoisting them would change which declaration wins
   on a page that is already live and already measured by check-site.mjs. Duplicating
   eight rules is cheaper than re-verifying the homepage. */
/* A real table (audit W8). Column widths match the grid it replaced. */
table.ct { width: 100%; border-collapse: collapse; table-layout: fixed; margin-top: 26px; }
table.ct th, table.ct td {
  text-align: left; vertical-align: baseline; font-weight: 400;
  padding: 18px 22px 18px 0; border-bottom: 1px solid rgba(255,255,255,0.06);
  font-size: 15px; line-height: 1.5;
}
table.ct tr > :first-child { width: 26%; }
table.ct tr > :last-child { padding-right: 0; }
.ct-head th, .ct-head td {
  padding-top: 0; padding-bottom: 13px; border-bottom: 1px solid rgba(255,255,255,0.14);
  font-size: 12px; letter-spacing: 0.04em; color: var(--f45);
}
.ct-head .me { color: var(--fg); font-weight: 600; font-size: 14px; letter-spacing: 0; }
.ct-row .l, .ct-row .t { color: var(--f55); }
.ct-row .m { color: var(--fg); }
.ct-note { margin: 18px 0 0; font-size: 12.5px; line-height: 1.6; color: var(--f40); text-wrap: pretty; }

/* Every figure on these pages carries its source. The list is part of the argument,
   not an appendix, so it is styled to be read rather than tucked away. */
.srcs { margin: 18px 0 0; padding-left: 0; list-style: none; }
.srcs li {
  padding: 9px 0; border-bottom: 1px solid var(--hair);
  font-size: 13.5px; line-height: 1.55; color: var(--f55);
}
.srcs li::before { content: none; }
/* A source URL is one unbreakable word, and at 320px it pushed three comparison pages
   sideways (audit W6). Let it break anywhere rather than scroll the page. */
.srcs .on { font-family: var(--mono); font-size: 11px; color: var(--f35); overflow-wrap: anywhere; }

/* The index of comparison pages. */
.clist { margin: 26px 0 0; display: grid; gap: 12px; }
.clist a {
  display: block; padding: 20px 22px; border-radius: 14px;
  box-shadow: inset 0 0 0 1px var(--ring); text-decoration: none;
  transition: background 0.25s ease, box-shadow 0.25s ease;
}
.clist a:hover { background: rgba(255,255,255,0.03); box-shadow: inset 0 0 0 1px rgba(255,255,255,0.14); }
.clist .nm { font-size: 17px; font-weight: 600; letter-spacing: -0.01em; }
.clist .bl { margin: 7px 0 0; font-size: 14.5px; line-height: 1.55; color: var(--f55); }

/* Below 720px each row becomes a small card: label, ours, theirs. The column headings
   leave the screen but stay in the table for a screen reader, and the vendor's cell is
   prefixed with the vendor's name so a sighted reader still knows whose it is. */
@media (max-width: 720px) {
  table.ct, table.ct tbody, table.ct tr, table.ct th, table.ct td { display: block; width: auto; }
  table.ct tr > :first-child { width: auto; }
  .ct-head {
    position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0);
  }
  table.ct .ct-row { padding: 16px 0; border-bottom: 1px solid rgba(255,255,255,0.06); }
  table.ct .ct-row th, table.ct .ct-row td { padding: 3px 0; border: 0; }
  .ct-row .l { color: var(--f40); font-size: 12px; letter-spacing: 0.04em; text-transform: uppercase; }
  .ct-row .t::before { content: attr(data-th) ': '; color: var(--f40); }
}
