/* ═══════════════════════════════════════════════════════════════════════
   gtm-audit-web — one stylesheet, built on the report's tokens (item 110)

   The app and the report are one product. The :root tokens below are the
   values in src/report/html/tokens.ts, and src/web/app-css.test.ts fails the
   build if they drift.

   Sixteen variables left from an earlier colour scheme have been removed
   here, each with zero uses anywhere in the tree: --bg, --fg, --border,
   --blue, --green, --grey, --bg-alt, --blue-bg, --green-bg and --grey-bg
   (item 155), then the six aliases they left behind — --muted, --primary,
   --orange, --orange-bg, --yellow and --yellow-bg. The comment above them
   said "older views and partials still use" these names; none did. Deleting
   ten of a kind and keeping six only makes the six look deliberate.

   --brand-* and --brand-mark are console chrome, not content colour — they
   never belong on a report page. See tokens.ts's BRAND for why it is a
   separate export.
   ═══════════════════════════════════════════════════════════════════════ */
:root {
  /* The space scale and the gutter, for the shared client band: masthead()
     draws it on both sides now, and its rules (src/report/html/chrome-css.ts)
     are the report's, written against the report's tokens. These five are the
     ones the report's :root has and this one did not. */
  --space-2: 8px;
  --space-4: 16px;
  --space-5: 20px;
  --space-7: 32px;
  --gutter: 48px;
  --ink-primary:   #1A1A18;
  --ink-body:      #2C2C2A;
  --ink-secondary: #5F5E5A;
  --ink-muted:     #888780;
  --rule:          #D3D1C7;
  --card-border:   #E5E3DA;
  --hair:          #EFEDE6;
  --page:          #FFFFFF;
  --ground:        #F2F1ED;
  --inset:         #FAF9F5;
  --accent:        #3A47C2;
  --accent-fill:   #EEEFFB;
  --accent-hover:  #2C379E;
  --accent-line:   #C9CDF3;
  --fill-critical: #FCEBEB;
  --ink-critical:  #A32D2D;
  --fill-warning:  #FAEEDA;
  --ink-warning:   #854F0B;
  --fill-pass:     #EAF3DE;
  --ink-pass:      #3B6D11;
  --fill-neutral:  #F1EFE8;
  --ink-neutral:   #5F5E5A;
  --grid:          #E7E5DE;
  --radius:        4px;
  --radius-card:   6px;
  --grid:          #E7E5DE;
  --font-sans:     -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  --font-mono:     "SF Mono", "Menlo", "Consolas", "Liberation Mono", monospace;

  /* Brand chrome — console only, never on a report page. */
  --brand-bar:        #14213D;
  --brand-bar-raised: #2B3D66;
  --brand-bar-line:   #3B4C73;
  --brand-bar-ink:    #C7D2EA;
  --brand-mark:       #A9B3F5;

  /* Resources (HANDOFF.md § Tokens used) — the colours the references use
     that the report palette does not have, and the radius scale. */
  --rs-mark:           #E3E5FA;
  --rs-on-navy:        #D9DCF5;
  --rs-on-navy-2:      #C9CFFA;
  --rs-radius-tile-sm: 8px;
  --rs-radius-tile-md: 10px;
  --rs-radius-tile-lg: 12px;
  --rs-radius-art:     14px;
  --rs-radius-btn:     8px;
  --rs-radius-strip:   12px;
  --rs-radius-band:    16px;
  --rs-radius-search:  10px;
}

* { box-sizing: border-box; }

body {
  font-family: var(--font-sans);
  color: var(--ink-primary);
  background: var(--ground);
  margin: 0;
  font-size: 14px;
  line-height: 1.5; font: 14px/1.5 var(--font-sans);
}

/* ── Chrome ─────────────────────────────────────────────────────────── */
/*
 * The page frame — spec §2b: 1440 wide, gutters 48, content 1344, centred on
 * wider screens with the ground colour filling the rest.
 *
 * `--frame-pad` is the gutter as a single value every band reads, and that is
 * the point rather than a convenience: the app bar, the client header, the tab
 * bar and the content all have to start on the same vertical line. They did
 * not. `main.content` was centred inside 1040px while `nav.tabs` was padded
 * 20px from the viewport's own edge, so the navigation and the cards under it
 * lined up with each other at exactly one window width and drifted apart at
 * every other. A band that spans the window paints full-bleed and centres a
 * `.frame` inside itself; a band that does not is a `.frame` directly.
 */
:root { --frame: 1440px; --frame-pad: 48px; }

.frame {
  max-width: var(--frame);
  margin: 0 auto;
  padding-left: var(--frame-pad);
  padding-right: var(--frame-pad);
}


/*
 * The client header — the band above the client tabs, on every page of one
 * client's workspace.
 *
 * 72px and a 128x48 mark slot are §2b's "Header" row. The mark is a slot
 * rather than an image box so a client with no mark leaves nothing behind:
 * the spec's `no-client-logo` state omits it rather than drawing an empty
 * frame, and the same rule holds here.
 */

/*
 * A run in flight, stated where every page of the workspace can see it.
 *
 * It is a status, not a control, so it is not a button: the link inside it is
 * the control. The dot is drawn by the rule rather than written into the
 * markup, so no renderer can put the indicator up without the state behind it.
 *
 * SCOPED to the header's action area. `running` is a state name three
 * different components use, and `#status-badge` on the run page is one of
 * them — it writes its own `<span class="dot">` and took a `::before` dot
 * from here as well, so the badge drew TWO on every running audit. The two
 * other users of the bare class name themselves further down this file, under
 * a comment saying exactly why; this rule was the one that never did.
 */
.masthead-actions .running {
  display: inline-flex; align-items: center; gap: 10px;
  height: 40px; padding: 0 14px;
  border-radius: var(--radius); background: var(--accent-fill);
  color: var(--accent); font-size: 14px; font-weight: 600;
}
.masthead-actions .running::before {
  content: ""; width: 8px; height: 8px; border-radius: 50%;
  background: var(--accent); flex: none;
}
.masthead-actions .running .state { color: var(--ink-secondary); font-weight: 400; }
.masthead-actions .running a { color: var(--accent); text-decoration: none; font-weight: 600; }
.masthead-actions .running a:hover { text-decoration: underline; }

main.content { padding-top: 28px; padding-bottom: 32px; }

/* §2b: forms and settings are 880 centred, not the full frame. */
main.content.narrow { max-width: calc(880px + var(--frame-pad) * 2); }

@media (max-width: 1279px) { :root { --frame-pad: 32px; } }
@media (max-width: 899px) {
  :root { --frame-pad: 16px; }
}

/*
 * `.masthead-back`'s own metrics — the user, 2026-10-01, asking for every
 * element in the two bars to agree, with the report as the guide.
 *
 * It was muted grey with 4px under it against the masthead's ink and 2px. The
 * link inside is `--accent` in both already, so the only visible difference
 * was the separator and any plain text beside it.
 */
.crumb { font-size: 13px; color: var(--ink-primary); margin-bottom: 2px; }
.crumb a { color: var(--accent); text-decoration: none; }
.crumb a:hover { text-decoration: underline; }
h1 { font-size: 22px; margin: 0 0 16px; color: var(--ink-primary); letter-spacing: -0.01em; }
.topbar { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-bottom: 18px; }
.topbar h1 { margin: 0; }

/* ── Cards ──────────────────────────────────────────────────────────── */
.card {
  background: var(--page);
  border: 1px solid var(--card-border);
  border-radius: var(--radius-card);
  padding: 20px 24px;
  margin-bottom: 16px;
}
.card h2 {
  font-size: 13px; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--ink-muted); margin: 0 0 12px; font-weight: 600;
}
.card .meta { color: var(--ink-muted); font-size: 13px; }
.card .actions { margin-top: 12px; display: flex; gap: 8px; flex-wrap: wrap; }
.sub { color: var(--ink-body); font-size: 13px; margin: 0 0 12px; }
.note { font-size: 12.5px; color: var(--ink-muted); margin-top: 10px; }

/* ── Buttons ────────────────────────────────────────────────────────── */
/* The gallery's .btn: a 40px control, not a padded inline box. §2b sets every
   control to height 40 (icon-only and list targets 44), and the 8px gap is
   what puts a glyph beside a label in "Run audit" and "Download PDF". */
button, .btn {
  font: 500 14px var(--font-sans);
  height: 40px; padding: 0 16px;
  border-radius: var(--radius);
  border: 1px solid var(--card-border);
  background: var(--page);
  color: var(--ink-primary);
  cursor: pointer;
  text-decoration: none;
  display: inline-flex; align-items: center; gap: 8px;
}
button:hover, .btn:hover { background: var(--inset); }
button:focus-visible, .btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
button.primary, .btn.primary { background: var(--accent); color: #fff; border-color: var(--accent); }
button.primary:not(:disabled):hover, .btn.primary:not(:disabled):hover { filter: brightness(0.95); background: var(--accent); }
/*
 * A primary control that cannot be used is grey, not a faded accent.
 *
 * `opacity: .6` on a filled accent button reads as a slightly dim blue button
 * — still the most prominent thing on the header, still inviting the press it
 * will refuse. "Run audit" while a run is in flight is the case: the route
 * refuses a second run, and the button should say so before it is pressed.
 * `:hover` is scoped above so it cannot paint the accent back on.
 */
button.primary:disabled, .btn.primary:disabled {
  background: var(--fill-neutral); color: var(--ink-muted);
  border-color: var(--card-border); opacity: 1; cursor: not-allowed;
}
.btn.quiet { background: var(--page); color: var(--accent); border-color: var(--accent); }
.btn.quiet:hover { background: var(--accent-fill); }
button:disabled, .btn:disabled { opacity: 0.6; cursor: default; }

/* ── Tables ─────────────────────────────────────────────────────────── */
.tblwrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; background: var(--page); font-size: 13.5px; }
th, td { padding: 10px; text-align: left; border-bottom: 1px solid var(--hair); vertical-align: middle; }
th {
  background: transparent; font-weight: 600; font-size: 12px; color: var(--ink-muted);
  letter-spacing: 0.04em; text-transform: uppercase; border-bottom: 1px solid var(--rule); padding: 8px 10px;
}
td { color: var(--ink-body); }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
td.mono { font-family: var(--font-mono); font-size: 12.5px; }
tbody tr:hover td { background: var(--inset); }
tr.rgroup td { background: var(--inset); font-weight: 600; color: var(--ink-primary); font-size: 12.5px; letter-spacing: 0.03em; }
a.rep { color: var(--accent); text-decoration: none; }
a.rep:hover { text-decoration: underline; }

/* ── Chips, badges, grades ──────────────────────────────────────────── */
/* A 24px rectangle at the card radius, not a pill. The console drew chips at
   a 20px radius, which is the one shape the gallery never uses — and it made
   a grade chip and a status chip read as two different families. */
.chip, .badge {
  display: inline-flex; align-items: center; height: 24px; padding: 0 8px;
  border-radius: var(--radius);
  font-size: 12px; font-weight: 600; white-space: nowrap;
}
.chip.pass, .badge-green  { background: var(--fill-pass);     color: var(--ink-pass); }
.chip.warn, .badge-yellow { background: var(--fill-warning);  color: var(--ink-warning); }
.chip.crit, .badge-orange { background: var(--fill-critical); color: var(--ink-critical); }
.chip.info, .badge-blue   { background: var(--accent-fill);   color: var(--accent); }
.chip.neutral, .badge-grey { background: var(--fill-neutral); color: var(--ink-neutral); }

.grade {
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; border-radius: var(--radius); font-weight: 700; font-size: 18px; flex-shrink: 0;
}
.grade.sm { width: 34px; height: 34px; font-size: 17px; }
.grade.A, .grade.B { background: var(--fill-pass);     color: var(--ink-pass); }
.grade.C           { background: var(--fill-warning);  color: var(--ink-warning); }
.grade.D, .grade.F { background: var(--fill-critical); color: var(--ink-critical); }
.grade.none        { background: var(--fill-neutral);  color: var(--ink-neutral); }

/* ── KPI tiles ──────────────────────────────────────────────────────── */
/*
 * One strip, divided — `client-01-home.png`.
 *
 * The cells were six separate tinted boxes with their own borders and a gap
 * between them, which read as six cards about six subjects. They are one
 * reading: this run, in six numbers. So it is one card, the cells are
 * separated by the 1px hair the spec asks for rather than by a gap, and the
 * grade cell is tinted because it is the one that carries a verdict.
 */
.kpis { display: grid; grid-template-columns: auto 1.4fr repeat(5, 1fr); align-items: stretch; }
/*
 * Centred in the cell, not stacked from the top.
 *
 * The strip's cells are as tall as the tallest of them — Coverage carries a
 * two-line sub-line — so top-aligned contents left every other cell's number
 * floating under a band of white. The mockup centres all six.
 */
.kpi {
  padding: 16px 20px; border-left: 1px solid var(--hair); min-width: 0;
  display: flex; flex-direction: column; justify-content: center;
}
.kpi:first-child { border-left: none; }
/*
 * The grade cell is the one that carries a verdict, so it is tinted by that
 * verdict and the letter is set big enough to read across a room. It was a
 * 24px chip in a white cell, which made the grade the smallest thing on a
 * strip of six numbers.
 */
.kpi--grade {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 4px; text-align: center; padding: 20px 28px; min-width: 150px;
}
.grade-big { font-size: 56px; line-height: 1; font-weight: 600; letter-spacing: -0.03em; }
.kpi--grade .lab { letter-spacing: .08em; }
.kpi--grade-pass { background: var(--fill-pass); }
.kpi--grade-pass .grade-big, .kpi--grade-pass .lab { color: var(--ink-pass); }
.kpi--grade-warning { background: var(--fill-warning); }
.kpi--grade-warning .grade-big, .kpi--grade-warning .lab { color: var(--ink-warning); }
.kpi--grade-critical { background: var(--fill-critical); }
.kpi--grade-critical .grade-big, .kpi--grade-critical .lab { color: var(--ink-critical); }
.kpi--grade-gap { background: var(--fill-neutral); }
.kpi--grade-gap .grade-big, .kpi--grade-gap .lab { color: var(--ink-secondary); }
.kpi .lab { font-size: 12px; font-weight: 600; color: var(--ink-secondary); letter-spacing: 0.08em; text-transform: uppercase; }
.kpi .val {
  font-size: 30px; font-weight: 600; color: var(--ink-primary); letter-spacing: -0.02em;
  line-height: 1.1; margin: 6px 0 4px; font-variant-numeric: tabular-nums;
}
.kpi .val small { font-size: 14px; font-weight: 400; color: var(--ink-muted); }
.kpi .delta { font-size: 13px; color: var(--ink-secondary); }
/* The latest run reads as a date and a way in, not as a statistic. */
.kpi--run .val { font-size: 18px; letter-spacing: -0.01em; }
.kpi--run a { color: var(--accent); text-decoration: none; font-size: 13px; }
.kpi--run a:hover { text-decoration: underline; }
/* The card holds the strip flush: the cells carry their own padding. */
.card--strip { padding: 0; overflow: hidden; }

@media (max-width: 1279px) {
  .kpis { grid-template-columns: auto 1fr 1fr 1fr; }
  .kpi { border-top: 1px solid var(--hair); }
  .kpi:first-child, .kpi:nth-child(2), .kpi:nth-child(3), .kpi:nth-child(4) { border-top: none; }
}
@media (max-width: 899px) { .kpis { grid-template-columns: auto 1fr; } }
.delta.up { color: var(--ink-pass); }
.delta.down { color: var(--ink-critical); }

/* ── Charts (inline SVG) ────────────────────────────────────────────── */
.charts { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
@media (max-width: 760px) { .charts { grid-template-columns: 1fr; } }
.chart svg { width: 100%; height: auto; display: block; font-family: var(--font-sans); }
.chart .axis text { fill: var(--ink-muted); font-size: 11px; }
.chart .grid line { stroke: var(--grid); stroke-width: 1; }
.legend { display: flex; gap: 14px; font-size: 12px; color: var(--ink-secondary); margin-top: 8px; flex-wrap: wrap; }
.legend i { display: inline-block; width: 10px; height: 10px; border-radius: 2px; margin-right: 6px; vertical-align: -1px; }
.spark { width: 120px; height: 28px; }

/* ── Region strip ───────────────────────────────────────────────────── */
.regions { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; }
/* The gallery's region-grades: a grade square, a name, one sub-line. */
.region { display: flex; align-items: center; gap: 12px; min-width: 0; }
.region-name { font-weight: 600; color: var(--ink-primary); font-size: 14px; }
.region-sub { color: var(--ink-secondary); font-size: 13px; }

/* ── Forms ──────────────────────────────────────────────────────────── */
form .field { margin-bottom: 12px; }
form label { display: block; font-weight: 600; margin-bottom: 4px; }
form input[type=text], form input[type=url], form input[type=email], form select {
  width: 100%; padding: 8px 10px; border: 1px solid var(--card-border); border-radius: var(--radius);
  font: inherit; background: var(--page); color: var(--ink-body);
}
form .checkbox-group label { font-weight: normal; display: inline-block; margin-right: 12px; }

pre.log, .log {
  background: var(--inset);
  border: 1px solid var(--hair);
  color: var(--ink-secondary);
  padding: 12px 14px;
  max-height: 320px;
  overflow: auto;
  font-family: var(--font-mono);
  font-size: 12px;
  border-radius: var(--radius);
  white-space: pre-wrap;
  margin: 0;
}
details summary { cursor: pointer; color: var(--accent); font-size: 13px; }

.error-box { background: var(--fill-critical); color: var(--ink-critical); padding: 10px 14px; border-radius: var(--radius); margin-bottom: 12px; }
.card.danger { border-color: var(--ink-critical); }
button.danger, .btn.danger { background: var(--ink-critical); color: #fff; border-color: var(--ink-critical); }
button.danger:hover, .btn.danger:hover { background: var(--ink-critical); filter: brightness(0.95); }
.btn.danger-link { color: var(--ink-critical); border-color: var(--ink-critical); }
.notice { background: var(--fill-pass); border-left: 4px solid var(--ink-pass); padding: 10px 14px; border-radius: 3px; margin-bottom: 12px; }

/* ── Run page: status, phases, activity, counters ───────────────────── */
#status-bar { display: flex; gap: 14px; align-items: center; flex-wrap: wrap; margin: 0 0 16px; }
#status-badge { padding: 3px 11px; border-radius: 999px; font-weight: 600; font-size: 13px; white-space: nowrap; }
#status-badge.initializing { background: var(--fill-warning);  color: var(--ink-warning); }
#status-badge.running      { background: var(--accent-fill);   color: var(--accent); }
#status-badge.complete     { background: var(--fill-pass);     color: var(--ink-pass); }
#status-badge.failed       { background: var(--fill-critical); color: var(--ink-critical); }
#status-badge.blocked      { background: var(--fill-neutral);  color: var(--ink-neutral); }
#status-badge.cancelled    { background: var(--fill-neutral);  color: var(--ink-neutral); }
#elapsed-eta { color: var(--ink-muted); font-size: 13px; }
.status { display: inline-flex; align-items: center; gap: 8px; font-weight: 600; color: var(--ink-primary); }
.status .dot { width: 9px; height: 9px; border-radius: 50%; background: var(--accent); animation: pulse 1.4s ease-in-out infinite; }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }

.steps { display: grid; grid-template-columns: repeat(6, 1fr); gap: 0 16px; }
@media (max-width: 760px) { .steps { grid-template-columns: repeat(3, 1fr); } }
/*
 * A bar above each step, not a box around it — client-07-run-progress.png.
 *
 * Six bordered tiles read as six buttons; six bars read as a track something
 * is moving along, which is what this is. The bar is the step's own progress:
 * a done step fills it, the current one tints it, the rest leave it grey.
 */
.step {
  padding: 0; background: none; border: none;
  font-size: 13px; color: var(--ink-secondary);
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.step::before {
  content: ""; display: block; width: 100%; height: 4px; border-radius: 2px;
  background: var(--hair); margin-bottom: 12px;
}
.step.done::before { background: var(--ink-pass); }
.step.now::before { background: var(--accent); }
.step .n {
  display: inline-flex; width: 20px; height: 20px; border-radius: 50%; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 600; background: var(--fill-neutral); color: var(--ink-neutral); flex: none;
}
.step.done { color: var(--ink-secondary); }
.step.done .n { background: var(--fill-pass); color: var(--ink-pass); }
.step.now { color: var(--ink-primary); font-weight: 600; }
.step.now .n { background: var(--accent); color: #fff; }

/* The rule closing the stepper lives here, on the id, because that is what the
   element carries: a `.runstate .steps` rule beside the card's other spacing
   lost to this selector and drew its line 5px under the labels instead of 20. */
#phase-stepper {
  list-style: none; margin: 12px 0 20px; padding: 0 0 20px;
  border-bottom: 1px solid var(--hair);
}
#status-badge { display: inline-flex; align-items: center; gap: 8px; }
#status-badge .dot { width: 9px; height: 9px; border-radius: 50%; background: currentColor; animation: pulse 1.4s ease-in-out infinite; }

#activity-line { margin: 0 0 16px; color: var(--ink-secondary); font-size: 13px; }
#activity-line.failed { color: var(--ink-critical); font-weight: 600; }
#counters { color: var(--ink-muted); margin: 6px 0 12px; font-size: 13px; }

@media (prefers-reduced-motion: reduce) { .status .dot, #status-badge .dot { animation: none; } }

/* ── Inline client field editing ────────────────────────────────────── */
/*
 * A settings row — `client-06-settings.png`.
 *
 * Full width of the card, the label in a fixed column, the value beside it and
 * the action hard right. It was a cramped 34px line with a 110px muted label
 * and the Edit link floating next to the value rather than at the card's edge,
 * so eleven rows read as a dense block of small grey text instead of a list
 * somebody could scan down.
 */
.field-row {
  display: flex; align-items: center; gap: 16px;
  padding: 14px 24px; border-bottom: 1px solid var(--hair); min-height: 56px;
}
/*
 * Every row is wrapped in its own `div#field-<key>` so HTMX can swap one in
 * place, which made `.field-row:last-child` match EVERY row — each is the only
 * child of its wrapper — and removed all the hairlines at once. The section
 * body drops the border on whichever wrapper comes last instead.
 */
.card--rows .sect-body > *:last-child .field-row,
.card--rows .sect-body > .field-row:last-child { border-bottom: none; }
.field-label { color: var(--ink-body); font-size: 14px; width: 200px; flex-shrink: 0; }
.field-value { flex: 1; min-width: 0; color: var(--ink-primary); font-size: 14px; }
.field-value .chip { margin-right: 6px; }
.field-value.mono, .field-value .mono { font-family: var(--font-mono); font-size: 13px; }
/*
 * `--rule` is a BORDER colour — #D3D1C7 — and this set type in it, which
 * measured 1.53:1 against the card. The word was there and nobody could read
 * it, which is the whole point of the row: it is the only thing saying why
 * this field has no Edit link beside it.
 */
.field-locked {
  display: inline-flex; align-items: center; gap: 6px;
  color: var(--ink-secondary); font-size: 13px; flex-shrink: 0;
}
.btn-link { background: none; border: none; color: var(--accent); padding: 0; font-size: 13px; font-weight: 500; cursor: pointer; text-decoration: none; flex-shrink: 0; }
.btn-link:hover { text-decoration: underline; background: none; }
.field-edit-form { padding: 10px 12px; border-left: 3px solid var(--ink-warning); background: var(--fill-warning); margin: 0; }
.field-edit-form label { display: block; font-size: 12px; color: var(--ink-muted); margin-bottom: 4px; margin-top: 8px; }
.field-edit-form label:first-child { margin-top: 0; }
.field-edit-form input[type="text"], .field-edit-form input[type="file"], .field-edit-form select { width: 100%; margin-bottom: 2px; }
.field-actions { display: flex; gap: 8px; margin-top: 10px; }
.field-optional { color: var(--ink-muted); font-size: 11px; font-weight: normal; }

/* ── Report mark (item 86) ──────────────────────────────────────────── */
.logo-panel { display: flex; gap: 20px; align-items: flex-start; }
.logo-tile { min-width: 112px; min-height: 112px; flex: none; max-width: 340px; display: flex; align-items: center; justify-content: center; }
.logo-tile.is-monogram { width: 112px; border-radius: 10px; background: var(--ground); }
.logo-tile img { max-width: 100%; max-height: none; width: auto; height: auto; }
.logo-monogram { font-size: 40px; font-weight: 600; color: var(--ink-muted); }
.logo-side { flex: 1; min-width: 0; }
.logo-provenance { margin: 0 0 10px; color: var(--ink-muted); }
.logo-actions { display: flex; flex-wrap: wrap; gap: 8px 12px; align-items: center; }
.logo-form { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 0; }
.logo-remove { margin: 0; }
.logo-hint { margin: 10px 0 0; font-size: 13px; color: var(--ink-muted); max-width: 60ch; }
.logo-error { margin: 0 0 10px; padding: 8px 12px; border-radius: 3px; background: var(--fill-critical); border-left: 4px solid var(--ink-critical); color: var(--ink-body); }

/* ── The public landing page (item 115) ─────────────────────────
   Its own section, no app shell: the marketing side can grow here
   without the console's layout coming with it. */
body.lp { background: var(--page); color: var(--ink-body); }
/*
 * The public page wears the product's chrome — `public-01-marketing.png`.
 *
 * The bar was white with the word "ConsentBot" set in body ink, so the one
 * page a stranger sees first was the one page with no mark on it and no
 * colour the product uses anywhere else. It is the app bar's navy, with the
 * app bar's mark and wordmark, and the contact band that closes the page is
 * the same navy rather than a grey that reads as another content section.
 */
.lp-top {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 32px; background: var(--brand-bar); color: #fff;
}
.lp-mark { display: inline-flex; align-items: center; gap: 10px; }
.lp-top .appbar-word { font-size: 17px; font-weight: 700; letter-spacing: -.01em; color: #fff; }
.lp-top .appbar-word span { color: var(--brand-mark); }
.lp-top .btn { background: var(--page); border-color: var(--page); color: var(--brand-bar); }

.lp-hero { max-width: 760px; margin: 0 auto; padding: 72px 24px 56px; text-align: center; }
.lp-hero h1 {
  margin: 0 0 18px; font-size: 42px; line-height: 1.1; font-weight: 600;
  letter-spacing: -.025em; color: var(--ink-primary);
}
.lp-lede { max-width: 60ch; margin: 0 auto; font-size: 17px; line-height: 1.6; color: var(--ink-secondary); }
.lp-cta { margin: 28px 0 10px; }
.lp-note { margin: 0; font-size: 13px; color: var(--ink-muted); }
/* The platform strip: recognition first, names second. */
.lp-logos {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 14px 22px;
  max-width: 720px; margin: 34px auto 0;
}
.lp-logo { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; color: var(--ink-secondary); }
.vmark {
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 8px; flex: none; overflow: hidden; vertical-align: middle;
}
.vmark--plain { background: none; }
.vmark-t { font-size: 12px; font-weight: 650; color: #fff; }

.lp-logos--cmp { max-width: 860px; margin-top: 4px; }
/* A monogram until a real mark exists: an honest initial beats an invented colour. */
.lp-mono {
  width: 34px; height: 34px; flex: none; border-radius: 8px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--fill-neutral); color: var(--ink-secondary);
  font-family: var(--font-mono); font-size: 13px; font-weight: 600;
}
.lp-band--cmp { background: var(--page); text-align: center; }
/* This band names the platforms a buyer is checking for — it earns a real heading. */
.lp-band h2.lp-h2--big {
  font-family: var(--font-sans); font-size: 24px; font-weight: 600; letter-spacing: -.015em;
  text-transform: none; color: var(--ink-primary); margin-bottom: 30px;
}
/* Wordmarks, not tiles: each vendor supplied a horizontal lockup. */
.lp-cmps {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: 24px 48px; max-width: 900px; margin: 0 auto;
}
.lp-cmp { display: inline-flex; flex-direction: column; align-items: center; gap: 7px; }
.lp-cmp img, .lp-cmp svg { display: block; }
.lp-cmp small { font-size: 11.5px; color: var(--ink-muted); }
.lp-band--cmp .lp-foot { text-align: center; }

.lp-band { padding: 48px 24px; border-top: 1px solid var(--hair); background: var(--inset); }
.lp-band--plain { background: var(--page); }
.lp-band--quiet { background: var(--ground); text-align: center; }
/*
 * The contact band closes the page in the product's navy —
 * `public-01-marketing.png`.
 *
 * It has to sit AFTER `.lp-band`, and that is not a nicety. Both selectors are
 * one class deep, so the cascade settles them by order: declared above the
 * base rule, the navy background lost and the white text won, which put white
 * type on a near-white band. Unreadable, and invisible to every test in this
 * repo — no assertion compares a colour to the colour behind it.
 */
.lp-band--contact { background: var(--brand-bar); text-align: center; }
/* `h2.lp-h2--big` carries an element selector, so matching it takes one too —
   without it the heading stayed navy on navy and all but disappeared. */
.lp-band--contact h2, .lp-band--contact h2.lp-h2--big, .lp-band--contact .lp-lede { color: #fff; }
.lp-band--contact .btn { background: var(--page); border-color: var(--page); color: var(--brand-bar); }
.lp-band h2 {
  max-width: 960px; margin: 0 auto 24px; font-size: 13px; font-weight: 600;
  letter-spacing: .09em; text-transform: uppercase; color: var(--ink-muted);
  font-family: var(--font-mono);
}
.lp-grid {
  max-width: 960px; margin: 0 auto; display: grid; gap: 22px 32px;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
.lp-item h3 { margin: 0 0 6px; font-size: 16px; font-weight: 600; color: var(--ink-primary); }
.lp-item p { margin: 0; font-size: 14.5px; line-height: 1.6; color: var(--ink-secondary); }
.lp-foot { max-width: 960px; margin: 26px auto 0; font-size: 13.5px; line-height: 1.6; color: var(--ink-muted); }
.lp-bottom {
  display: flex; flex-wrap: wrap; gap: 8px 24px; justify-content: space-between;
  padding: 22px 32px; border-top: 1px solid var(--hair);
  font-size: 12.5px; color: var(--ink-muted);
}
@media (max-width: 640px) {
  .lp-hero { padding: 48px 16px 40px; }
  .lp-hero h1 { font-size: 30px; }
  .lp-top, .lp-bottom, .lp-band { padding-left: 16px; padding-right: 16px; }
}

/* ── Console app bar ────────────────────────────────────────────────────
   docs/report-components_v2.html § app-bar, states default / admin /
   admin-switcher-open. Console chrome: never emitted into a report file,
   and with no print behaviour to define — nobody prints the console.

   Sizes live here rather than on the elements. The spec's gallery writes the
   switcher's grade chips at 24px inline; a size written onto an element is a
   size no later rule can override, which is the lesson the report's own
   stylesheet already paid for.
   ─────────────────────────────────────────────────────────────────────── */
/* The band the bar sits in. The bar itself is a rounded card, so the band is
   what insets it from the window edge and what the open menu is measured
   against. */
/*
 * The app bar is not here. It is served from /static/chrome.css, built by
 * src/report/html/chrome-css.ts, and the report's own stylesheet inlines the
 * same string — one copy for both. This file had the second one, as bare
 * .appbar/.switcher-* rules, and the two had drifted apart in about a dozen
 * measurements plus four things that were not taste; chrome-css.ts lists
 * them. The shared rules are scoped .console .x, which both sides emit.
 *
 * .spacer and .runs-running stay below: the first is this sheet's own
 * generic and the second is the run page, not the bar.
 */
.spacer { flex-grow: 1; }

/* The spec's colour vocabulary for a grade chip: by what the grade means,
   not by which letter it is. `.grade.A`/`.C`/… above are the console's older
   spelling and are still what the dashboards emit. */
.grade--pass     { background: var(--fill-pass);     color: var(--ink-pass); }
.grade--warning  { background: var(--fill-warning);  color: var(--ink-warning); }
.grade--critical { background: var(--fill-critical); color: var(--ink-critical); }
.grade--gap      { background: var(--ground); color: var(--ink-secondary); border: 1px dashed var(--ink-muted); }

.muted { color: var(--ink-secondary); font-size: 12px; }
.cookee-title { flex-grow: 1; }

/* Scoped, not global: `#status-badge.running` on the run page is a different
   element with the same class name, and a global `.running::before` would put
   a dot inside a badge that already draws its own. That is not hypothetical —
   the header's own indicator was written unscoped and did exactly this, so
   the badge showed two dots on every running audit. Every rule that means the
   spec's `running` pill names where it applies. */
.runs-running.running {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; font-weight: 600;
  color: var(--accent-hover); background: var(--accent-fill);
  border-radius: var(--radius); padding: 2px 8px;
}
.runs-running.running::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--accent);
}

/* ── Runs table (spec component `runs-table`) ───────────────────────────
   Client → Reports. Its own vocabulary: the spec is explicit that it does
   not reuse the inventory table's, and the console's own `table`/`th`/`td`
   rules above are the older spelling. Values are the spec's.

   `.runs` is itself a card — background, border, radius, padding — so the
   page does not wrap it in one. */
/*
 * No padding of its own: the title row, the running band, the table's first
 * and last cells and the count all carry the card's 24px gutter themselves,
 * so the rules and the band can reach the card's edges. With the card padding
 * on as well, every one of them sat 44px in and the table looked indented
 * inside its own card.
 */
.runs {
  background: var(--page); border: 1px solid var(--card-border);
  border-radius: var(--radius-card); padding: 0; margin-bottom: 16px;
}
/* The `empty` state's paragraph is a `.body`, which the spec's gallery styles and
   kills the margin of with an inline style in the frame itself — and the report's
   own sheet has a `.body` rule. This sheet has none, so without this the
   paragraph takes the browser's default margins inside .runs' padding, where the
   spec draws it flush. Colour and size come from `body` by inheritance; only the
   margin needed saying.

   This shipped as a guard with no rule: the rule was added, then the guard was
   verified by deleting the rule and running the test, then `git checkout --` was
   used to "restore" it — which reverted to HEAD, where the addition had never
   been committed. The guard went out and the rule did not. Verifying a guard by
   deleting its subject only works if the subject is committed first. */
.runs .body { margin: 0; padding: 0 24px 20px; }
/* The console has no global `a { text-decoration: none }` where the spec's
   gallery does, so every link inside this component would render underlined
   and browser-blue. Scoped here rather than added globally, which would
   restyle seven views this task has not looked at. */
.runs a { color: var(--accent); text-decoration: none; }
.runs a:hover { color: var(--accent-hover); text-decoration: underline; }
.runs-running { margin: 0 0 10px; }
.runs-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.runs-table th {
  text-align: left; font-size: 11px; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-secondary);
  padding: 8px 12px; border-bottom: 1px solid var(--card-border);
}
.runs-table td { padding: 10px 12px; border-bottom: 1px solid var(--hair); }
/*
 * The first and last cells inset to the card's own gutter, so the table's
 * text starts on the same vertical line as the card's title, its running band
 * and its count. They were 12px in while everything around them was 24, which
 * left the head and the band looking indented against their own table.
 */
.runs-table th:first-child, .runs-table td:first-child { padding-left: 24px; }
.runs-table th:last-child, .runs-table td:last-child { padding-right: 24px; }
.runs-row--latest { background: var(--accent-fill); }
.runs-latest { font-size: 12px; font-weight: 600; color: var(--accent); margin-left: 6px; }
/*
 * A heading sits over its own column — the user, 2026-10-01.
 *
 * The numbers are right-aligned and the headings were left-aligned, so HIGH,
 * MEDIUM, PASSED and UNTESTED each sat a column-width away from the figure
 * they name. `client-02-reports.png` draws it the same way and is wrong about
 * it; recorded in `docs/mockups/README.md`.
 *
 * `.runs-table th` is more specific than `.runs-n`, so the heading rule has to
 * name both rather than rely on the body rule reaching it.
 */
.runs-n, .runs-table th.runs-n { text-align: right; }
.runs-n { font-family: var(--font-mono); }
.runs-open, .runs-table th.runs-open { text-align: right; }
.grade--sm { width: 28px; height: 28px; font-size: 14px; }
/* A spec-vocabulary grade chip is sized by `.grade--sm`, but the console's
   older `.grade` rule above fixes 44px and 22px. Same specificity, and this
   file is read top to bottom, so `--sm` wins on both — but only because it is
   below. Kept next to the component it belongs to, with the reason written
   down. */

/* Hidden from sight, not from a screen reader. */
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }

/* The runs table's heading sits outside the component, because the spec's
   frame has none, so it is not `.card h2` and would otherwise take the
   browser's own 24px. Structural rather than a new class name. */
main.content > h2 {
  font-size: 13px; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--ink-muted); margin: 0 0 12px; font-weight: 600;
}

/* ── Settings: a rail beside the cards (client-06-settings.png) ──────── */
/*
 * The rail is rendered from the sections themselves, so a section cannot
 * exist without a way to reach it — the failure the old page had in a
 * different form, where four unrelated cards sat in one scroll with no index
 * at all.
 */
.settings { display: grid; grid-template-columns: 200px minmax(0, 1fr); gap: 32px; align-items: start; }
/*
 * The rail — the owner's drawing: one item per section, the current one on a
 * tinted fill in bold dark ink, Delete client in red.
 *
 * It was 14px muted grey with no current state at all, which made six
 * navigation items read as a caption nobody would click.
 *
 * The current item is driven by the URL fragment with no script: `:has()` lets
 * the rail react to which section is `:target`. The six rules below are
 * explicit rather than clever because there are six sections and a reader has
 * to be able to see which rule fires. Before anything is clicked nothing is
 * targeted, so the first item is current — which is also what the page is
 * actually showing.
 */
.settings-rail { display: flex; flex-direction: column; gap: 2px; position: sticky; top: 24px; }
.settings-rail a {
  padding: 14px 16px; border-radius: var(--radius);
  color: var(--ink-primary); text-decoration: none; font-size: 16px;
}
.settings-rail a/*
 * Red words, not a red box. A destructive action reads as destructive by its
 * label; outlining it as well makes every row on a list look like a warning.
 * The confirmation is where the weight belongs, and it has it.
 */
.danger-link { color: var(--ink-critical); }
button.btn.danger-link, .btn.danger-link { border-color: var(--card-border); background: var(--page); }
.settings-rail a:hover { background: var(--page); }

/* Current: tinted and bold. */
.settings-rail a[data-on] { background: var(--accent-fill); font-weight: 600; }
.settings:not(:has(:target)) .settings-rail a:first-child { background: var(--accent-fill); font-weight: 600; }
.settings:has(#site:target) .settings-rail a[href="#site"],
.settings:has(#audit-scope:target) .settings-rail a[href="#audit-scope"],
.settings:has(#container-source:target) .settings-rail a[href="#container-source"],
.settings:has(#access:target) .settings-rail a[href="#access"],
.settings:has(#report-mark:target) .settings-rail a[href="#report-mark"],
.settings:has(#delete:target) .settings-rail a[href="#delete"] {
  background: var(--accent-fill); font-weight: 600;
}

.settings-body { min-width: 0; display: flex; flex-direction: column; gap: 20px; }
.settings-body .card { margin-bottom: 0; }
.card--danger { border-color: var(--ink-critical); }
/*
 * Red words, not a red box. A destructive action reads as destructive by its
 * label; outlining it as well makes every row on a list look like a warning.
 * The confirmation is where the weight belongs, and it has it.
 */
.danger-link { color: var(--ink-critical); }
button.btn.danger-link, .btn.danger-link { border-color: var(--card-border); background: var(--page); }

@media (max-width: 899px) {
  .settings { grid-template-columns: minmax(0, 1fr); gap: 20px; }
  .settings-rail { position: static; flex-direction: row; flex-wrap: wrap; }
}

/* The grade cell on the clients list: the square, then what qualifies it. */
.grade-cell { display: inline-flex; align-items: center; gap: 10px; }
.chip.info { background: var(--accent-fill); color: var(--accent); }

/* The clients list's header row: title, then search and the primary action. */
.topbar-actions { display: flex; align-items: flex-end; gap: 12px; }
.search { display: flex; flex-direction: column; gap: 4px; margin: 0; }
.search label { font-size: 13px; color: var(--ink-secondary); }
.search input {
  height: 40px; padding: 0 12px; font: 400 14px var(--font-sans);
  border: 1px solid var(--card-border); border-radius: var(--radius);
  background: var(--page); color: var(--ink-primary); min-width: 260px;
}
.search input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.topbar { align-items: flex-end; }

/* ── Signed-out pages (public-02-sign-in.png) ───────────────────────── */
.auth { max-width: 480px; margin: 120px auto; padding: 0 16px; text-align: center; }
.auth-brand {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  margin-bottom: 24px; color: var(--brand-bar);
}
.auth-brand .appbar-word { font-size: 24px; font-weight: 700; letter-spacing: -0.01em; }
.auth-brand .appbar-word span { color: var(--accent); }
.auth .card h1 { font-size: 22px; margin: 0 0 12px; }
.auth .card p { color: var(--ink-body); margin: 0 0 16px; }
.auth .card .btn { display: inline-flex; }
.auth .lp-note a { color: var(--accent); text-decoration: none; }
.auth .lp-note a:hover { text-decoration: underline; }

/* The delete confirmation (console-03-delete-client.png). */
.confirm h1 { font-size: 22px; margin: 4px 0 12px; }
.confirm .field { margin: 16px 0 12px; }
.confirm .field label { display: block; margin-bottom: 6px; font-size: 14px; }
.confirm input {
  width: 100%; height: 40px; padding: 0 12px; font: 400 14px var(--font-sans);
  border: 1px solid var(--card-border); border-radius: var(--radius); background: var(--page);
}
.actions--end { justify-content: flex-end; }
/* The card zeroes its own padding for the ruled rows, so the action bar
   carries its own — the buttons were sitting on the card's edge. */
.fsections .actions { padding: 20px 24px; border-top: 1px solid var(--hair); margin-top: 0; }
button.danger, .btn.danger { background: var(--ink-critical); border-color: var(--ink-critical); color: #fff; }
/*
 * Disabled-looking until the typed value matches, with no script: `pattern`
 * makes the form invalid and the browser refuses the submit either way. This
 * is appearance following a rule the browser is already enforcing, not a
 * second gate — the server checks again regardless.
 */
form:invalid button.danger { opacity: .55; }

/* ── Sectioned forms (console-02-add-client.png) ────────────────────── */
/*
 * Every field is its own row, ruled off from the next — the same shape the
 * settings page uses, and what `console-02-add-client.png` draws. Without the
 * rules, twelve fields in four groups read as one long column and the grouping
 * carried no weight.
 *
 * The rules span the card, so the rows run to its edges and carry their own
 * horizontal padding; the section heading sits in a band above them.
 */
.fsections { padding: 0; }
.fsection { border-top: 1px solid var(--hair); }
.fsection:first-child { border-top: none; }
.fsection h2 {
  font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: .08em;
  color: var(--ink-secondary); margin: 0; padding: 18px 24px 4px;
}
.frow {
  display: grid; grid-template-columns: 200px minmax(0, 1fr); gap: 20px; align-items: start;
  padding: 14px 24px; border-top: 1px solid var(--hair);
}
.fsection h2 + .frow { border-top: none; }
.frow-label { font-size: 14px; color: var(--ink-body); padding-top: 10px; }
/* Capped so a field does not run the frame's full width. */
.frow-control { max-width: 820px; }
.frow-control input[type="text"], .frow-control input[type="url"], .frow-control select {
  width: 100%; height: 40px; padding: 0 12px; font: 400 14px var(--font-sans);
  border: 1px solid var(--card-border); border-radius: var(--radius); background: var(--page);
  color: var(--ink-primary);
}
/*
 * :user-invalid, not :invalid.
 *
 * `:invalid` matches an empty required field the moment the page renders, so
 * the form opened with its first empty box already outlined red — an error
 * about something nobody had done yet. `:user-invalid` waits until the field
 * has been interacted with, which is when the mockup shows its red container
 * ID and its message.
 */
.frow-control input:user-invalid { border-color: var(--ink-critical); }
.frow-help { margin: 6px 0 0; font-size: 13px; color: var(--ink-secondary); }
.frow-control input[type="file"] { margin-top: 12px; font-size: 13px; }
.frow-control .inline { display: inline-flex; align-items: center; gap: 8px; margin-bottom: 8px; }

/* The container source as two selectable cards, not two bare radios. */
.choices { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.choice {
  display: flex; align-items: flex-start; gap: 10px; padding: 14px 16px; font-size: 14px;
  border: 1px solid var(--card-border); border-radius: var(--radius); background: var(--page);
  line-height: 1.45;
  /* `form label` is 600 for a field label. Inside a choice only the title is,
     and without this the whole card renders bold. */
  font-weight: 400;
}
.choice input { margin-top: 3px; flex: none; }
/*
 * The card is a submit button, so it resets what a button brings: left-aligned
 * text, its own background, and a pointer only where pressing does something.
 * The current source is `disabled` because it is already in effect, and it
 * must still read as SELECTED rather than as unavailable — so it keeps full
 * opacity and only the genuinely unavailable one dims.
 */
button.choice {
  text-align: left; font: 400 14px var(--font-sans); width: 100%;
  /* `button, .btn` sets a 40px height for controls — a choice card is not one,
     and at 40px its description rendered outside its own border. */
  height: auto; align-items: flex-start;
}
button.choice > span { display: block; min-width: 0; }
button.choice:not(:disabled) { cursor: pointer; }
button.choice:not(:disabled):hover { border-color: var(--accent-line); background: var(--inset); }
button.choice.choice--on:disabled { opacity: 1; cursor: default; }
button.choice.choice--off:disabled { opacity: .6; cursor: not-allowed; }
/*
 * The card is a submit button, so it resets what a button brings: left-aligned
 * text, its own background, and a pointer only where pressing does something.
 * The current source is `disabled` because it is already in effect, and it
 * must still read as SELECTED rather than as unavailable — so it keeps full
 * opacity and only the unavailable one dims.
 */
button.choice {
  text-align: left; font: 400 14px var(--font-sans); width: 100%;
  /* `button, .btn` sets a 40px height for controls — a choice card is not one,
     and at 40px its description rendered outside its own border. */
  height: auto; align-items: flex-start;
}
button.choice > span { display: block; min-width: 0; }
button.choice:not(:disabled) { cursor: pointer; }
button.choice:not(:disabled):hover { border-color: var(--accent-line); background: var(--inset); }
button.choice.choice--on:disabled { opacity: 1; cursor: default; }
button.choice.choice--off:disabled { opacity: .6; cursor: not-allowed; }
/*
 * The card is a submit button, so it resets what a button brings: left-aligned
 * text, the card's own background, and a pointer only where pressing does
 * something. The current source is `disabled` — it is already in effect — and
 * dims no further than the border, because it is the selected one and must
 * still read as selected rather than as unavailable.
 */
button.choice {
  text-align: left; font: 400 14px var(--font-sans); width: 100%;
  /* `button, .btn` sets a 40px height for controls — a choice card is not one,
     and at 40px its description rendered outside its own border. */
  height: auto; align-items: flex-start;
}
button.choice > span { display: block; min-width: 0; }
button.choice:not(:disabled) { cursor: pointer; }
button.choice:not(:disabled):hover { border-color: var(--accent-line); background: var(--inset); }
button.choice.choice--on:disabled { opacity: 1; cursor: default; }
button.choice.choice--off:disabled { opacity: .6; cursor: not-allowed; }
.choice:has(input:checked) { border-color: var(--accent); background: var(--accent-fill); }
.choice b { font-weight: 600; }
/* Three cards where the choice has three answers: Add client's tag manager. */
.choices--3 { grid-template-columns: repeat(3, 1fr); }
/*
 * Only the fields the checked card needs. `[data-when]` names the choice a
 * field belongs to, and it is hidden unless that card is checked. Hiding
 * rather than showing keeps each field's own display, and a browser without
 * `:has()` shows every field instead of none.
 */
form:not(:has(input[name="gtmSourceKind"][value="gcs"]:checked)) [data-when="gcs"],
form:not(:has(input[name="gtmSourceKind"][value="live"]:checked)) [data-when="live"],
form:not(:has(input[name="gtmSourceKind"][value="none"]:checked)) [data-when="none"] { display: none; }
@media (max-width: 899px) {
  .frow { grid-template-columns: minmax(0, 1fr); gap: 6px; }
  .frow-label { padding-top: 0; }
  .choices { grid-template-columns: 1fr; }
}

/* ── Settings cards (client-06-settings.png) ────────────────────────── */
/*
 * Every section is a header band, a hairline, then its body. The heading is
 * §2b's Heading role (18/600, title case) — the console's `.card h2` renders
 * the 12px uppercase Label, which is for the small labels INSIDE a card, and
 * using it here made six sections read as six captions.
 */
.card--sect { padding: 0; }
.sect-head {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 18px 24px; border-bottom: 1px solid var(--hair);
}
.card--sect .sect-head h2 {
  font-size: 18px; font-weight: 600; letter-spacing: -0.01em;
  color: var(--ink-primary); text-transform: none; margin: 0;
}
.sect-lede { margin: 4px 0 0; font-size: 14px; color: var(--ink-secondary); }
.sect-body { padding: 20px 24px; }
/* Rows run to the card's edges so each hairline spans its full width. */
.card--rows .sect-body { padding: 0; }
.card--danger .sect-head { border-bottom: none; }

/* Chips in a settings value read as a set, so they take the neutral fill. */
.field-value .chip { background: var(--fill-neutral); color: var(--ink-secondary); }

/*
 * The rail marks where you are. `:target` is what makes it work without a
 * script: the rail links are fragments, so following one both scrolls to the
 * section and selects it. Nothing is highlighted before the first click,
 * which is the honest state — the page has not been navigated yet.
 */
.card--sect:target { scroll-margin-top: 24px; }

/* The two source cards, and the one with nothing behind it. */
.source-choice { padding: 20px 24px; }
.source-choice .choices { margin-bottom: 16px; }
.choice--on { border-color: var(--accent); background: var(--accent-fill); }
.choice--off { opacity: .6; }
.choice .mono { font-size: 12.5px; }
.choice .chip--gap { margin-top: 6px; display: inline-flex; }

/* A labelled row of controls inside a section body. */
.sect-row {
  display: flex; align-items: center; gap: 16px;
  padding: 16px 24px; border-top: 1px solid var(--hair);
}
.sect-row-label { font-size: 14px; color: var(--ink-body); width: 200px; flex-shrink: 0; }
.sect-row .logo-form { display: flex; align-items: center; gap: 12px; margin: 0; }
.source-choice + .logo-error { margin: 0 24px; }
.card--sect .logo-hint { margin: 12px 24px 20px; max-width: 760px; }
/*
 * The hint belongs to the upload controls, so it starts where they start —
 * it was flush to the card and read as a note about the mark beside it.
 */
.logo-side .logo-hint, .logo-panel .logo-hint { margin-left: 0; }

/* The chart card's heading and its legend share a row (client-01-home.png). */
.chart-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
.chart-head .sub { margin-bottom: 0; }
.chart .legend { margin: 0; }

/* ── The runs table (client-02-reports.png) ─────────────────────────── */
/*
 * The card's own title row, the running band under it, and the count that
 * closes it. The band used to sit above everything and outside the table's
 * width, so it read as a notice about the page rather than a row about to
 * join this list.
 */
.runs-head {
  display: flex; align-items: baseline; gap: 16px;
  padding: 18px 24px 0;
}
.runs-head h2 {
  font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: .08em;
  color: var(--ink-secondary); margin: 0;
}
.runs-head .sub { margin: 0; color: var(--ink-secondary); font-size: 13px; }
.runs .runs-running {
  display: flex; align-items: center; gap: 10px;
  margin: 12px 24px 16px; padding: 10px 14px;
  background: var(--accent-fill); border-radius: var(--radius); color: var(--accent);
  font-size: 14px;
}
.runs .runs-running .muted { color: var(--ink-secondary); font-weight: 400; }
.runs .runs-running a { margin-left: auto; color: var(--accent); text-decoration: none; font-weight: 600; }
.runs .runs-running a:hover { text-decoration: underline; }
.runs-foot {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 24px 18px; font-size: 13px;
}
.runs-foot a { color: var(--accent); text-decoration: none; }
.runs-foot a:hover { text-decoration: underline; }

/* Region chips sit in one line and never wrap a row taller than its neighbours. */
.runs-regions { white-space: nowrap; }
.runs-regions .chip { margin-right: 4px; }
.runs-gtm, .runs-cmp { white-space: nowrap; }
.runs-gtm .mono, .runs-cmp .mono { font-family: var(--font-mono); font-size: 12.5px; }
.runs-gtm .chip--gap { margin-left: 6px; }
.chip--pass { background: var(--fill-pass); color: var(--ink-pass); }
.chip--critical { background: var(--fill-critical); color: var(--ink-critical); }
.chip--warning { background: var(--fill-warning); color: var(--ink-warning); }
.chip--neutral { background: var(--fill-neutral); color: var(--ink-neutral); }
.chip--gap { background: none; border: 1px dashed var(--rule); color: var(--ink-secondary); }
@media (max-width: 1279px) { .runs-table { font-size: 13px; } }

/* ── Cookee chats (client-03-cookee-chats.png) ──────────────────────── */
.chats { padding: 0; }
.chats-head {
  display: flex; align-items: flex-end; justify-content: space-between; gap: 24px;
  padding: 18px 24px;
}
.chats-head h2 {
  font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: .08em;
  color: var(--ink-secondary); margin: 0;
}
.chats-head .sub { margin: 4px 0 0; }
.chats-tools { display: flex; align-items: flex-end; gap: 16px; margin: 0; }
.chats-tools label {
  display: flex; flex-direction: column; gap: 4px;
  font-size: 13px; font-weight: 400; color: var(--ink-secondary);
}
.chats-tools select, .chats-tools input {
  height: 40px; padding: 0 12px; font: 400 14px var(--font-sans);
  border: 1px solid var(--card-border); border-radius: var(--radius);
  background: var(--page); color: var(--ink-primary);
}
.chats-tools input { min-width: 240px; }
.chats-table th, .chats-table td { padding: var(--cell-y, 10px) 24px; }
.chats-table .chats-actions { text-align: right; white-space: nowrap; }
.chats-table td.chats-actions { display: table-cell; }
.chats-table td.chats-actions form { display: inline-block; margin: 0 0 0 8px; }
.chats-foot { padding: 14px 24px 18px; font-size: 13px; }
.chats-table td.chats-actions .btn { margin-left: 8px; }

/*
 * One chat, read as a page — client-04-cookee-chat.png.
 *
 * The card runs edge to edge inside its own padding: the head, the note and
 * the composer each have their own, and the transcript keeps the card's so a
 * bubble never touches the border.
 */
.chat { padding: 0; overflow: hidden; }
.chat-back { margin-bottom: 8px; }
.chat-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 24px; padding: 22px 24px 18px;
}
.chat-head h1 { font-size: 21px; margin: 0 0 4px; }
.chat-head .meta { margin: 0; }
.chat-actions { display: flex; align-items: flex-start; gap: 8px; }
.chat-actions form { margin: 0; }
/* Rename opens in place. `<details>` is the whole mechanism, so the summary
   has to look and sit exactly like the two controls beside it. */
.chat-rename { position: relative; }
.chat-rename > summary { list-style: none; cursor: pointer; display: inline-flex; align-items: center; }
.chat-rename > summary::-webkit-details-marker { display: none; }
.chat-rename[open] > summary { background: var(--inset); }
.chat-rename > form {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 2;
  display: flex; gap: 8px; margin: 0; padding: 10px;
  background: var(--page); border: 1px solid var(--card-border);
  border-radius: var(--radius-card); box-shadow: 0 6px 18px rgba(20, 33, 61, 0.12);
}
/*
 * `form input[type="text"]` above is (0,1,2) and `.chat-rename input` was
 * (0,1,1), so the generic rule's `width: 100%` won — 100% of a shrink-to-fit
 * popover, which measured 22px (the user, 2026-10-01: "a very small box
 * appears, making it difficult to rename"). Named with the attribute so the
 * two are compared on equal terms and this one wins on being more specific
 * rather than on luck.
 */
.chat-rename > form input[type="text"] { width: 320px; }

/* The one line that says where the answers come from, set apart from both the
   title above it and the transcript below — the same band the drawer draws. */
.chat-note {
  margin: 0; padding: 12px 24px;
  background: var(--ground); border-top: 1px solid var(--hair); border-bottom: 1px solid var(--hair);
  color: var(--ink-secondary); font-size: 13px;
}

.chat-thread {
  display: flex; flex-direction: column; gap: 18px;
  min-height: 420px; max-height: 620px; overflow-y: auto;
  padding: 24px; background: var(--page);
}
.chat-turn { display: flex; }
/* The reader's questions right, Cookee's answers left: the mockup's shape, and
   the one cue that tells the two apart without a label on every bubble. */
.chat-turn--user { justify-content: flex-end; }
.chat-turn--cookee { justify-content: flex-start; }
.chat-turn .chat-text { max-width: 72%; font-size: 14.5px; line-height: 1.55; }
/* A question is a short thing someone typed, so it wears a bubble. An answer
   runs to paragraphs, headings and lists, and a tinted box around several
   hundred words reads as a quotation rather than as the page's own text. */
.chat-turn--user .chat-text {
  background: var(--accent-fill); color: var(--ink-primary);
  border-radius: var(--radius-card); padding: 10px 14px;
}
.chat-turn--cookee .chat-text { color: var(--ink-body); }
.chat-text > *:first-child { margin-top: 0; }
.chat-text > *:last-child { margin-bottom: 0; }
.chat-text p { margin: 0 0 10px; }
.chat-text ul, .chat-text ol { margin: 0 0 10px; padding-left: 20px; }
.chat-text h2, .chat-text h3 { font-size: 14.5px; margin: 14px 0 6px; }
.chat-text code {
  font-family: var(--font-mono); font-size: 12.5px;
  background: var(--inset); border: 1px solid var(--hair); border-radius: var(--radius); padding: 1px 4px;
}

.chat-form {
  display: flex; gap: 10px; margin: 0;
  padding: 16px 24px; border-top: 1px solid var(--hair); background: var(--page);
}
.chat-form input { flex: 1; }
/* Icon-only, so square and centred: the shared button rule is built around a
   label with an optional glyph beside it, and left the arrow against the left
   edge of a 44px box. */
.chat-form button { width: 44px; padding: 0; font-size: 16px; justify-content: center; }

@media (max-width: 899px) {
  .chat-head { flex-direction: column; gap: 14px; }
  .chat-actions { flex-wrap: wrap; }
  .chat-rename > form { position: static; box-shadow: none; }
  .chat-rename > form input[type="text"] { width: auto; flex: 1; }
  .chat-turn .chat-text { max-width: 100%; }
}
.chats--empty { padding: 24px; text-align: center; }
.chats--empty h2 { margin-bottom: 8px; }
.chats--empty a { color: var(--accent); text-decoration: none; }

/* ── The run in flight (client-07-run-progress.png) ─────────────────── */
/*
 * Two columns: the run's state and its test grid on the left, the live log
 * and the report slot on the right. It was one column of five stacked cards,
 * twice the height of the drawing, with the log folded away behind a
 * <details> — on the one page whose whole purpose is watching something
 * happen.
 */
.runpage {
  display: grid; grid-template-columns: minmax(0, 1fr) var(--rail, 400px);
  gap: var(--col-gap, 32px); align-items: start;
}
.runpage-main, .runpage-rail { display: flex; flex-direction: column; gap: 20px; min-width: 0; }
.runpage .card { margin-bottom: 0; }

/* One baseline for the heading, the badge and the clock. Centring instead put
   the badge's text a couple of pixels above the words either side of it: the
   three boxes are different heights, so their centres do not line up even
   though their text should. */
.runstate-head { display: flex; align-items: baseline; gap: 16px; margin-bottom: 20px; }
.runstate-head h1 { font-size: 22px; margin: 0; }
.runstate-clock { color: var(--ink-secondary); font-size: 14px; }
/* Space, not a rule. The mockup separates the stepper from the counters with
   nothing but air — a hairline here would be the third horizontal line in a
   card 250px tall. */
/* The stepper is closed by a rule. What is under it — the activity line while
   a test is running, the counters before one starts — is a different kind of
   statement, and the card is tall enough that space alone did not separate
   them. */
/* Spacing and the closing rule are on `#phase-stepper` itself — its id beats
   any selector written here. */
.runstate .kpis { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.runstate .kpi { border-left: none; padding: 0; }

.runtests-head { display: flex; align-items: baseline; gap: 12px; margin-bottom: 4px; }
.runtests-head h2 { margin: 0; }
.runtests-head .sub { margin: 0; }
/*
 * A scenario per row, a region per column — client-07-run-progress.png.
 *
 * The region columns share what the two text columns leave, evenly, so two
 * regions do not sit at different widths because one chip says "Queued" and
 * the other "Skipped". The status sits in its own column, centred on the
 * column heading, because the reader is comparing down a column, not along
 * a row.
 */
.matrix { table-layout: fixed; }
.matrix th:first-child, .matrix td:first-child { width: 88px; }
.matrix th:nth-child(2), .matrix td:nth-child(2) { width: 28%; }
.matrix .rcol { text-align: left; }
/* "Not run here" is a fact about the plan, not a result: it is set in the
   muted ink every other absence uses, never as a chip. */
.matrix td.na { color: var(--ink-muted); font-size: 12.5px; }

/* Nothing has started, so the line says nothing rather than repeating the
   log's waiting copy beside it. */
#activity-line:empty { display: none; }

.runlog-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
.runlog-head h2 { margin: 0; }
.runlog-head .mono { font-family: var(--font-mono); font-size: 12.5px; color: var(--ink-secondary); }
/*
 * The log is visible, not folded away. It was inside a closed <details> on
 * the one page whose purpose is watching something happen.
 */
.runlog .log {
  display: block; margin: 0; height: 430px; overflow: auto;
  background: var(--brand-bar); color: #D7DEEE;
  border-radius: var(--radius); padding: 14px 16px;
  font-family: var(--font-mono); font-size: 12.5px; line-height: 1.5;
  white-space: pre-wrap; overflow-wrap: anywhere;
}
/* A slot waiting to be filled reads as a slot: dashed, like every other
   "the audit has not got here yet" surface in the report. */
.card--awaiting { border-style: dashed; }

@media (max-width: 1279px) {
  .runpage { grid-template-columns: minmax(0, 1fr); }
  .runlog .log { height: 260px; }
}

/*
 * A run in flight is the accent, not amber. Amber is the warning role — it
 * means a result needs attention — and a run that has merely started is not a
 * warning about anything. The other statuses keep their own roles.
 */
#status-badge.initializing, #status-badge.running {
  background: var(--accent-fill); color: var(--accent);
  display: inline-flex; align-items: center; gap: 8px;
  height: 28px; padding: 0 12px; border-radius: var(--radius); font-weight: 600; font-size: 13px;
}

/* The Viewers row: one viewer per line, with what became of their invitation. */
/* The Viewers block — enhancements/viewers-mockup.png. One row per viewer,
   Remove confirmed in the row, and an add box under the list. */
.viewer-head { display: flex; align-items: center; gap: 16px; padding: 14px 24px 6px; }
.viewer-head .field-label { width: auto; }
.viewer-count { font-size: 13px; color: var(--ink-muted); }
.viewer-row { display: flex; align-items: center; gap: 16px; padding: 12px 24px; border-bottom: 1px solid var(--hair); min-height: 52px; }
.viewer-email { flex: 0 0 260px; min-width: 0; font-size: 14px; color: var(--ink-primary); overflow-wrap: anywhere; }
.viewer-state { flex: 1; min-width: 0; font-size: 13px; color: var(--ink-muted); }
.viewer-actions { display: flex; gap: 16px; align-items: center; flex-shrink: 0; }
.viewer-actions button:not(.btn-link) { padding: 5px 12px; font-size: 13px; }
.btn-link.viewer-remove { color: var(--ink-critical); }
.viewer-row--confirm { background: var(--fill-critical); }
.viewer-row--confirm .viewer-state { color: var(--ink-critical); }
.viewer-add { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; padding: 14px 24px; border-bottom: 1px solid var(--hair); background: var(--inset); }
.viewer-add .error-box { flex-basis: 100%; margin: 0; }
.viewer-add input { flex: 1; min-width: 200px; }
@media (max-width: 640px) {
  .viewer-row { flex-wrap: wrap; gap: 4px 16px; }
  .viewer-email { flex-basis: 100%; }
}
.viewer-invite-failed { color: var(--ink-critical); }

/* Sign-in by code: spacing for the stacked form controls. */
.auth form { margin: 14px 0 0; }
.auth form label { display: block; margin-bottom: 6px; }
.auth form input[type="email"], .auth form input[type="text"] { box-sizing: border-box; width: 100%; margin-bottom: 12px; }
.auth form input[name="code"] { text-align: center; font-size: 20px; letter-spacing: 0.3em; }
.auth .card .auth-message { color: var(--ink-critical); }
.auth .card .lp-note { margin-top: 20px; }
.auth .card .auth-hint { font-size: 13px; color: var(--ink-muted); margin: 8px 0 0; }

/* ════ Resources ═════════════════════════════════════════════════════════
   Everything for the public site chrome and /resources lives below this line.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── Shared public header: the nav and the phone menu ───────────────────
   site-chrome.ts. `.lp-top` and `.lp-bottom` above are unchanged; these add
   Product · Resources · Sign in (HANDOFF.md) and, under 760px, a 48px menu
   button opening a plain drop-down list (spec D10). A <details>, so the
   menu works with no script at all. */
.lp-top { position: relative; }
.lp-mark { text-decoration: none; }
.lp-nav { display: flex; align-items: center; gap: 30px; font-size: 15px; }
.lp-nav-link { color: var(--rs-on-navy); text-decoration: none; }
.lp-nav-link:hover { color: #fff; }
.lp-nav-link[aria-current="page"] { color: #fff; font-weight: 600; padding: 5px 0; box-shadow: inset 0 -2px 0 #fff; }
.lp-menu { display: none; }
.lp-act-short { display: none; }
.lp-menu > summary {
  list-style: none; width: 48px; height: 48px; display: flex; align-items: center; justify-content: center;
  cursor: pointer; border-radius: 8px;
}
.lp-menu > summary::-webkit-details-marker { display: none; }
.lp-menu > summary:focus-visible { outline: 2px solid #fff; outline-offset: -4px; }
.lp-menu-list {
  position: absolute; right: 8px; top: calc(100% - 4px); z-index: 30; min-width: 220px;
  margin: 0; padding: 8px 0; list-style: none; background: var(--page); border-radius: 12px;
  box-shadow: 0 12px 32px rgba(20, 33, 61, .18);
}
.lp-menu-list a {
  display: flex; align-items: center; min-height: 48px; padding: 0 20px;
  font-size: 16px; font-weight: 600; color: var(--brand-bar); text-decoration: none;
}
.lp-menu-list a:hover { background: var(--accent-fill); }
.lp-menu-list a[aria-current="page"] { color: var(--accent); }
@media (max-width: 759px) {
  .lp-top:not(.lp-top--plain) { padding: 6px 4px 6px 16px; } /* 6 + 48 menu button + 6 = 60px (HANDOFF.md) */
  .lp-top:not(.lp-top--plain) .lp-mark { min-height: 44px; } /* a 44px tap target, like every other control */
  .lp-nav { gap: 4px; }
  .lp-nav-link { display: none; }
  .lp-menu { display: block; }
  .lp-top:not(.lp-top--plain) .btn { height: 44px; }
  .lp-act-long { display: none; }
  .lp-act-short { display: inline; }
}

/* ── Resources ("Consent Briefing") ──────────────────────────────────────
   docs/design-briefs/resources/*-reference.html are the source of truth;
   HANDOFF.md's "Decisions (final)" are binding. The references are inline
   styles; each rule below names the reference element it was copied from.

   Every class is prefixed `rs-` because the console already owns `.btn`,
   `.card`, `.lab`, `.meta` and `.mono` in this sheet. The tile classes
   (`.tile`, `.tone-*`, `.k-*`, `.m-*`, `.u`) are copied as-is (HANDOFF.md
   § Image system).

   Two global rules in this sheet reach into these pages and are undone
   here on purpose: `button, .btn { height: 40px; … }` (every rs- button sets
   its own height, border and background) and `h1 { font-size: 22px; … }`. */
body.rs { -webkit-font-smoothing: antialiased; }
:where(.rs) :where(h1, h2, h3, p, ol) { margin: 0; }
/* Zero specificity, so any rs- class that sets a colour wins. */
:where(.rs) a { color: var(--accent); text-decoration: none; }
:where(.rs) a:where(:hover) { color: var(--accent-hover); }
.rs mark { background: var(--rs-mark); color: inherit; border-radius: 3px; padding: 0 2px; }
.rs-visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.rs-skip { position: absolute; left: -9999px; top: 8px; z-index: 40; background: var(--page); padding: 10px 14px; border-radius: 8px; }
.rs-skip:focus { left: 8px; }
.rs-wrap { max-width: 1200px; margin: 0 auto; padding: 0 24px; }

/* Type: `.lab`, `.meta`, `.ttl`, `.sh`, `.h2a` in the references' <style>. */
.rs-lab {
  font-family: var(--font-mono); font-size: 11px; line-height: 1.2; letter-spacing: .14em;
  text-transform: uppercase; font-weight: 700; color: var(--ink-secondary);
}
.rs-lab--navy { color: var(--brand-bar); }
.rs-lab--on-navy { color: var(--brand-mark); }
.rs-meta { font-size: 13px; line-height: 1.4; color: var(--ink-secondary); }
.rs-muted { color: var(--ink-secondary); }
.rs-ttl { color: var(--ink-primary); }
.rs-ttl:hover { color: var(--accent); }
.rs-sh { font-size: 30px; line-height: 1.1; font-weight: 700; letter-spacing: -.02em; color: var(--brand-bar); }
.rs-h2a { font-size: 30px; line-height: 1.15; font-weight: 700; letter-spacing: -.022em; color: var(--brand-bar); }

/* Pills: `.pill`, `.pill.p2`, `.pill.p3`, `.pill.new`. */
.rs-pills { display: flex; gap: 6px; flex-wrap: wrap; }
.rs-pill {
  display: inline-block; font-family: var(--font-mono); font-size: 10.5px; line-height: 1; letter-spacing: .1em;
  text-transform: uppercase; font-weight: 700; padding: 6px 10px; border-radius: 999px;
  background: var(--accent-fill); color: var(--accent);
}
.rs-pill--region { background: var(--ground); color: var(--ink-body); }
.rs-pill--platform { background: var(--page); color: var(--ink-body); box-shadow: inset 0 0 0 1px var(--rule); }
.rs-pill--new { background: var(--brand-bar); color: #fff; }

/* Buttons: `.btn`, `.btn.pri`, `.btn.sec`, `.btn.lil` in states-*.html. */
.rs-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: auto; min-height: 46px; padding: 13px 22px; border: 0; border-radius: var(--rs-radius-btn);
  font: inherit; font-size: 15px; font-weight: 700; line-height: 1.2; text-align: center;
  text-decoration: none; cursor: pointer;
}
.rs-btn--pri, .rs-btn--pri:hover { background: var(--accent); color: #fff; }
.rs-btn--pri:hover { background: var(--accent-hover); }
.rs-btn--sec { background: var(--page); color: var(--accent); box-shadow: inset 0 0 0 1.5px var(--accent); }
.rs-btn--sec:hover { background: var(--accent-fill); color: var(--accent); }
.rs-btn--lil { background: var(--brand-mark); color: var(--brand-bar); }
.rs-btn--white, .rs-btn--white:hover { background: #fff; color: var(--brand-bar); }

/* Tiles — copied as-is from the references' <style>. */
.tile { position: relative; overflow: hidden; background: var(--t-bg); display: block; }
.tile svg { position: absolute; left: 0; top: 0; width: 100%; height: 100%; display: block; }
.tile .u { display: none; }
.m-reg .u-reg, .m-cm .u-cm, .m-gtm .u-gtm, .m-gpc .u-gpc, .m-bp .u-bp { display: inline; }
.tone-indigo { --t-bg: #232C78; --t-fg: #6371D4; --t-hi: #C9CFFA; }
.tone-navy { --t-bg: #14213D; --t-fg: #4C5B8C; --t-hi: #A9B3F5; }
.tone-teal { --t-bg: #0E3F3B; --t-fg: #3F8A80; --t-hi: #9FE6D3; }
.tone-ember { --t-bg: #4A1F18; --t-fg: #A5503C; --t-hi: #FFC2A6; }
.tone-graphite { --t-bg: #2B2B28; --t-fg: #77766F; --t-hi: #E4E2D8; }
.k-bg { fill: var(--t-bg); } .k-fl { fill: var(--t-fg); } .k-hi { fill: var(--t-hi); }
.k-ln { fill: none; stroke: var(--t-fg); stroke-width: 1.6px; }
.k-hs { fill: none; stroke: var(--t-hi); stroke-width: 2.6px; }
.k-bs { fill: none; stroke: var(--t-bg); stroke-width: 2.6px; }
.k-ds { stroke-dasharray: 5 5; } .k-fo { fill-opacity: .6; } .k-faint { stroke-opacity: .3; }

/* Masthead — resources-home-reference.html, first <section>. */
.rs-mast-in {
  max-width: 1200px; margin: 0 auto; padding: 56px 24px 0;
  display: flex; flex-direction: column; align-items: center; text-align: center; gap: 32px;
}
.rs-mast-copy { max-width: 760px; }
.rs-h1 { font-size: 64px; line-height: 1.04; font-weight: 700; letter-spacing: -.03em; color: var(--brand-bar); margin: 14px 0 0; }
.rs-lede { font-size: 19px; line-height: 1.55; color: var(--ink-secondary); margin: 16px auto 0; max-width: 640px; }
.rs-search { width: 560px; max-width: 100%; }
.rs-search-box {
  display: flex; align-items: center; gap: 12px; height: 54px; padding: 0 12px 0 16px;
  border: 1px solid var(--ink-muted); border-radius: var(--rs-radius-search); background: var(--page);
}
.rs-search-box:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }
.rs-search-box input {
  flex: 1; min-width: 0; height: 100%; border: 0; outline: 0; background: transparent;
  font: inherit; font-size: 15px; color: var(--ink-primary);
}
.rs-search-box input::-webkit-search-cancel-button { display: none; }
.rs-search-clear {
  position: relative; flex: none; width: 28px; height: 28px; border-radius: 50%;
  background: var(--ground); display: flex; align-items: center; justify-content: center;
}
.rs-search-clear::after { content: ''; position: absolute; inset: -8px; }

/* This week's roundup — resources-home-reference.html, second <section>. */
.rs-roundup-in { padding-top: 64px; padding-bottom: 40px; }
.rs-roundup-head {
  display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between;
  gap: 16px 40px; padding-bottom: 28px;
}
.rs-roundup-headl { max-width: 780px; }
.rs-kicker { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.rs-roundup-title { font-size: 40px; line-height: 1.12; font-weight: 700; letter-spacing: -.026em; color: var(--brand-bar); margin-top: 14px; }
.rs-roundup-grid { display: flex; flex-wrap: wrap; gap: 48px 64px; align-items: flex-start; padding-top: 8px; }
.rs-lead { flex: 7 1 560px; min-width: 0; }
.rs-lead > .tile { aspect-ratio: 16 / 9; border-radius: var(--rs-radius-art); }
.rs-lead-body { margin-top: 28px; max-width: 700px; }
.rs-lead .rs-pills { gap: 8px; }
.rs-lead-h { font-size: 40px; line-height: 1.12; font-weight: 700; letter-spacing: -.026em; margin: 16px 0; }
.rs-lead-sum { font-size: 18px; line-height: 1.6; color: var(--ink-secondary); }
.rs-lead .rs-meta { margin-top: 18px; }
/* The reference gives every secondary story margin-bottom:36px, the last one
   too, so the column ends 36px below its last story. */
.rs-seconds { flex: 5 1 380px; min-width: 0; display: flex; flex-direction: column; gap: 36px; padding-bottom: 36px; }
.rs-second { display: flex; gap: 20px; }
.rs-second > .tile { flex: none; width: 150px; aspect-ratio: 3 / 2; border-radius: var(--rs-radius-tile-md); align-self: flex-start; }
.rs-second-body, .rs-row-body, .rs-result-body, .rs-card-body { min-width: 0; }
.rs-second-h { font-size: 20px; line-height: 1.25; font-weight: 700; letter-spacing: -.015em; margin: 11px 0 8px; }
.rs-second-sum { font-size: 14.5px; line-height: 1.5; color: var(--ink-secondary); }
.rs-second .rs-meta { margin-top: 9px; }

/* Archive — resources-home-reference.html <main>, and states-*.html. */
.rs-archive { margin-top: 64px; scroll-margin-top: 16px; }
/* states-*-desktop.html: no padding under the head (the home reference's 10px
   pairs with its inline "Filters combine.", which sits on its own line here). */
.rs-archive-head { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 8px; }
.rs-filters { margin-top: 20px; display: flex; flex-direction: column; gap: 14px; }
.rs-frow { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 8px 10px; }
.rs-frow .rs-lab { margin-right: 4px; }
.rs-fspacer { width: 28px; }
.rs-fsum { text-align: center; }
.rs-fsum a { font-weight: 600; }
/* Filter chip: `.fchip`, `.fchip.on` (selected = aria-pressed). */
.rs-chip {
  display: inline-flex; align-items: center; gap: 8px; height: auto; min-height: 38px; padding: 9px 14px;
  font: inherit; font-size: 13.5px; line-height: 1; color: var(--ink-body); text-decoration: none;
  background: var(--page); border: 1px solid var(--rule); border-radius: 999px; cursor: pointer;
}
.rs-chip:hover { background: var(--page); border-color: var(--ink-muted); color: var(--ink-body); }
.rs-chip i { font-style: normal; color: var(--ink-secondary); font-size: 12px; }
.rs-chip svg { flex: none; }
.rs-chip[aria-pressed="false"] svg { display: none; }
.rs-chip[aria-pressed="true"], .rs-chip[aria-pressed="true"]:hover { background: var(--brand-bar); border-color: var(--brand-bar); color: #fff; }
.rs-chip[aria-pressed="true"] i { color: var(--rs-on-navy-2); }
/* Removable chip: `.xchip`. */
.rs-xchip {
  display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 6px 6px 6px 14px;
  font-size: 13.5px; color: var(--brand-bar); background: var(--accent-fill); border-radius: 999px; text-decoration: none;
}
.rs-xchip b { width: 24px; height: 24px; border-radius: 50%; background: var(--page); display: inline-flex; align-items: center; justify-content: center; }
.rs-list { display: flex; flex-wrap: wrap; gap: 0 56px; margin-top: 20px; }
.rs-row { flex: 1 1 440px; min-width: 0; display: flex; gap: 18px; padding: 16px 0; align-items: flex-start; }
.rs-row > .tile { flex: none; width: 108px; aspect-ratio: 3 / 2; border-radius: var(--rs-radius-tile-sm); }
.rs-row-h { font-size: 18px; line-height: 1.3; font-weight: 700; letter-spacing: -.01em; margin: 9px 0 6px; }
.rs-results { max-width: 840px; margin: 24px auto 0; }
.rs-result { display: flex; gap: 22px; padding: 20px 0; align-items: flex-start; }
.rs-result > .tile { flex: none; width: 132px; aspect-ratio: 3 / 2; border-radius: var(--rs-radius-tile-sm); }
.rs-result-h { font-size: 21px; line-height: 1.28; font-weight: 700; letter-spacing: -.015em; margin: 10px 0 8px; }
.rs-result-sum { font-size: 15.5px; line-height: 1.55; color: var(--ink-secondary); }
.rs-result .rs-meta { margin-top: 9px; }
.rs-row, .rs-result { scroll-margin-top: 16px; }
.rs-more { display: flex; flex-direction: column; align-items: center; gap: 12px; margin-top: 36px; }
.rs-more-btn { padding: 13px 28px; }
/* No results — states-no-results-desktop.html. */
.rs-empty { display: flex; flex-direction: column; align-items: center; text-align: center; margin-top: 56px; }
.rs-empty-icon { width: 72px; height: 72px; border-radius: 50%; background: var(--accent-fill); display: flex; align-items: center; justify-content: center; }
.rs-empty h3 { font-size: 26px; line-height: 1.2; font-weight: 700; letter-spacing: -.02em; color: var(--brand-bar); margin-top: 24px; }
.rs-empty p { font-size: 16.5px; line-height: 1.6; color: var(--ink-secondary); margin-top: 10px; max-width: 520px; }
.rs-empty-actions { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; margin-top: 24px; }
.rs-removes-lab { margin-top: 36px; }
.rs-removes { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; margin-top: 14px; }

/* Mobile filter bar and sheet — mobile-home / mobile-filter-sheet / mobile-no-results.
   Hidden unless resources.js has put `js` on <html>: with no script the
   chips above stay inline and every control is a plain link or submit. */
.rs-fbar, .rs-xchips { display: none; }
.rs-fbtn {
  display: inline-flex; align-items: center; gap: 10px; height: 44px; padding: 0 16px;
  font: inherit; font-size: 15px; font-weight: 600; color: var(--brand-bar);
  background: var(--page); border: 1px solid var(--ink-muted); border-radius: 999px; cursor: pointer;
}
.rs-fbtn:hover { background: var(--page); }
.rs-fbadge {
  min-width: 20px; height: 20px; padding: 0 6px; border-radius: 10px; background: var(--brand-bar); color: #fff;
  font-size: 12px; font-weight: 700; display: inline-flex; align-items: center; justify-content: center;
}
.rs-sheet {
  position: fixed; inset: 84px 0 0 0; width: auto; height: auto; max-width: none; max-height: none;
  margin: 0; padding: 0; border: 0; border-radius: 20px 20px 0 0; background: var(--page); color: var(--ink-body);
}
.rs-sheet[open] { display: block; }
.rs-sheet::backdrop { background: rgba(20, 33, 61, .55); }
.rs-sheet-form { height: 100%; display: flex; flex-direction: column; }
.rs-sheet-grip { display: flex; justify-content: center; padding-top: 10px; }
.rs-sheet-grip span { width: 40px; height: 4px; border-radius: 2px; background: var(--rule); }
.rs-sheet-head { display: flex; align-items: center; justify-content: space-between; padding: 8px 8px 0 20px; }
.rs-sheet-head h2 { font-size: 22px; line-height: normal; font-weight: 700; letter-spacing: -.02em; color: var(--brand-bar); }
.rs-sheet-close { width: 48px; height: 48px; padding: 0; border: 0; background: transparent; display: flex; align-items: center; justify-content: center; }
.rs-sheet-close:hover { background: transparent; }
.rs-sheet-body { flex: 1; overflow: auto; padding: 0 20px; }
.rs-sheet-body > .rs-meta { font-size: 13.5px; }
.rs-sheet-group { margin-top: 22px; }
.rs-sheet-group h3 { font-size: 15px; line-height: normal; font-weight: 700; color: var(--brand-bar); margin-bottom: 12px; }
.rs-sheet-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.rs-sheet-foot { display: flex; align-items: center; gap: 16px; padding: 14px 20px 24px; }
.rs-sheet-clear {
  height: auto; min-height: 46px; padding: 0 4px; border: 0; background: none;
  font: inherit; font-size: 15px; font-weight: 700; color: var(--accent);
}
.rs-sheet-clear:hover { background: none; }
/* Block, not flex: as a flex container the button splits "Show ", the count
   and " articles" into items and trims the spaces ("Show4articles"). */
.rs-sheet-foot .rs-btn { flex: 1; display: block; }

/* Conversion strip and newsletter band — the last two sections of the home <main>. */
.rs-strip {
  margin-top: 64px; padding: 22px 28px; border-radius: var(--rs-radius-strip); background: var(--accent-fill);
  display: flex; flex-wrap: wrap; gap: 16px 32px; align-items: center; justify-content: space-between;
}
.rs-strip-copy { min-width: 0; flex: 1 1 380px; }
.rs-strip h2 { font-size: 21px; line-height: 1.25; font-weight: 700; letter-spacing: -.015em; color: var(--brand-bar); }
.rs-strip p { font-size: 14.5px; line-height: 1.5; color: var(--ink-body); margin-top: 4px; }
.rs-strip .rs-btn { font-size: 14.5px; padding: 12px 20px; min-height: 44px; }
.rs-news {
  margin-top: 24px; padding: 36px 40px; border-radius: var(--rs-radius-band); background: var(--brand-bar);
  display: flex; flex-wrap: wrap; gap: 24px 56px; align-items: center; justify-content: space-between;
}
.rs-news-copy { flex: 1 1 380px; min-width: 0; }
.rs-news h2 { font-size: 28px; line-height: 1.15; font-weight: 700; letter-spacing: -.02em; color: #fff; margin: 10px 0 8px; }
.rs-news-copy p { font-size: 15px; line-height: 1.55; color: var(--rs-on-navy); }
.rs-news-form { flex: 1 1 380px; max-width: 520px; min-width: 0; }
.rs-news-form fieldset { margin: 0; padding: 0; border: 0; min-width: 0; }
.rs-news-row { display: flex; flex-wrap: wrap; gap: 10px; }
.rs-news-field { flex: 1 1 240px; }
.rs-news-field input {
  width: 100%; height: 50px; padding: 0 16px; border: 0; border-radius: var(--rs-radius-btn);
  display: block; font: inherit; font-size: 16px; color: var(--ink-primary); background: #fff;
}
.rs-news-row .rs-btn { height: 50px; min-height: 50px; padding: 0 24px; font-size: 16px; }
.rs-news-form :disabled { cursor: not-allowed; }
.rs-news-note { font-size: 13px; line-height: 1.45; color: var(--rs-on-navy-2); margin-top: 10px; }

/* Footer: the landing page's two strings on a #F2F1ED band (HANDOFF.md § Page structure 7). */
.rs .lp-bottom {
  margin-top: 72px; padding: 26px 48px; border-top: 0; background: var(--ground);
  font-size: 13px; line-height: normal; gap: 12px; color: var(--ink-secondary);
}

/* Article — article-desktop-reference.html. */
.rs-back { padding-top: 28px; line-height: normal; }
.rs-back a { font-size: 14px; font-weight: 600; }
.rs-ahead { max-width: 900px; margin: 0 auto; padding: 36px 24px 0; text-align: center; }
.rs-ahead .rs-pills { justify-content: center; gap: 8px; }
.rs-ah1 { font-size: 52px; line-height: 1.1; font-weight: 700; letter-spacing: -.03em; color: var(--brand-bar); margin: 22px 0; }
.rs-ameta { display: flex; flex-wrap: wrap; gap: 6px 18px; justify-content: center; font-size: 15.5px; line-height: 1.5; color: var(--ink-body); }
.rs-ameta a { font-weight: 700; }
.rs-jumpbtn { display: none; }
.rs-art-wrap { padding-top: 44px; }
.rs-art { max-width: 1040px; margin: 0 auto; aspect-ratio: 16 / 7; border-radius: var(--rs-radius-art); }
.rs-acols { padding-top: 64px; display: flex; flex-wrap: wrap; justify-content: center; gap: 56px 96px; align-items: flex-start; }
.rs-abody { flex: 0 1 720px; min-width: 0; }
.rs-abody > section + section { margin-top: 56px; }
.rs-abody > section { scroll-margin-top: 16px; }
.rs-alede { font-size: 21px; line-height: 1.6; color: var(--ink-primary); margin-top: 16px; }
.rs-bullets { display: flex; flex-direction: column; gap: 16px; margin-top: 20px; }
.rs-bul { display: flex; gap: 16px; align-items: flex-start; font-size: 18px; line-height: 1.6; color: var(--ink-body); }
.rs-bul i { flex: none; width: 8px; height: 8px; border-radius: 2px; background: var(--accent); margin-top: 11px; }
.rs-paras { display: flex; flex-direction: column; gap: 22px; margin-top: 20px; font-size: 18px; line-height: 1.7; color: var(--ink-body); }
.rs-code {
  font-family: var(--font-mono); font-size: .86em; background: var(--ground); color: var(--ink-primary);
  padding: 2px 6px; border-radius: 4px; white-space: nowrap;
}
.rs-code:empty { display: none; }
.rs-card2 .rs-code { background: #fff; }
.rs-check { background: var(--accent-fill); border-radius: var(--rs-radius-band); padding: 36px 36px 32px; }
.rs-check > .rs-lab { color: var(--accent-hover); }
.rs-check > .rs-h2a { margin-top: 10px; }
.rs-steps { list-style: none; margin: 24px 0 0; padding: 0; display: flex; flex-direction: column; gap: 20px; }
.rs-steps li { display: flex; gap: 18px; align-items: flex-start; }
.rs-step-n {
  flex: none; width: 30px; height: 30px; margin-top: 1px; border-radius: 50%; background: var(--accent); color: #fff;
  font-weight: 700; font-size: 14px; display: flex; align-items: center; justify-content: center;
}
.rs-steps p { font-size: 17.5px; line-height: 1.6; color: var(--ink-primary); }
.rs-abody > .rs-astrip { margin-top: 20px; }
.rs-astrip {
  padding: 28px 32px; border-radius: var(--rs-radius-band); background: var(--brand-bar);
  display: flex; flex-wrap: wrap; gap: 16px 28px; align-items: center; justify-content: space-between;
}
.rs-astrip > div { flex: 1 1 320px; min-width: 0; }
.rs-astrip h2 { font-size: 22px; line-height: 1.25; font-weight: 700; letter-spacing: -.015em; color: #fff; }
.rs-astrip p { font-size: 15px; line-height: 1.5; color: var(--rs-on-navy); margin-top: 6px; }
.rs-astrip .rs-btn { min-height: 44px; padding: 13px 20px; }
.rs-rail { flex: 0 0 300px; min-width: 0; position: sticky; top: 24px; display: flex; flex-direction: column; gap: 32px; }
.rs-source { background: var(--ground); border-radius: var(--rs-radius-art); padding: 24px; }
.rs-source-name { font-size: 19px; line-height: 1.3; font-weight: 700; color: var(--ink-primary); margin-top: 12px; }
.rs-source-full { font-size: 14px; line-height: 1.5; color: var(--ink-secondary); margin-top: 2px; }
.rs-source-date { font-size: 14px; line-height: 1.5; color: var(--ink-body); margin-top: 12px; }
.rs-source .rs-btn { display: flex; width: 100%; min-height: 44px; margin-top: 18px; padding: 13px 16px; }
.rs-source-note { font-size: 12.5px; line-height: 1.5; color: var(--ink-secondary); margin-top: 12px; }
.rs-toc > .rs-lab { margin-bottom: 8px; }
.rs-jump { display: flex; gap: 12px; align-items: baseline; padding: 7px 0; font-size: 15px; line-height: 1.4; color: var(--ink-body); }
.rs-jump:hover { color: var(--accent); }
.rs-jump span { width: 16px; font-family: var(--font-mono); font-size: 11px; color: var(--ink-secondary); }
.rs-related { margin-top: 104px; }
.rs-related > .rs-sh { text-align: center; }
.rs-cards { display: flex; flex-wrap: wrap; gap: 40px; margin-top: 36px; }
.rs-card { flex: 1 1 300px; min-width: 0; }
.rs-card > .tile { aspect-ratio: 16 / 9; border-radius: var(--rs-radius-tile-lg); }
.rs-card .rs-pills { margin-top: 18px; }
.rs-card-h { font-size: 20px; line-height: 1.28; font-weight: 700; letter-spacing: -.015em; margin: 12px 0 8px; }
.rs-article-page .rs-news { margin-top: 96px; }
.rs-status h1 { margin: 0; }
.rs-status { padding-top: 72px; padding-bottom: 24px; max-width: 720px; }
.rs-status p { font-size: 17px; line-height: 1.6; color: var(--ink-body); margin-top: 16px; }

/* Phone — mobile-*-reference.html (390px). Tablet widths keep the desktop
   rules: every two-column block above is a flex-wrap and stacks by itself. */
@media (max-width: 759px) {
  .rs-wrap { padding: 0 16px; }
  .rs-mast-in { padding: 36px 16px 0; gap: 22px; }
  .rs-h1 { font-size: 40px; line-height: 1.05; margin: 12px 0 0; }
  .rs-lede { font-size: 16px; margin-top: 12px; }
  .rs-search { width: 100%; }
  .rs-search-box { height: 48px; gap: 10px; padding: 0 10px 0 14px; }
  .rs-search-box input { font-size: 16px; }

  .rs-roundup-in { padding-top: 44px; padding-bottom: 0; }
  .rs-roundup-head { display: block; padding-bottom: 0; }
  .rs-roundup-head > .rs-meta { display: block; }
  .rs-kicker { gap: 10px; }
  .rs-roundup-title { font-size: 28px; line-height: 1.15; letter-spacing: -.025em; margin: 12px 0 6px; }
  .rs-roundup-grid { display: block; padding-top: 24px; }
  .rs-lead > .tile { aspect-ratio: 16 / 10; border-radius: var(--rs-radius-tile-lg); }
  .rs-lead-body { margin-top: 20px; }
  .rs-lead .rs-pills { gap: 6px; }
  .rs-lead-h { font-size: 27px; line-height: 1.15; letter-spacing: -.025em; margin: 12px 0; }
  .rs-lead-sum { font-size: 16px; }
  .rs-lead .rs-meta { margin-top: 14px; }
  .rs-seconds { gap: 24px; margin-top: 32px; padding-bottom: 0; }
  .rs-second { gap: 14px; }
  .rs-second > .tile { width: 104px; border-radius: var(--rs-radius-tile-sm); }
  .rs-second-h, .rs-row-h, .rs-result-h, .rs-card-h { font-size: 17px; line-height: 1.3; letter-spacing: -.01em; margin: 8px 0 5px; }
  .rs-second-sum { display: none; }
  .rs-second .rs-meta, .rs-row .rs-meta, .rs-result .rs-meta, .rs-card .rs-meta { font-size: 12.5px; margin-top: 0; }

  .rs-archive { margin-top: 56px; }
  .rs-archive-head { gap: 6px; padding-bottom: 0; }
  .rs-sh { font-size: 26px; }
  .rs-chip { min-height: 44px; }
  .js .rs-fbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 20px; }
  .js .rs-xchips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
  /* With script the chips live in the sheet and this form is empty: drop its
     margin too, or it adds 20px between the Filter bar and the list. */
  .js .rs-filters { margin-top: 0; }
  .js .rs-filters .rs-frow { display: none; }
  .js .rs-filters .rs-fsum { display: none; }
  .rs-list { display: flex; flex-direction: column; gap: 20px; margin-top: 20px; }
  .rs-row { flex: none; gap: 14px; padding: 0; }
  .rs-row > .tile, .rs-result > .tile { width: 88px; }
  .rs-results { margin-top: 20px; display: flex; flex-direction: column; gap: 20px; }
  .rs-result { gap: 14px; padding: 0; }
  .rs-result-sum { font-size: 16px; }
  .rs-more { align-items: stretch; gap: 10px; margin-top: 28px; }
  .rs-more .rs-meta { text-align: center; }
  .rs-empty { margin-top: 44px; }
  .rs-empty h3 { font-size: 22px; margin-top: 20px; }
  .rs-empty p { font-size: 16px; margin-top: 8px; }
  .rs-empty-actions { width: 100%; margin-top: 22px; }
  .rs-empty-actions .rs-btn { width: 100%; }
  .rs-removes-lab { margin-top: 28px; }
  .rs-removes { flex-direction: column; gap: 8px; width: 100%; margin-top: 12px; }
  .rs-removes .rs-chip { justify-content: space-between; width: 100%; }

  .rs-strip { display: block; margin-top: 48px; padding: 20px; }
  .rs-strip h2 { font-size: 19px; }
  .rs-strip p { font-size: 16px; margin-top: 6px; }
  .rs-strip .rs-btn { display: flex; width: 100%; margin-top: 16px; min-height: 46px; padding: 13px 22px; font-size: 15px; }
  .rs-news { display: block; margin-top: 16px; padding: 28px 20px; }
  .rs-news h2 { font-size: 24px; line-height: 1.2; }
  .rs-news-copy p { font-size: 16px; }
  .rs-news-form { margin-top: 18px; }
  .rs-news-row { display: block; }
  .rs-news-field { display: block; }
  .rs-news-row .rs-btn { display: flex; width: 100%; margin-top: 10px; }
  .rs .lp-bottom { flex-direction: column; gap: 8px; margin-top: 48px; padding: 24px 16px; line-height: 1.55; }

  /* The link is a 44px tap target; the negative margin keeps the header where
     the reference's 17px-tall link puts it (20px padding + text). */
  .rs-back { padding-top: 8px; }
  .rs-back a { display: inline-flex; align-items: center; min-height: 44px; padding-right: 16px; margin-bottom: -14px; }
  .rs-ahead { padding: 24px 16px 0; text-align: left; }
  .rs-ahead .rs-pills { justify-content: flex-start; gap: 6px; }
  .rs-ah1 { font-size: 31px; line-height: 1.13; letter-spacing: -.028em; margin: 16px 0; }
  .rs-ameta { display: block; font-size: 16px; line-height: 1.55; }
  .rs-ameta > span { display: block; }
  .rs-jumpbtn { display: inline-flex; margin-top: 18px; padding: 11px 16px; min-height: 44px; }
  .rs-art-wrap { padding-top: 24px; }
  .rs-art { aspect-ratio: 16 / 10; border-radius: var(--rs-radius-tile-lg); }
  .rs-acols { display: block; padding-top: 40px; }
  .rs-abody > section + section { margin-top: 40px; }
  .rs-h2a { font-size: 25px; line-height: 1.18; }
  .rs-alede { font-size: 19px; margin-top: 12px; }
  .rs-bullets { gap: 14px; margin-top: 16px; }
  .rs-bul { gap: 14px; font-size: 17px; }
  .rs-bul i { margin-top: 10px; }
  .rs-paras { gap: 18px; margin-top: 16px; font-size: 17px; }
  .rs-check { margin-left: -4px; margin-right: -4px; border-radius: var(--rs-radius-art); padding: 26px 20px 24px; }
  .rs-check > .rs-h2a { margin-top: 8px; }
  .rs-steps { gap: 18px; margin-top: 20px; }
  .rs-steps li { gap: 14px; }
  .rs-step-n { width: 28px; height: 28px; font-size: 13px; }
  .rs-steps p { font-size: 16.5px; }
  .rs-abody > .rs-astrip { margin-top: 16px; }
  .rs-astrip { display: block; padding: 22px 20px; border-radius: var(--rs-radius-art); }
  .rs-astrip h2 { font-size: 20px; }
  .rs-astrip p { font-size: 16px; }
  .rs-astrip .rs-btn { display: flex; width: 100%; margin-top: 16px; }
  .rs-rail { position: static; margin-top: 32px; }
  .rs-source { padding: 22px 20px; }
  .rs-source-full, .rs-source-date { font-size: 16px; }
  .rs-source-name, .rs-source-date { margin-top: 10px; }
  .rs-source .rs-btn { margin-top: 16px; }
  .rs-toc { display: none; }
  .rs-related { margin-top: 48px; }
  .rs-related > .rs-sh { text-align: left; font-size: 25px; line-height: 1.2; letter-spacing: -.022em; }
  .rs-cards { flex-direction: column; gap: 22px; margin-top: 20px; }
  .rs-card { flex: none; display: flex; gap: 14px; align-items: flex-start; }
  .rs-card > .tile { flex: none; width: 104px; aspect-ratio: 3 / 2; border-radius: var(--rs-radius-tile-sm); }
  .rs-card .rs-pills { margin-top: 0; }
  .rs-article-page .rs-news { margin-top: 48px; }
}
