* { box-sizing: border-box; margin: 0; padding: 0; }

/* ── AmICredible ─────────────────────────────────────────────────────────────
   The product's visual language, applied to this page:

     * A warm ivory ground with white cards, not a cool grey app chrome.
     * Deep navy as the brand colour — text, buttons, and the quote block.
     * Serif for anything the reader reads (the claim, the quote, the analysis
       prose); sans for everything that is interface (labels, pills, buttons,
       form fields). That split is the most recognisable thing about the
       product and it is the one to get right.
     * Uppercase, letterspaced micro-labels above every section.
     * Generous corner radii, hairline warm borders.
     * A score ring rather than a bar.

   Both themes ship. Light is the default; dark follows the system unless the
   reader has picked one explicitly, in which case .theme-light / .theme-dark on
   <html> wins (see the theme block in app.js).

   FONTS ARE SYSTEM-ONLY. The app has no build step, no dependencies and makes
   no network requests other than to its own proxy, and a webfont would add all
   three. The serif stack below is chosen to land close to the product's face on
   macOS (Charter) and to degrade sanely elsewhere. */

:root {
  color-scheme: light;

  --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-serif: Charter, "Bitstream Charter", "Sitka Text", "Iowan Old Style", Cambria, Georgia, serif;
  /* Kept as an alias: existing rules refer to --font. */
  --font: var(--font-sans);

  --bg: #EDEAE2;
  /* Recessed areas inside a card: the form body, criteria cards, source cards. */
  --bg-sunken: #EAE6DB;
  --card: #FFFFFF;
  /* The field you type into is the lightest surface on the page — the product
     inverts the usual arrangement, where inputs are darker than their card. */
  --input: #FDFCF9;
  --border: #E1DBCE;
  --border-strong: #D3CAB7;

  --ink: #15263D;
  --ink-soft: #445671;
  --muted: #7F8899;

  --navy: var(--ink);
  --navy-light: var(--ink-soft);
  --text: var(--ink);

  --quote-bg: #1E3A5E;
  --quote-ink: #F2F0E8;
  --gold: #C6A867;

  --ring-track: #E6DFCF;

  /* Verdict tones. Colour is always driven by the verdict label, never by the
     numeric score — see the VERDICT_TONE table in app.js. 'neutral' carries
     unverified and characterization: a claim checked and not corroborated, or a
     contested value judgment. Neither is a failure, so neither is ever red. */
  --tone-good-bg: #E7F2E9;   --tone-good-fg: #1F6B3A;   --tone-good-solid: #2E7D4F;
  --tone-severe-bg: #FAEAE5; --tone-severe-fg: #A83C28; --tone-severe-solid: #C0492F;
  --tone-neutral-bg: #ECEEF3; --tone-neutral-fg: #3E5170; --tone-neutral-solid: #48628A;
  --tone-info-bg: #F1EFE8;   --tone-info-fg: #77796F;   --tone-info-solid: #98988C;
  --tone-error-bg: #FAEAE5;  --tone-error-fg: #A83C28;  --tone-error-solid: #C0492F;

  --amber-bg: #FAF2E1;
  --amber-fg: #8A5A00;
  --amber-border: #E7D3A6;

  --link: #1F5C8F;
  --mark-bg: #15263D;
  --shadow: 0 1px 2px rgba(21, 38, 61, 0.04), 0 8px 24px rgba(21, 38, 61, 0.05);
}

/* System dark, unless the reader explicitly chose light. */
@media (prefers-color-scheme: dark) {
  :root:not(.theme-light) {
    color-scheme: dark;

    --bg: #0D1A2B;
    --bg-sunken: #192C45;
    --card: #142338;
    --input: #101E31;
    --border: #25384F;
    --border-strong: #31465F;

    --ink: #E9EDF3;
    --ink-soft: #B7C3D3;
    --muted: #8496AC;

    --quote-bg: #1D3B60;
    --quote-ink: #EFF3F9;

    --ring-track: #22354C;

    --tone-good-bg: #16321F;   --tone-good-fg: #7ED4A2;   --tone-good-solid: #48B47D;
    --tone-severe-bg: #3A201B; --tone-severe-fg: #F19980; --tone-severe-solid: #E0755C;
    --tone-neutral-bg: #1E3048; --tone-neutral-fg: #AEC1DA; --tone-neutral-solid: #7EA0C8;
    --tone-info-bg: #1B2739;   --tone-info-fg: #98A6BA;   --tone-info-solid: #8492A6;
    --tone-error-bg: #3A201B;  --tone-error-fg: #F19980;  --tone-error-solid: #E0755C;

    --amber-bg: #32291A;
    --amber-fg: #E5BF7C;
    --amber-border: #4B3C23;

    --link: #7FB6E8;
    --mark-bg: #263B54;
    --shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 8px 24px rgba(0, 0, 0, 0.28);
  }
}

/* An explicit choice wins over the system in both directions. */
:root.theme-dark {
  color-scheme: dark;

  --bg: #0D1A2B;
  --bg-sunken: #192C45;
  --card: #142338;
  --input: #101E31;
  --border: #25384F;
  --border-strong: #31465F;

  --ink: #E9EDF3;
  --ink-soft: #B7C3D3;
  --muted: #8496AC;

  --quote-bg: #1D3B60;
  --quote-ink: #EFF3F9;

  --ring-track: #22354C;

  --tone-good-bg: #16321F;   --tone-good-fg: #7ED4A2;   --tone-good-solid: #48B47D;
  --tone-severe-bg: #3A201B; --tone-severe-fg: #F19980; --tone-severe-solid: #E0755C;
  --tone-neutral-bg: #1E3048; --tone-neutral-fg: #AEC1DA; --tone-neutral-solid: #7EA0C8;
  --tone-info-bg: #1B2739;   --tone-info-fg: #98A6BA;   --tone-info-solid: #8492A6;
  --tone-error-bg: #3A201B;  --tone-error-fg: #F19980;  --tone-error-solid: #E0755C;

  --amber-bg: #32291A;
  --amber-fg: #E5BF7C;
  --amber-border: #4B3C23;

  --link: #7FB6E8;
  --mark-bg: #263B54;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 8px 24px rgba(0, 0, 0, 0.28);
}

body {
  font-family: var(--font-sans);
  color: var(--ink);
  background: var(--bg);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

.hidden { display: none !important; }

/* ── Page shell ──────────────────────────────────────────────────────────────
   Uses the width the browser gives it rather than a fixed narrow band, with two
   limits that keep it readable at any size:

     * the shell caps at 1520px, because past that the gutters grow but nothing
       gains — a laptop runs effectively edge to edge, an ultrawide does not
       stretch to a horizon;
     * every block of prose carries its own measure cap (see the max-width rules
       through this file), so widening the page widens the LAYOUT — more columns,
       more side-by-side — and never the line length.

   The gutter scales with the viewport, so the same rules serve a phone and a
   6K display without a stack of breakpoints. */
.page {
  --gutter: clamp(16px, 3.5vw, 56px);
  max-width: 1520px;
  margin: 0 auto;
  padding: clamp(28px, 4vw, 52px) var(--gutter) 96px;
  display: flex;
  flex-direction: column;
  gap: clamp(16px, 1.6vw, 24px);
}

/* ── Brand lockup ── */
.page-header { display: flex; flex-direction: column; gap: 14px; margin-bottom: 4px; }
.brand-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.brand { display: flex; align-items: center; gap: 12px; }
.brand-mark {
  width: 38px; height: 38px; border-radius: 11px; flex: none;
  background: var(--mark-bg); display: grid; place-items: center;
}
.brand-mark::after {
  content: ""; width: 9px; height: 9px; border-radius: 50%; background: var(--gold);
}
.brand-name {
  font-family: var(--font-serif); font-size: 21px; font-weight: 700;
  letter-spacing: -0.01em; color: var(--ink); line-height: 1.1;
}
.brand-tagline {
  font-size: 10px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.14em; color: var(--muted); margin-top: 3px;
}
.theme-toggle {
  width: 36px; height: 36px; border-radius: 50%; flex: none;
  background: var(--card); border: 1px solid var(--border); color: var(--ink-soft);
  font-size: 15px; line-height: 1; display: grid; place-items: center;
  transition: border-color 0.15s, color 0.15s;
}
.theme-toggle:hover { border-color: var(--border-strong); color: var(--ink); }

.page-title-block { display: flex; flex-direction: column; gap: 6px; margin-top: 10px; }
.page-title {
  font-family: var(--font-serif); font-size: 42px; font-weight: 600;
  letter-spacing: -0.025em; line-height: 1.1; color: var(--ink);
}
.page-subtitle {
  color: var(--ink-soft); font-size: 14.5px; max-width: 52em; line-height: 1.65;
  margin-top: 4px;
}

/* ── Data entry ── */
/* The product's assess-a-claim card: a navy header bar naming the task, a
   recessed cream body, and near-white fields. The inversion matters — the
   lightest surface on the page is the one you are meant to type into. */
.analyze-form {
  background: var(--card); border: 1px solid var(--border); border-radius: 14px;
  overflow: hidden; box-shadow: var(--shadow);
}
.form-head {
  background: var(--quote-bg); color: var(--quote-ink);
  padding: 16px 22px; display: flex; align-items: center; gap: 14px;
}
.form-head-icon {
  width: 36px; height: 36px; border-radius: 10px; flex: none;
  background: rgba(255, 255, 255, 0.12); display: grid; place-items: center;
}
.form-head-icon svg { width: 18px; height: 18px; display: block; }
.form-head-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.form-head-title { font-size: 15px; font-weight: 700; letter-spacing: 0.01em; }
.form-head-sub { font-size: 12.5px; color: rgba(255, 255, 255, 0.62); line-height: 1.45; }
.form-head-note {
  flex: none; display: flex; align-items: center; gap: 6px;
  font-size: 11.5px; color: rgba(255, 255, 255, 0.62);
}
.form-head-note svg { width: 13px; height: 13px; display: block; }

.form-body {
  background: var(--bg-sunken); padding: 22px;
  display: flex; flex-direction: column; gap: 18px;
}
.field { display: flex; flex-direction: column; gap: 7px; }
.field label {
  font-size: 10.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.1em; color: var(--muted);
}
.field label .optional { font-weight: 600; text-transform: none; letter-spacing: 0.01em; color: var(--muted); }
.field input, .field textarea {
  font-family: var(--font-serif); font-size: 15px;
  padding: 14px 16px; border: 1px solid var(--border-strong); border-radius: 10px;
  color: var(--ink); background: var(--input);
  transition: border-color 0.15s, box-shadow 0.15s;
}
.field textarea { resize: vertical; min-height: 180px; line-height: 1.6; }
.field input:focus, .field textarea:focus {
  outline: none; border-color: var(--quote-bg);
  box-shadow: 0 0 0 3px rgba(30, 58, 94, 0.1);
}
.field input::placeholder, .field textarea::placeholder { color: var(--muted); }

/* A file picker cannot be styled the way the other fields are — the button
   inside it belongs to the browser. So it is given the field's ground and the
   button is dressed to match the page's secondary action, which is the most
   that can be done without replacing the control and losing its keyboard
   behaviour with it. */
.field input[type="file"] {
  font-family: var(--font-sans); font-size: 13px; padding: 11px 12px;
  cursor: pointer;
}
.field input[type="file"]::file-selector-button {
  font: inherit; font-weight: 700; cursor: pointer;
  margin-right: 12px; padding: 8px 14px; border-radius: 8px;
  border: 1px solid var(--border-strong); background: var(--card); color: var(--ink);
}
.field input[type="file"]::file-selector-button:hover { border-color: var(--ink-soft); }

.char-counter { align-self: flex-end; font-size: 11.5px; color: var(--muted); }
.char-counter.warning { color: var(--amber-fg); font-weight: 700; }
.char-counter.over { color: var(--tone-severe-fg); font-weight: 700; }

/* Loading a .txt file: a second way to fill the textarea, so it sits under it
   as a subordinate row rather than as a field of its own — it is not a fourth
   place the article can come from, and giving it the weight of one would say
   it was. The picker itself inherits the file-input dressing above, since it
   is inside .field like the PDF one. */
.txt-load { display: flex; flex-direction: column; gap: 7px; padding-top: 4px; }
.txt-load > label { font-size: 10px; }
/* Empty until something is loaded, and it collapses when it is empty — an
   always-present blank line under the box would read as a missing value. */
.txt-status:empty { display: none; }
.txt-status { font-size: 11.5px; color: var(--muted); line-height: 1.5; }
.txt-status.over { color: var(--tone-severe-fg); font-weight: 700; }

/* ── Where the article comes from ── */
/* A row of options rather than a dropdown: there are three, one of them is
   unavailable and has to say so, and a disabled item in a select is invisible
   until it is opened. */
.field-label {
  font-size: 10.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.1em; color: var(--muted);
}
.source-choice { display: flex; flex-wrap: wrap; gap: 8px; }
.source-option {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 10px 14px; border: 1px solid var(--border-strong); border-radius: 10px;
  background: var(--input); cursor: pointer;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.source-option:hover:not(.is-disabled) { border-color: var(--ink-soft); }
.source-option:has(input:checked) {
  border-color: var(--quote-bg); box-shadow: 0 0 0 3px rgba(30, 58, 94, 0.1);
}
.source-option input { accent-color: var(--quote-bg); margin: 0; }
.source-option-name { font-size: 13px; font-weight: 700; color: var(--ink); }
/* Named, present and not yet available. Hiding it would leave a reader with a
   PDF wondering whether they had missed the control; this tells them the
   answer without accepting a file the server would refuse. */
.source-option.is-disabled { cursor: not-allowed; background: var(--bg-sunken); border-style: dashed; }
.source-option.is-disabled .source-option-name { color: var(--muted); }
.source-option-note { font-size: 11px; font-weight: 600; color: var(--muted); }

.field-hint { font-size: 12px; color: var(--muted); line-height: 1.55; max-width: 60ch; }

/* ── What to check ── */
/* Stacked rather than side by side like the intake selector, because these two
   are not interchangeable the way "paste" and "from URL" are: one is the
   default and one costs materially more, and the sentence under each is the
   part that decides it. A row of chips would set the helper text at a size
   nobody reads, which is how a user ends up in the expensive mode by accident. */
.mode-choice { display: flex; flex-direction: column; gap: 8px; }
.mode-option {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 12px 14px; border: 1px solid var(--border-strong); border-radius: 10px;
  background: var(--input); cursor: pointer;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.mode-option:hover { border-color: var(--ink-soft); }
.mode-option:has(input:checked) {
  border-color: var(--quote-bg); box-shadow: 0 0 0 3px rgba(30, 58, 94, 0.1);
}
.mode-option input { accent-color: var(--quote-bg); margin: 2px 0 0; flex: none; }
.mode-option-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.mode-option-name { font-size: 13px; font-weight: 700; color: var(--ink); }
.mode-option-note { font-size: 12px; color: var(--muted); line-height: 1.5; }


.form-footer {
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  border-top: 1px solid var(--border); padding-top: 18px; flex-wrap: wrap;
}
.form-footer-note { font-size: 12.5px; color: var(--muted); line-height: 1.55; max-width: 34em; }
/* The two actions travel together at the end of the row rather than being
   spread by the footer's space-between, which would leave Clear stranded in
   the middle of it. */
.form-footer-actions { display: flex; align-items: center; justify-content: space-between; gap: 18px; }

button { font: inherit; cursor: pointer; }

.btn-primary {
  flex: none;
  background: var(--quote-bg); color: var(--quote-ink); border: 1px solid var(--quote-bg);
  border-radius: 10px; padding: 12px 22px; font-size: 13px; font-weight: 700;
  letter-spacing: 0.02em; display: inline-flex; align-items: center; gap: 8px;
  transition: opacity 0.15s;
}
.btn-primary:hover:not(:disabled) { opacity: 0.9; }
/* Muted rather than faded: the product's disabled action is a flat slate, which
   reads as "not yet" instead of as a rendering glitch. */
.btn-primary:disabled {
  background: var(--muted); border-color: var(--muted); color: var(--card);
  cursor: not-allowed; opacity: 1;
}

.btn-secondary {
  background: var(--card); color: var(--ink); border: 1px solid var(--border-strong);
  border-radius: 8px; padding: 8px 14px; font-size: 12.5px; font-weight: 700;
  transition: border-color 0.15s;
}
.btn-secondary:hover { border-color: var(--ink-soft); }

.btn-text {
  background: none; border: none; color: var(--muted); font-size: 12px; font-weight: 700;
  text-decoration: underline; padding: 0;
}
.btn-text:hover { color: var(--ink); }

/* ── On to the next article ── */
/* The foot of the findings, and deliberately not a card: a bordered box the
   same weight as the cards above it would read as one more section of the
   report rather than as the way out of it. */
.next-article {
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  flex-wrap: wrap; padding: 2px 2px 8px;
}
.next-article-note { font-size: 13px; color: var(--muted); font-weight: 700; }

/* ── Loading ── */
.loading {
  background: var(--card); border: 1px solid var(--border); border-radius: 14px;
  padding: 18px 22px; display: flex; flex-direction: column; gap: 12px; align-items: flex-start;
  box-shadow: var(--shadow);
}
.loading-text { font-size: 14.5px; color: var(--ink-soft); font-family: var(--font-serif); }
.loading-track { width: 100%; height: 3px; background: var(--bg-sunken); border-radius: 999px; overflow: hidden; }
.loading-fill {
  height: 100%; width: 40%; background: var(--gold); border-radius: 999px;
  animation: indeterminate 1.1s ease-in-out infinite;
}
@keyframes indeterminate {
  0%   { margin-left: -40%; }
  100% { margin-left: 100%; }
}
/* Cautionary, not severe: the analysis is still running and may still land.
   Styling this like the error banner would say the run had failed. */
.loading-trouble {
  font-size: 13px; line-height: 1.5; color: var(--ink-soft);
  background: var(--bg-sunken); border: 1px solid var(--border);
  border-radius: 8px; padding: 9px 12px; width: 100%;
}

/* ── Errors ── */
.error-box {
  font-size: 14px; color: var(--tone-severe-fg); background: var(--tone-severe-bg);
  border: 1px solid var(--tone-severe-fg); border-radius: 10px;
  padding: 13px 16px; line-height: 1.55;
}

/* ── Abstention (no central claim) ── */
/* A successful outcome, not a failure — styled as a neutral card, never as
   the error banner above. */
.abstention-card {
  background: var(--card); border: 1px solid var(--border); border-radius: 14px;
  padding: 20px 22px; display: flex; flex-direction: column; gap: 8px;
  box-shadow: var(--shadow);
}
.abstention-label {
  font-size: 10.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.1em; color: var(--muted);
}
.abstention-note { font-size: 15px; color: var(--ink-soft); line-height: 1.65; font-family: var(--font-serif); max-width: 72ch; }

/* The evidence for the decision, not the decision. Quiet, in a row, and set
   apart from the sentence above it — a reader who wants to know how close it
   came can find it, and one who does not is not made to read a threshold. */
.abstention-numbers { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.abstention-number {
  display: inline-flex; align-items: baseline; gap: 7px;
  padding: 5px 11px; border-radius: 999px;
  background: var(--bg-sunken); border: 1px solid var(--border);
}
.abstention-number-label {
  font-size: 10.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.06em; color: var(--muted);
}
.abstention-number-value { font-family: var(--font-serif); font-size: 14px; color: var(--ink); }

/* THE NEXT STEP, AND IT IS THE POINT OF THE CARD. An abstention with no way
   forward reads as a failure however carefully it is worded. Divided off so it
   is plainly an offer rather than a continuation of the explanation. */
.abstention-next {
  display: flex; flex-direction: column; align-items: flex-start; gap: 10px;
  margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--border);
}
.abstention-next-note { font-size: 13px; color: var(--muted); line-height: 1.6; max-width: 68ch; }

/* ── Intake details ── */
/* Provenance, and styled to stay out of the way of the two findings: card
   ground, no tone colour, no icon that could read as a warning. The collapsed
   state is the normal one. */
.intake-card {
  background: var(--card); border: 1px solid var(--border); border-radius: 14px;
  padding: 4px 22px 6px; box-shadow: var(--shadow);
  display: flex; flex-direction: column;
}
/* The card's own collapsible sits alone, so the divider the section header
   carries everywhere else would be a line under nothing. */
.intake-card .collapsible-header { border-top: none; }
.intake-body { font-family: var(--font-sans); }
.intake-row {
  display: flex; gap: 14px; align-items: baseline;
  padding: 7px 0; border-bottom: 1px solid var(--border);
}
.intake-row:last-child { border-bottom: none; }
.intake-row-label {
  flex: none; width: 8.5em; font-size: 10.5px; font-weight: 800;
  text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted);
}
.intake-row-value { font-size: 13px; color: var(--ink); word-break: break-word; min-width: 0; }

.intake-warnings { padding-top: 12px; display: flex; flex-direction: column; gap: 7px; }
.intake-warnings-label {
  font-size: 10.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--muted);
}
.intake-warnings-list { list-style: none; display: flex; flex-wrap: wrap; gap: 6px; }
/* The server's own short strings, shown as they are. Monospace because that is
   what they are — identifiers, not sentences — and setting them in the reading
   face would invite them to be read as findings. */
.intake-warning {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 11.5px; color: var(--ink-soft);
  background: var(--bg-sunken); border: 1px solid var(--border);
  border-radius: 6px; padding: 3px 8px;
}

/* The headline the reader never chose. Amber-free: nothing has gone wrong yet,
   and the server may well have read the right title. It is a "check this",
   which is why it carries an action rather than a tone. */
.intake-headline-note {
  display: flex; flex-direction: column; align-items: flex-start; gap: 7px;
  padding: 16px 0 14px;
}
.intake-headline-label {
  font-size: 10.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.1em; color: var(--muted);
}
.intake-headline-title {
  font-family: var(--font-serif); font-size: 17px; line-height: 1.35;
  color: var(--ink); max-width: 72ch;
}
.intake-headline-hint { font-size: 12.5px; color: var(--muted); line-height: 1.55; max-width: 68ch; }

/* ── What was not read ── */
/* THE ONE INTAKE SURFACE THAT IS NOT COLLAPSED, and the only one carrying a
   tone. Everything else this card holds describes what intake did to material
   it had; this describes material it never had, and a reader who does not know
   the charts and the scanned pages went unread will take a clean set of
   verdicts to cover them.

   Amber, not red: nothing has gone wrong. It is the method's boundary, stated
   plainly, and it appears on every PDF result because it is true of every one
   of them. */
.intake-text-layer {
  display: flex; align-items: flex-start; gap: 12px;
  margin: 14px 0 4px; padding: 14px 16px;
  background: var(--amber-bg); border: 1px solid var(--amber-border); border-radius: 10px;
}
.intake-text-layer-icon { flex: none; width: 18px; height: 18px; color: var(--amber-fg); margin-top: 1px; }
.intake-text-layer-icon svg { width: 100%; height: 100%; display: block; }
.intake-text-layer-text { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.intake-text-layer-label {
  font-size: 10.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.09em; color: var(--amber-fg);
}
.intake-text-layer-note { font-size: 13.5px; color: var(--ink-soft); line-height: 1.6; max-width: 72ch; }

/* ── The image intake ── */
/* Reads as the .txt loader does — a picker, a line naming what was picked, and
   a hint — because it is the same gesture. What is different is the box under
   it, which is not decoration: it decides which of two checks runs. */
.image-status:empty { display: none; }
.image-status { font-size: 11.5px; color: var(--muted); line-height: 1.5; word-break: break-word; }

.image-claim {
  display: flex; flex-direction: column; gap: 7px;
  margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--border);
}
.image-claim > label { font-size: 10px; display: flex; align-items: center; gap: 8px; }
/* Optional, and said so rather than implied by an empty asterisk. Leaving it
   empty is a real choice with a different outcome, not a field skipped. */
.label-optional {
  font-size: 9.5px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--muted);
  background: var(--bg-sunken); border: 1px solid var(--border);
  border-radius: 5px; padding: 2px 6px;
}
.image-claim textarea { min-height: 68px; }

/* ── A claim the reader did not write ── */
/* THE STRONGEST NOTICE ON THE RESULT CARD, and it is not a warning. The verdict
   above it is about a sentence the analyzer composed from a picture, and the
   reader is entitled to see that before they read the score as an answer to
   their question. Gold rather than amber: nothing has gone wrong, and treating
   a derived claim as a defect would be as wrong as hiding that it is one. */
.post-text { margin: 10px 0 4px; }
.post-text-label {
  font-size: 11px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--ink-soft);
}
.post-text-value { margin: 4px 0 0; font-size: 14px; color: var(--ink-soft); line-height: 1.6; max-width: 72ch; }

.derived-claim-note {
  display: flex; align-items: flex-start; gap: 12px;
  margin: 4px 0 2px; padding: 14px 16px;
  background: var(--bg-sunken); border: 1px solid var(--border);
  border-left: 3px solid var(--gold); border-radius: 0 10px 10px 0;
}
.derived-claim-icon { flex: none; width: 18px; height: 18px; color: var(--gold); margin-top: 1px; }
.derived-claim-icon svg { width: 100%; height: 100%; display: block; }
.derived-claim-text { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.derived-claim-label {
  font-size: 10.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.09em; color: var(--ink);
}
.derived-claim-hint { font-size: 13px; color: var(--ink-soft); line-height: 1.6; max-width: 72ch; }

/* ── What was read in the image ── */
/* PROVENANCE, STYLED AS PROVENANCE. It sits with the intake card and looks like
   it: no score, no pill, no verdict colour anywhere in it. The claim the
   analyzer drew out of the image is scored in the card above; what is in here
   is a transcription and a description, and giving either one a tone would make
   it read as a finding — which is precisely the confusion that scored a sign
   taped to a wall 6.68/10 on 4 September. */
.media-card {
  background: var(--card); border: 1px solid var(--border); border-radius: 14px;
  padding: 4px 22px 6px; box-shadow: var(--shadow);
  display: flex; flex-direction: column;
}
.media-card .collapsible-header { border-top: none; }
.media-body { font-family: var(--font-sans); display: flex; flex-direction: column; gap: 4px; }

.media-entry {
  display: flex; flex-direction: column; gap: 2px;
  padding: 10px 0; border-bottom: 1px solid var(--border);
}
.media-entry:last-child { border-bottom: none; }
.media-entry-head { display: flex; align-items: center; gap: 8px; }
.media-entry-kind {
  font-size: 9.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.09em; color: var(--muted);
  background: var(--bg-sunken); border: 1px solid var(--border);
  border-radius: 5px; padding: 2px 7px;
}

/* An image that could not be read at all. Amber, because it is a limit on what
   was analysed — the same reading as the PDF text-layer note. */
.media-entry-failed {
  display: flex; flex-direction: column; gap: 4px;
  margin: 8px 0 4px; padding: 12px 14px;
  background: var(--amber-bg); border: 1px solid var(--amber-border); border-radius: 10px;
}
.media-entry-failed-label {
  font-size: 10.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.09em; color: var(--amber-fg);
}
.media-entry-failed-note { font-size: 13px; color: var(--ink-soft); line-height: 1.6; max-width: 72ch; }

/* Read, and it did not bear on the verdict. Quieter than a failure because it
   is not one — but it is still a correction to the obvious assumption that
   every image sent contributed to the answer. */
.media-entry-unused {
  margin: 8px 0 4px; padding: 10px 14px;
  font-size: 13px; color: var(--ink-soft); line-height: 1.6; max-width: 72ch;
  background: var(--bg-sunken); border: 1px dashed var(--border); border-radius: 10px;
}

.media-row {
  display: flex; gap: 14px; align-items: baseline;
  padding: 7px 0;
}
.media-row-label {
  flex: none; width: 11em; font-size: 10.5px; font-weight: 800;
  text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted);
}
.media-row-value { font-size: 13px; color: var(--ink); line-height: 1.6; word-break: break-word; min-width: 0; max-width: 72ch; }
/* Verbatim, in the image's own language, so it is set as a quotation rather
   than as this page's own prose. */
.media-row-value.quoted { font-family: var(--font-serif); font-size: 14px; color: var(--ink-soft); }
.media-other-claims {
  list-style: disc; padding-left: 18px; min-width: 0;
  font-size: 13px; color: var(--ink-soft); line-height: 1.6; max-width: 72ch;
}
.media-other-claims li { padding: 2px 0; }

/* ── Load-bearing claims ── */
/* STYLED AS A RESULT, NOT AS A NOTICE. This is the whole point of the card: a
   multi-claim document has been analysed, and the verdicts in here are as real
   as the central claim's. So it borrows the result card's own vocabulary — the
   same card ground, the same verdict pills, the same "Not scored" rule — rather
   than the muted treatment the abstention card uses for a genuine absence.
   Anything quieter would restate in CSS the thing the copy was fixed to stop
   saying. */
.load-bearing-card {
  background: var(--card); border: 1px solid var(--border); border-radius: 14px;
  padding: 22px 24px; display: flex; flex-direction: column; gap: 14px;
  box-shadow: var(--shadow);
}
.load-bearing-head { display: flex; flex-direction: column; gap: 6px; }
.load-bearing-label {
  font-size: 10.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.1em; color: var(--muted);
}
.load-bearing-intro {
  font-size: 15px; color: var(--ink-soft); line-height: 1.6;
  font-family: var(--font-serif); max-width: 72ch;
}
.load-bearing-assessment {
  font-size: 14.5px; color: var(--ink); line-height: 1.6;
  font-family: var(--font-serif); max-width: 72ch;
  padding-left: 14px; border-left: 3px solid var(--border);
}

/* Counts, not a verdict. Chips carry the verdict tones so the tally reads at a
   glance, but nothing here is a document-level score — see normalizeAssessment
   for why one is never derived. */
.load-bearing-tally { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.tally-total {
  font-size: 11px; font-weight: 700; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--muted);
}
.tally-chip {
  font-size: 11px; font-weight: 700; padding: 4px 10px; border-radius: 999px;
}
.tally-chip.good { background: var(--tone-good-bg); color: var(--tone-good-fg); }
.tally-chip.severe { background: var(--tone-severe-bg); color: var(--tone-severe-fg); }
.tally-chip.neutral { background: var(--tone-neutral-bg); color: var(--tone-neutral-fg); }
.tally-chip.info { background: var(--tone-info-bg); color: var(--tone-info-fg); }
.tally-chip.error { background: var(--tone-error-bg); color: var(--tone-error-fg); }
.tally-extra { font-size: 12px; color: var(--muted); }

/* The "not checked" marker moved into the row's ring slot — see
   .score-ring-empty. It is an absence where a number would be, which is where
   a reader looks for one, and saying it twice in one row said it worse. */

/* ── One claim, in the shape of the card above it ── */
/* A hairline between paragraphs is what a list of NOTES looks like. Each of
   these is a verdict on a claim, arrived at the same way the one at the top of
   the page was, and it now has the same anatomy: a ring, then the claim, then
   the pill — one step down in scale.

   Given its own ground rather than a rule between rows, because six results in
   a column need to be told apart at a glance before any of them is read. */
.load-bearing-list {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: 12px;
}
.load-bearing-item {
  padding: 18px 20px;
  background: var(--bg-sunken); border: 1px solid var(--border); border-radius: 12px;
  display: flex; flex-direction: column; gap: 11px;
}

/* Same arrangement as .claim-head, at row scale: the number is read first and
   the claims line up down the page whether or not they have one. */
.load-bearing-item-head { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; }
.load-bearing-item-text { display: flex; flex-direction: column; gap: 7px; min-width: 0; flex: 1 1 20ch; }
.load-bearing-item-text .eyebrow { font-size: 9.5px; letter-spacing: 0.13em; }
.load-bearing-verdict-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* Stepped from the card's clamp(19px, 1.5vw, 24px) — one level down, the same
   face, so the two read as the same kind of thing at different scales. */
.load-bearing-text {
  font-size: 17px; line-height: 1.4; color: var(--ink);
  font-family: var(--font-serif); max-width: 60ch; letter-spacing: -0.005em;
}
.load-bearing-assessed {
  font-size: 12.5px; color: var(--muted); line-height: 1.5; max-width: 68ch;
}
.load-bearing-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.load-bearing-frame {
  font-size: 11px; font-weight: 600; letter-spacing: 0.03em; color: var(--muted);
  padding: 3px 9px; border: 1px solid var(--border); border-radius: 999px;
}
.load-bearing-source-count { font-size: 12px; color: var(--muted); }
.load-bearing-summary {
  font-size: 14.5px; color: var(--ink-soft); line-height: 1.65;
  font-family: var(--font-serif); max-width: 70ch;
}
.load-bearing-sources {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: 4px;
}
.load-bearing-source { display: flex; align-items: baseline; gap: 8px; font-size: 13px; }
.load-bearing-source-link { color: var(--link); text-decoration: none; }
.load-bearing-source-link:hover { text-decoration: underline; }
.load-bearing-stance { font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; }
.load-bearing-stance.stance-supports { color: var(--tone-good-fg); }
.load-bearing-stance.stance-contradicts { color: var(--tone-severe-fg); }

/* ── Currency: overtaken by events ── */
/* A THIRD TREATMENT, DELIBERATELY UNLIKE THE OTHER TWO. It is not a credibility
   verdict, so it borrows none of the verdict tones; it is not a defect in the
   headline, so it avoids the amber the fidelity defect uses. It reads as a
   notice: the brand navy on a tinted ground, an icon, no colour that means
   "wrong". The article may be accurate, well sourced and superseded all at
   once — the styling has to leave room for that being true. */
.currency-card {
  background: var(--tone-neutral-bg);
  border: 1px solid var(--border);
  border-left: 3px solid var(--quote-bg);
  border-radius: 12px;
  padding: 18px 22px;
  display: flex; align-items: flex-start; gap: 14px;
}
.currency-icon {
  width: 34px; height: 34px; border-radius: 10px; flex: none;
  background: var(--card); border: 1px solid var(--border);
  display: grid; place-items: center; color: var(--quote-bg);
}
:root.theme-dark .currency-icon { color: var(--ink); }
@media (prefers-color-scheme: dark) {
  :root:not(.theme-light) .currency-icon { color: var(--ink); }
}
.currency-icon svg { width: 17px; height: 17px; display: block; }
.currency-text { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.currency-label {
  font-size: 10.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.12em; color: var(--tone-neutral-fg);
}
.currency-note {
  font-family: var(--font-serif); font-size: 15px; line-height: 1.65;
  color: var(--ink); max-width: 78ch;
}
/* The dated specifics — the part an editor acts on. */
.currency-claims { list-style: none; display: flex; flex-direction: column; gap: 10px; }
.currency-claims:empty { display: none; }
.currency-claims li {
  display: flex; flex-direction: column; gap: 3px;
  border-left: 2px solid var(--border-strong); padding-left: 14px; max-width: 78ch;
}
.currency-claim-text {
  font-family: var(--font-serif); font-size: 14px; color: var(--ink-soft); line-height: 1.5;
}
.currency-claim-note { font-size: 13px; font-weight: 700; color: var(--ink); line-height: 1.5; }

/* ── Result card ── */
.result-card {
  background: var(--card); border: 1px solid var(--border); border-radius: 14px;
  padding: 24px 26px; display: flex; flex-direction: column; gap: 14px;
  box-shadow: var(--shadow);
}

/* ── The one card that is the answer ── */
/* THE SCORE IS THE DELIVERABLE. It used to sit as a 104px ring at the right of
   a claim header, under a heading smaller than the claim text beside it, below
   the provenance and below the headline check — the number the whole page
   exists to produce was the fifth thing a reader met.

   This does not add a summary band duplicating what is already here, because a
   second copy of a verdict is a second copy to drift. It gives the card that
   already holds the answer the weight of one: it reads first, it is set apart
   from the ground, and the figure inside it is the largest thing on the page. */
#resultCard {
  padding: 30px 30px 26px;
  border-width: 2px; border-color: var(--border-strong);
  box-shadow: 0 1px 2px rgba(21, 38, 61, 0.05), 0 14px 40px rgba(21, 38, 61, 0.09);
}
#resultCard .indicator-heading { font-size: 12px; letter-spacing: 0.14em; color: var(--ink-soft); }

/* ── The two indicators ── */
/* Article credibility and headline fidelity are separate measures of separate
   things, and the styling says so: identical card, identical heading weight,
   adjacent, neither nested inside the other. Anything that made one look
   subordinate would imply a relationship that does not exist. */
.indicator-card { gap: 16px; }
.indicator-head {
  display: flex; flex-direction: column; gap: 4px;
  padding-bottom: 14px; border-bottom: 1px solid var(--border);
}
.indicator-heading {
  font-size: 10.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.12em; color: var(--muted);
}
.indicator-sub { font-size: 13px; color: var(--ink-soft); line-height: 1.55; }
#fidelityCard .indicator-heading { font-size: 12px; letter-spacing: 0.14em; color: var(--ink-soft); }

/* The uppercase micro-label above a section — the product's most repeated
   typographic device. */
.eyebrow {
  font-size: 10.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.12em; color: var(--muted);
}

/* ── Claim header ── */
/* The claim, its verdict and its score, in the product's arrangement: the
   assessed claim set large in serif, the ring to its right. */
/* The score reads BEFORE the claim it belongs to — `order` rather than a DOM
   move, so the markup keeps naming the claim before its number. Below the
   breakpoint the grid stacks and the number is simply first. */
.claim-head { display: flex; align-items: center; gap: 30px; flex-wrap: wrap; }
.claim-head .score-row { order: -1; margin-left: 0; }
/* The claim keeps a measure so it never runs the width of a wide card, but the
   ring is pushed to the far edge rather than trailing the text — the gap
   between them is the layout, not an accident of string length. */
.claim-head-text { display: flex; flex-direction: column; gap: 10px; min-width: 0; max-width: 46ch; flex: 1 1 22ch; }
.score-row { margin-left: auto; }

/* Stepped DOWN from clamp(26px, 2.4vw, 38px). The claim is what was checked and
   it has to be readable; it is not the finding, and while it was the largest
   thing in the card it read as one. */
.result-title {
  font-family: var(--font-serif); font-size: clamp(19px, 1.5vw, 24px); font-weight: 600;
  line-height: 1.35; letter-spacing: -0.01em; color: var(--ink);
}

/* ── The document label ── */
/* Set at the same weight the single claim's title gets, because it answers the
   same question the card has always answered — it just answers it over the set
   rather than over whichever claim won a tie-break.

   The average below it is deliberately SMALLER than the label and carries its
   own caption. It is real and worth seeing; it is not the finding, and a
   layout that let it read as one would restore exactly the masking the
   count-driven label removes. */
.document-verdict { display: flex; flex-direction: column; gap: 12px; }
.document-verdict-head { display: flex; flex-direction: column; align-items: flex-start; gap: 9px; }
/* The document-mode equivalent of the ring, and sized like it: this label IS
   the deliverable in that mode, arrived at by counting verdicts. The average
   beneath it stays small — promoting the number would restore exactly the
   masking the count-driven label removes. */
.document-verdict-label {
  font-family: var(--font-serif); font-size: clamp(32px, 3.4vw, 52px); font-weight: 600;
  line-height: 1.1; letter-spacing: -0.02em; color: var(--ink);
  border-bottom: 5px solid var(--ring-track); padding-bottom: 6px;
}
.document-verdict-label.good { border-bottom-color: var(--tone-good-solid); }
.document-verdict-label.severe { border-bottom-color: var(--tone-severe-solid); }
.document-verdict-label.neutral { border-bottom-color: var(--tone-neutral-solid); }
.document-verdict-label.info { border-bottom-color: var(--tone-info-solid); }

/* Visible by design. A label counted over four of nine claims is a different
   statement from one counted over all nine, and the difference is invisible in
   the label itself. */
.document-verdict-provisional {
  font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.07em;
  padding: 5px 11px; border-radius: 999px;
  background: var(--amber-bg); color: var(--amber-fg); border: 1px solid var(--amber-border);
}
.document-verdict-reason {
  font-family: var(--font-serif); font-size: 16px; line-height: 1.6;
  color: var(--ink-soft); max-width: 72ch;
}
.document-verdict-receipt {
  font-size: 12.5px; color: var(--muted); font-weight: 600; letter-spacing: 0.01em;
}
.document-verdict-average { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; }
.document-verdict-average-num {
  font-family: var(--font-serif); font-size: 19px; font-weight: 600; color: var(--ink-soft);
}
.document-verdict-average-caption { font-size: 11.5px; color: var(--muted); max-width: 48ch; line-height: 1.5; }

/* ── The counted head ── */
/* Set at the document label's weight, because it answers the same question for
   the same reason — it just arrives at it by counting the rows below rather
   than being handed a label by the server.

   The headline carries the tone, and the tone follows the DISPUTED count: one
   contradicted claim is severe however many supported ones surround it. That
   is the whole argument for counting instead of averaging, expressed as a
   colour. */
.claim-rollup { display: flex; flex-direction: column; gap: 13px; }
.claim-rollup-head { display: flex; flex-direction: column; align-items: flex-start; gap: 9px; }
.claim-rollup-headline {
  font-family: var(--font-serif); font-size: clamp(30px, 3.2vw, 48px); font-weight: 600;
  line-height: 1.1; letter-spacing: -0.02em; color: var(--ink);
  border-bottom: 5px solid var(--ring-track); padding-bottom: 6px;
}
.claim-rollup-headline.good { border-bottom-color: var(--tone-good-solid); }
.claim-rollup-headline.severe { border-bottom-color: var(--tone-severe-solid); }
.claim-rollup-headline.neutral { border-bottom-color: var(--tone-neutral-solid); }
.claim-rollup-tally { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.claim-rollup-reason {
  font-family: var(--font-serif); font-size: 16px; line-height: 1.6;
  color: var(--ink-soft); max-width: 72ch;
}
/* Why there is no single figure, said out loud. An absence a reader has to
   infer reads as something missing; the reason for it is itself a finding. */
.claim-rollup-note {
  font-size: 12.5px; color: var(--muted); line-height: 1.55; max-width: 64ch;
  padding-left: 12px; border-left: 2px solid var(--border);
}

.verdict-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.confidence-text { font-size: 12.5px; color: var(--muted); font-weight: 600; }

.pill {
  display: inline-block; font-size: 10.5px; font-weight: 800; letter-spacing: 0.1em;
  text-transform: uppercase; padding: 6px 14px; border-radius: 999px;
}
.pill.good { background: var(--tone-good-bg); color: var(--tone-good-fg); }
.pill.severe { background: var(--tone-severe-bg); color: var(--tone-severe-fg); }
.pill.neutral { background: var(--tone-neutral-bg); color: var(--tone-neutral-fg); }
.pill.info { background: var(--tone-info-bg); color: var(--tone-info-fg); }
.pill.error { background: var(--tone-error-bg); color: var(--tone-error-fg); }

/* ── Score ring ── */
/* A ring, not a bar — the product's signature. The arc is drawn with a
   conic-gradient masked into an annulus; app.js sets only the sweep angle and
   the tone class, and the colour comes from the tone token via currentColor so
   the ring is theme-aware without JavaScript knowing any colours. */
.score-row { flex: none; }
/* 104px -> 168px, and the stroke with it. At the old size the figure sat at
   21px against a 38px claim title beside it: the page's largest type was the
   sentence being judged rather than the judgment. */
.score-ring {
  position: relative; width: 168px; height: 168px;
  display: grid; place-items: center;
}
.score-fill {
  position: absolute; inset: 0; border-radius: 50%;
  background: conic-gradient(var(--ring-track) 0, var(--ring-track) 0);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 13px), #000 calc(100% - 12px));
  mask: radial-gradient(farthest-side, transparent calc(100% - 13px), #000 calc(100% - 12px));
  transition: background 0.5s ease;
}
.score-fill.good { color: var(--tone-good-solid); }
.score-fill.severe { color: var(--tone-severe-solid); }
.score-fill.neutral { color: var(--tone-neutral-solid); }
.score-fill.info { color: var(--tone-info-solid); }
.score-fill.error { color: var(--tone-error-solid); }

.score-ring-center { position: relative; display: flex; flex-direction: column; align-items: center; gap: 3px; }
.score-badge {
  font-family: var(--font-serif); font-size: 44px; font-weight: 600;
  line-height: 1; letter-spacing: -0.03em; color: var(--ink);
}
/* Tone on the FIGURE as well as the arc. The colour still comes from the
   verdict band and never from the number — see isScoreSuppressed and the note
   on VERDICT_TONE — this only stops a 2.4 reading as neutrally as an 8.4. */
.score-badge.good { color: var(--tone-good-fg); }
.score-badge.severe { color: var(--tone-severe-fg); }
.score-badge.neutral { color: var(--tone-neutral-fg); }
.score-badge.info { color: var(--tone-info-fg); }
.score-badge.error { color: var(--tone-error-fg); }
.score-caption {
  font-size: 9px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.14em; color: var(--muted);
}

/* ── The row-scale ring ── */
/* The same element, the same sweep, one size down. Sharing the class is the
   point: a claim scoring 8.5 in the list must draw exactly as a central claim
   scoring 8.5 does, and two ring implementations are two rings that drift. */
.score-ring.compact { width: 96px; height: 96px; }
.score-ring.compact .score-fill {
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 9px), #000 calc(100% - 8px));
  mask: radial-gradient(farthest-side, transparent calc(100% - 9px), #000 calc(100% - 8px));
}
.score-badge.compact { font-size: 19px; letter-spacing: -0.02em; }

/* NO NUMBER, SAME FOOTPRINT. A row whose ring vanished would pull its claim out
   of line with every other row, and that ragged edge reads as a different kind
   of result rather than the same kind with no number in it. Dashed, because the
   outline is holding a place rather than reporting a quantity. */
.score-ring-empty {
  border: 2px dashed var(--border-strong); border-radius: 50%;
  padding: 10px; text-align: center;
}
.score-ring-empty-label {
  font-size: 11px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.06em; line-height: 1.3; color: var(--muted);
}
/* 'unverified' is a FINDING — checked, and nothing independent bore on it in
   either direction — so it keeps its verdict's tone. 'unchecked' never became a
   finding at all and stays grey. */
.score-ring-empty.neutral { border-color: var(--tone-neutral-solid); }
.score-ring-empty.neutral .score-ring-empty-label { color: var(--tone-neutral-fg); }
.score-ring-empty.info { border-color: var(--tone-info-solid); }
.score-ring-empty.error { border-color: var(--tone-error-solid); }
.score-ring-empty.error .score-ring-empty-label { color: var(--tone-error-fg); }

/* The verdict beside the number, at a size that carries. It is the half of the
   answer that survives when the figure is withheld. */
#resultCard .claim-head .pill { font-size: 12px; padding: 8px 18px; letter-spacing: 0.09em; }

/* ── The reserved slot ── */
/* Shaped like the card it stands in for, so the page does not resize under the
   reader when the score lands. Deliberately inert: no shimmer, no pulse on the
   ring — this sits on screen for the better part of a minute, and something
   animating for that long beside a result the reader is trying to read is
   noise. */
.score-pending {
  background: var(--card); border: 2px dashed var(--border-strong); border-radius: 14px;
  padding: 30px; display: flex; flex-direction: column; gap: 18px;
}
.score-pending-body { display: flex; align-items: center; gap: 30px; flex-wrap: wrap; }
.score-pending-ring {
  flex: none; width: 168px; height: 168px; border-radius: 50%;
  border: 13px solid var(--ring-track);
}
.score-pending-text { display: flex; flex-direction: column; gap: 7px; min-width: 0; flex: 1 1 22ch; }
.score-pending-title { font-family: var(--font-serif); font-size: 22px; color: var(--ink-soft); }
.score-pending-note { font-size: 13px; color: var(--muted); line-height: 1.6; max-width: 52ch; }

.not-scored-box {
  background: var(--bg-sunken); border: 1px solid var(--border); border-radius: 10px;
  padding: 14px 16px; display: flex; flex-direction: column; gap: 5px;
}
/* WHEN THERE IS NO NUMBER, THIS IS THE ANSWER. "Unverified" means the claim was
   checked and nothing independent bore on it either way — a real finding, and
   the one most likely to be misread as a failure to produce a score. It gets
   the weight the ring would have had; the enlarged verdict pill above it
   carries the rest. */
#resultCard .not-scored-box { padding: 18px 20px; gap: 7px; }
#resultCard .not-scored-label {
  font-family: var(--font-serif); font-size: 26px; font-weight: 600;
  letter-spacing: -0.01em; color: var(--ink); text-transform: none;
}
#resultCard .not-scored-note { font-size: 14px; line-height: 1.6; }
.not-scored-label {
  font-size: 10.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.1em; color: var(--muted);
}
.not-scored-note { font-size: 14px; color: var(--ink-soft); line-height: 1.6; font-family: var(--font-serif); max-width: 72ch; }

.error-result-box {
  background: var(--tone-error-bg); border: 1px solid var(--tone-error-fg); border-radius: 10px;
  padding: 15px 17px; display: flex; flex-direction: column; gap: 10px;
  font-size: 14px; color: var(--tone-error-fg);
}
.error-result-msg { font-size: 13px; line-height: 1.55; color: var(--tone-error-fg); }
.error-result-box .btn-secondary { align-self: flex-start; }

/* Shown only when the sentence in the article and the proposition actually
   checked differ — the verdict applies to the latter. */
.assessed-note {
  display: flex; flex-direction: column; gap: 3px;
  background: var(--bg-sunken); border-left: 3px solid var(--gold);
  border-radius: 0 8px 8px 0; padding: 10px 14px;
}
.assessed-label {
  font-size: 9.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.1em; color: var(--muted);
}
.assessed-value { font-size: 14px; color: var(--ink); line-height: 1.55; font-family: var(--font-serif); }

/* ── The pull quote ── */
/* The analyzer's plain-language statement of what is actually the case, given
   the product's quote-block treatment: deep navy, serif, gold quote mark. */
.summary-text {
  max-width: 62em;
  font-family: var(--font-serif); font-size: 17.5px; line-height: 1.55;
  color: var(--quote-ink); background: var(--quote-bg);
  border-radius: 12px; padding: 22px 26px 22px 62px; position: relative;
}
.summary-text::before {
  content: "\201C"; position: absolute; left: 22px; top: 16px;
  font-family: var(--font-serif); font-size: 46px; line-height: 1;
  color: var(--gold); opacity: 0.9;
}

/* ── Headline fidelity ── */
/* TWO TREATMENTS, AND THE SPLIT IS isDefect — never the fidelity value.
   `sensationalised` returns isDefect:false and gets the informational style:
   muted, the same weight as a note. Not red, no warning triangle, not grouped
   with overstated/unsupported. Tabloid register is not inaccuracy, and an
   editor who sees heightened phrasing flagged as a defect stops trusting the
   indicator within a day. */
.fidelity-body { display: flex; flex-direction: column; gap: 12px; }
.fidelity-main { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.fidelity-aside { display: flex; flex-direction: column; gap: 12px; min-width: 0; }

@media (min-width: 1024px) {
  .fidelity-body {
    display: grid; align-items: start;
    grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
    column-gap: clamp(28px, 3vw, 44px);
  }
  /* In the rail the divider is the column rule, not a line above each block. */
  .fidelity-aside > .fidelity-support, .fidelity-aside > .fidelity-issues {
    border-top: none; padding-top: 0;
  }
  .fidelity-aside {
    border-left: 1px solid var(--border);
    padding-left: clamp(28px, 3vw, 44px);
    gap: 22px;
  }
}
.fidelity-verdict-row { display: flex; align-items: center; gap: 10px; }
.fidelity-pill {
  display: inline-block; padding: 8px 18px; border-radius: 999px;
  font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.09em;
}
.fidelity-pill.informational { background: var(--tone-neutral-bg); color: var(--tone-neutral-fg); }
.fidelity-pill.defect { background: var(--amber-bg); color: var(--amber-fg); }

.fidelity-headline {
  font-family: var(--font-serif); font-size: 19px; font-weight: 600; line-height: 1.35;
  letter-spacing: -0.01em; color: var(--ink); max-width: 46ch;
}
/* Grown alongside the credibility figure. The two indicators are adjacent and
   EQUALLY WEIGHTED by design — enlarging one and leaving the other is how a
   pair becomes a headline with a footnote. */
.fidelity-label {
  font-family: var(--font-serif); font-size: clamp(19px, 1.6vw, 25px);
  font-weight: 600; color: var(--ink); line-height: 1.3; letter-spacing: -0.01em;
}
/* Written for an editor and the most useful thing on the card, so it gets
   body-copy treatment rather than being squeezed into a caption. */
.fidelity-reasoning {
  font-family: var(--font-serif); font-size: 15px; color: var(--ink-soft); line-height: 1.65;
  max-width: 78ch;
}

.fidelity-support, .fidelity-issues {
  display: flex; flex-direction: column; gap: 8px;
  padding-top: 14px; border-top: 1px solid var(--border);
}
.fidelity-support-label, .fidelity-issues-label {
  font-size: 10.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.1em; color: var(--muted);
}
.fidelity-support-list, .fidelity-issues-list { list-style: none; display: flex; flex-direction: column; gap: 9px; }

/* Verbatim article sentences, rendered as the quotations they are. */
.fidelity-support-list li { border-left: 2px solid var(--gold); padding-left: 14px; }
.fidelity-quote {
  font-family: var(--font-serif); font-size: 14.5px; color: var(--ink-soft);
  line-height: 1.6; quotes: "\201C" "\201D";
}
.fidelity-issues-list li {
  font-size: 13.5px; color: var(--amber-fg); line-height: 1.6;
  list-style: disc; margin-left: 18px;
}

/* The check failed. Not a finding about the headline, so it carries no verdict
   styling of any kind — a false accusation against a sound headline is worse
   than showing nothing. */
.fidelity-unavailable {
  background: var(--bg-sunken); border: 1px solid var(--border); border-radius: 10px;
  padding: 14px 16px; display: flex; flex-direction: column; gap: 5px;
}
.fidelity-unavailable-label {
  font-size: 10.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.1em; color: var(--muted);
}
.fidelity-unavailable-note { font-size: 13.5px; color: var(--ink-soft); line-height: 1.6; }

/* ── Partial-report warning ── */
/* The verdict below it is real, so this is a caution inside the card, not
   the transport error banner. */
.report-warnings-box {
  background: var(--amber-bg); border: 1px solid var(--amber-border); border-radius: 10px;
  padding: 12px 16px; display: flex; flex-direction: column; gap: 5px;
}
.report-warnings-label {
  font-size: 10.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.1em; color: var(--amber-fg);
}
.report-warnings-list { list-style: disc; padding-left: 18px; }
.report-warnings-list li { font-size: 12.5px; color: var(--amber-fg); line-height: 1.55; }

/* ── Headline vs. story delta ── */
/* Legacy: the analyzer no longer verifies the headline against external
   sources, so this should no longer arrive. See renderDelta in app.js. */
.delta-box {
  border: 1px solid var(--border); border-radius: 10px; background: var(--bg-sunken);
  padding: 16px 18px; display: flex; flex-direction: column; gap: 9px;
}
.delta-box.overreach { background: var(--amber-bg); border-color: var(--amber-border); }
.delta-heading { font-size: 16px; font-weight: 700; color: var(--ink); line-height: 1.4; font-family: var(--font-serif); }
.delta-box.overreach .delta-heading { color: var(--amber-fg); }
.delta-note { font-size: 13.5px; color: var(--ink-soft); line-height: 1.6; }
.delta-box.overreach .delta-note { color: var(--amber-fg); }
.delta-compare {
  display: flex; flex-direction: column; gap: 7px;
  border-top: 1px solid var(--border); padding-top: 10px;
}
.delta-box.overreach .delta-compare { border-top-color: var(--amber-border); }
.delta-side { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.delta-side-label { font-size: 12px; font-weight: 700; color: var(--ink); min-width: 11em; }
.delta-compare .pill { font-size: 9.5px; padding: 4px 10px; }
.delta-side-score { font-size: 12.5px; font-weight: 800; color: var(--ink-soft); }
.delta-gap { font-size: 12px; color: var(--muted); }
.delta-box.overreach .delta-gap { color: var(--amber-fg); }

/* ── Selection transparency ── */
/* Headline mode ranks claims and checks one. These say which and how
   load-bearing, so the pick reads as a ranking rather than a certainty. */
.selection-strip { display: flex; flex-wrap: wrap; gap: 7px; }
.selection-chip {
  font-size: 11px; font-weight: 700; color: var(--ink-soft);
  background: var(--bg-sunken); border: 1px solid var(--border);
  border-radius: 999px; padding: 4px 12px; cursor: help;
}

.ambiguity-box {
  background: var(--bg-sunken); border-left: 3px solid var(--muted);
  border-radius: 0 8px 8px 0; padding: 12px 14px;
  display: flex; flex-direction: column; gap: 4px;
}
.ambiguity-label {
  font-size: 9.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.1em; color: var(--muted);
}
.ambiguity-runner-up { font-size: 14px; color: var(--ink); line-height: 1.55; font-family: var(--font-serif); }

/* ── Framing advisory ── */
/* Visually detached from the verdict block on purpose: worth an editor's
   attention, but not evidence about the claim. */
.framing-flags-box {
  border: 1px dashed var(--border-strong); border-radius: 10px;
  padding: 14px 16px; display: flex; flex-direction: column; gap: 8px;
}
.framing-flags-label {
  font-size: 10.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.1em; color: var(--ink-soft);
}
.framing-flags-sub { font-weight: 600; text-transform: none; letter-spacing: normal; color: var(--muted); }
.framing-flags-list {
  list-style: disc; padding-left: 18px; display: flex; flex-direction: column; gap: 7px;
}
.framing-flags-list li { font-size: 13.5px; color: var(--ink-soft); line-height: 1.55; }
.framing-flag-text { color: var(--ink); }
.framing-flag-note { display: block; font-size: 12px; color: var(--muted); margin-top: 3px; }

/* The analyzer's own statement of what headline mode covers. */
.mode-note {
  font-size: 12px; color: var(--muted); line-height: 1.6;
  border-top: 1px solid var(--border); padding-top: 12px;
}

/* ── Result layout ── */
/* Single column by default; at desk width it splits the way the product's
   assessment page does — the reading column beside a rail carrying the
   reference and provenance material. The DOM order is the reading order, so
   the collapsed state needs no special handling. */
.result-columns { display: grid; grid-template-columns: minmax(0, 1fr); }
.result-main, .result-rail { min-width: 0; }

@media (min-width: 1024px) {
  .result-columns {
    grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr);
    column-gap: clamp(28px, 3vw, 44px);
  }
  .result-rail {
    border-left: 1px solid var(--border);
    padding-left: clamp(28px, 3vw, 44px);
  }
  /* The rail's first divider would double up with the column rule. */
  .result-rail > .collapsible:first-child .collapsible-header { border-top: none; padding-top: 0; }
}

/* ── Section headers ── */
/* The product's repeated section device: an icon in a rounded tile, a small
   uppercase eyebrow, and the section name set large in serif. Here they are
   also the collapsible triggers, so the chevron stays as the affordance — the
   look is the product's, the behaviour is this page's. */
.collapsible-header {
  display: flex; align-items: center; gap: 14px; width: 100%;
  background: none; border: none; border-top: 1px solid var(--border);
  padding: 18px 0 14px; margin: 0; cursor: pointer; text-align: left;
  font-family: var(--font-sans); color: inherit;
}
.section-icon {
  width: 40px; height: 40px; border-radius: 11px; flex: none;
  background: var(--bg-sunken); border: 1px solid var(--border);
  display: grid; place-items: center; color: var(--ink-soft);
}
.section-icon svg { width: 19px; height: 19px; display: block; }
.section-titles { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.section-eyebrow {
  font-size: 9.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.14em; color: var(--muted);
}
.section-title {
  font-family: var(--font-serif); font-size: 20px; font-weight: 600;
  letter-spacing: -0.01em; color: var(--ink); line-height: 1.25;
}
.count { font-size: 12px; font-weight: 600; color: var(--muted); }
.chevron {
  flex: none; font-size: 10px; color: var(--muted);
  transition: transform 0.15s; transform-origin: 50% 50%;
}
.collapsible.open .chevron { transform: rotate(90deg); }
.collapsible-header:hover .section-title { color: var(--ink); }
.collapsible-header:hover .section-icon { border-color: var(--border-strong); }
.collapsible-body { display: none; padding: 4px 0 10px; }
.collapsible.open .collapsible-body { display: block; }
/* Bodies that lay themselves out have to restate it here: `.collapsible.open
   .collapsible-body` is two classes deep and would otherwise win over the
   single-class rule on the list itself, silently flattening every grid and
   flex container in this card back to block. */
.collapsible.open .criteria-list { display: grid; }
.collapsible.open .justification-block,
.collapsible.open .key-evidence-list,
.collapsible.open .sources-list { display: flex; }

/* The analysis prose is the longest thing a reader actually reads, so it takes
   the product's serif body treatment. */
#analysisBody {
  font-family: var(--font-serif); font-size: 15.5px; line-height: 1.7; color: var(--ink-soft);
  max-width: 74ch;
}

/* ── Assessment criteria ── */
/* Two-up cards, each with the criterion set in serif, a boxed score chip, and
   the reasoning below — the product's criteria grid. */
.criteria-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 12px; }
.criteria-item {
  background: var(--bg-sunken); border: 1px solid var(--border); border-radius: 12px;
  padding: 16px 18px; display: flex; flex-direction: column; gap: 10px;
}
.criteria-item-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.criteria-item-label {
  font-family: var(--font-serif); font-size: 16px; font-weight: 600;
  color: var(--ink); line-height: 1.3;
}
/* Boilerplate that reads identically on every card, so it is generated rather
   than written into the DOM — the label element stays exactly the criterion
   name for anything reading textContent. */
.criteria-item-label::after {
  content: "Assessment criterion"; display: block; margin-top: 3px;
  font-family: var(--font-sans); font-size: 11px; font-weight: 500;
  letter-spacing: 0.01em; color: var(--muted);
}
.criteria-item-score {
  flex: none; background: var(--card); border: 1px solid var(--border);
  border-radius: 10px; padding: 7px 12px; display: flex; align-items: baseline; gap: 1px;
  font-family: var(--font-serif); color: var(--ink);
}
.criteria-item-score-num { font-size: 21px; font-weight: 600; letter-spacing: -0.02em; }
.criteria-item-score-unit { font-size: 12px; color: var(--muted); }
.criteria-item-reasoning {
  font-family: var(--font-serif); font-size: 14px; color: var(--ink-soft); line-height: 1.6;
}

/* ── Why this score ── */
/* The server's prose, then the figures it refers to as a plain ledger. */
.justification-block { display: flex; flex-direction: column; gap: 16px; }
.jb-explanation {
  font-family: var(--font-serif); font-size: 15px; line-height: 1.7; color: var(--ink-soft);
  max-width: 68ch;
}
.jb-rows { display: flex; flex-direction: column; }
.jb-row {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 11px 0; border-top: 1px solid var(--border);
}
.jb-row:last-child { border-bottom: 1px solid var(--border); }
.jb-row-label { font-size: 13.5px; color: var(--ink-soft); }
.jb-row-value {
  font-family: var(--font-serif); font-size: 15px; font-weight: 600;
  color: var(--ink); letter-spacing: -0.01em;
}

/* ── Key evidence ── */
/* Numbered discs rather than bullets, as the product numbers its findings. */
.key-evidence-list {
  list-style: none; padding-left: 0; counter-reset: evidence;
  display: flex; flex-direction: column; gap: 14px;
}
.key-evidence-list li {
  position: relative; padding-left: 42px; counter-increment: evidence; max-width: 82ch;
  font-family: var(--font-serif); font-size: 15px; color: var(--ink-soft); line-height: 1.6;
}
.key-evidence-list li::before {
  content: counter(evidence);
  position: absolute; left: 0; top: 0;
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--bg-sunken); border: 1px solid var(--border);
  display: grid; place-items: center;
  font-family: var(--font-sans); font-size: 12px; font-weight: 700; color: var(--ink-soft);
}

/* ── Sources ── */
.sources-list { display: flex; flex-direction: column; gap: 12px; }
.source-group-label {
  font-size: 9.5px; font-weight: 800; color: var(--muted); text-transform: uppercase;
  letter-spacing: 0.12em; padding: 6px 2px 0;
}
/* The poc-docs source row, set at this page's scale: outlet and stance on top,
   headline, one meta line, full text on request. */
.source-card {
  border: 1px solid var(--border); border-radius: 10px; padding: 12px 14px;
  display: flex; flex-direction: column; gap: 5px; background: var(--bg-sunken);
}
.source-card.source-card-grouped { border-left: 3px solid var(--gold); }
.source-card-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
/* The outlet carries the link — see renderSources() in app.js for why it, and
   not the headline, is the anchor. Not uppercased: outlet names carry their
   own casing (arXiv, UNESCO). */
.source-outlet {
  font-size: 14px; font-weight: 700; color: var(--link); text-decoration: none;
  min-width: 0; overflow-wrap: anywhere;
}
.source-outlet:hover { text-decoration: underline; }
.source-stance {
  flex-shrink: 0; white-space: nowrap;
  font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.05em;
  padding: 3px 9px; border-radius: 999px;
}
.source-stance.supports { background: var(--tone-good-bg); color: var(--tone-good-fg); }
.source-stance.contradicts { background: var(--tone-severe-bg); color: var(--tone-severe-fg); }
.source-stance.neutral { background: var(--tone-neutral-bg); color: var(--tone-neutral-fg); }
/* The headline arrives already capped at 160 characters and cut at a sentence
   boundary. No clamp, no ellipsis and no max-height here: a second trim would
   put two ellipses on one line. It wraps instead. */
.source-headline { font-size: 14px; color: var(--ink); line-height: 1.45; }
.source-card-meta { font-size: 12px; color: var(--muted); }
.source-fulltext-toggle {
  align-self: flex-start; margin-top: 2px;
  background: none; border: none; padding: 0;
  font-size: 10.5px; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: 0.06em;
}
.source-fulltext-toggle:hover { color: var(--link); }
.source-card-snippet {
  font-size: 13px; color: var(--ink-soft); line-height: 1.55; overflow-wrap: anywhere;
}

@media (min-width: 1024px) {
  .score-ring { width: 132px; height: 132px; }
  .score-fill {
    -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 10px), #000 calc(100% - 9px));
    mask: radial-gradient(farthest-side, transparent calc(100% - 10px), #000 calc(100% - 9px));
  }
  .score-badge { font-size: 26px; }
  .claim-head { gap: 40px; }
}

@media (max-width: 560px) {
  .page { padding: 28px 14px 60px; }
  .result-card { padding: 18px 18px; }
  .form-body, .form-head { padding: 16px 16px; }
  /* The reassurance line drops below the title rather than squeezing it into
     four lines. */
  .form-head { flex-wrap: wrap; }
  .form-head-note { flex-basis: 100%; padding-left: 50px; }
  .page-title { font-size: 32px; }
  .form-footer { flex-direction: column; align-items: stretch; }
  .claim-head { flex-direction: column; gap: 16px; }
  .result-title { font-size: 19px; }
  .claim-rollup-headline { font-size: 27px; }
  .load-bearing-item { padding: 15px 15px; }
  .load-bearing-text { font-size: 16px; }
  .load-bearing-item-head { gap: 14px; }
  .score-ring.compact { width: 84px; height: 84px; }
  .score-badge.compact { font-size: 17px; }
  #resultCard { padding: 22px 18px 20px; }
  .score-ring, .score-pending-ring { width: 132px; height: 132px; }
  .score-badge { font-size: 36px; }
  .claim-head, .score-pending-body { gap: 20px; }
  .summary-text { font-size: 16px; padding: 18px 20px 18px 52px; }
  .section-title { font-size: 18px; }
}

/* ── Download PDF ────────────────────────────────────────────────────────────
   The bar that offers the PDF, and the title block that only the PDF shows.
   Not a card: like the next-article foot, it is a way to use the report, not a
   section of it. */
.report-actions {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  flex-wrap: wrap; padding: 0 2px;
}
.report-actions-note { font-size: 12.5px; color: var(--muted); font-weight: 600; }
.print-only { display: none; }

/* ── Print: the report, not the page ─────────────────────────────────────────
   What Download PDF produces. The browser's print-to-PDF keeps every <a href>
   as a clickable link, which is why the PDF is made this way and not by any
   route that rasterises the page — so nothing here may replace a link with
   text or draw the report as an image.

   Four jobs, in order:
     1. Light, always. A reader in dark mode would otherwise print pale text on
        a dark ground, or pale text on white paper with the grounds dropped.
     2. Only the report. The form, the page's own title and every control go.
        NOT `button` wholesale: every section heading here is the text of a
        collapsible's <button>, and hiding buttons would hide the headings.
     3. Everything open. The sources are the product; a PDF that shows them
        folded is a PDF without the evidence.
     4. A claim is never split across a page break, so a verdict and its
        sources are read together.

   Verdict colour is never the only signal: every pill and chip carries its
   verdict in words, and here also an outline, so it survives a greyscale
   printer that drops tinted grounds. */
@page {
  size: A4;
  margin: 18mm 14mm 16mm;
  @top-left { font-family: -apple-system, "Segoe UI", Roboto, sans-serif; font-size: 8pt; color: #555; vertical-align: bottom; padding-bottom: 3mm; }
  @top-right { font-family: -apple-system, "Segoe UI", Roboto, sans-serif; font-size: 8pt; color: #555; vertical-align: bottom; padding-bottom: 3mm; }
  @bottom-right { content: "Page " counter(page) " of " counter(pages); font-family: -apple-system, "Segoe UI", Roboto, sans-serif; font-size: 8pt; color: #555; }
}

/* ── The story card ── */
/* THE ANSWER TO THE QUESTION THAT WAS ASKED. The journalist typed a story and
   pasted a link; this card is the story's own verdict, checked independently
   of whatever was at that link, and the article report below it answers its
   own separate question.

   It is styled as a PEER of the credibility card, not as a banner above it:
   same card, same pill, same ring, same suppression treatment. The two are
   verdicts of the same kind about different subjects, and a reader comparing
   them should not have to translate between two presentations. What tells
   them apart is the heading and the emphasis below, never the vocabulary. */
#storyCard {
  padding: 30px 30px 26px;
  border-width: 2px; border-color: var(--border-strong);
  box-shadow: 0 1px 2px rgba(21, 38, 61, 0.05), 0 14px 40px rgba(21, 38, 61, 0.09);
}
#storyCard .indicator-heading { font-size: 12px; letter-spacing: 0.14em; color: var(--ink-soft); }
#storyCard .not-scored-box { padding: 18px 20px; gap: 7px; }
#storyCard .not-scored-label {
  font-family: var(--font-serif); font-size: 26px; font-weight: 600;
  letter-spacing: -0.01em; color: var(--ink); text-transform: none;
}

/* ── "The link you supplied is about something else" ── */
/* THE LOUDEST THING ON THE PAGE WHEN IT FIRES, and it earns that. Every
   finding below it is then about a different subject from the one the reader
   asked about, and the failure mode this whole change exists to end is a
   reader taking the linked article's verdict as their story's. It sits at the
   very top of the first card for that reason: it has to be read before
   anything it qualifies. */
.story-mismatch {
  background: var(--tone-severe-bg); border: 1px solid var(--tone-severe-fg);
  border-radius: 10px; padding: 16px 18px;
  display: flex; flex-direction: column; gap: 7px;
}
.story-mismatch-label {
  font-weight: 700; font-size: 15px; color: var(--tone-severe-fg); line-height: 1.4;
}
.story-mismatch-reason { font-size: 13.5px; color: var(--ink); line-height: 1.6; }

/* The engine's own summary sentence, rendered as written. Set at reading size
   because it is the finding in prose — it opens with what the link was, who
   else reports the story, and what the reporting actually says. */
.story-summary { font-size: 14.5px; color: var(--ink); line-height: 1.65; }

/* ── Who else reports this ── */
/* The line a newsroom acts on. "Nobody has denied this" and "somebody else has
   independently stood it up" are different findings, and before this card the
   page could not tell them apart at all. */
.story-corroboration {
  background: var(--bg-sunken); border: 1px solid var(--border); border-radius: 10px;
  padding: 14px 16px; display: flex; flex-direction: column; gap: 7px;
}
.story-corroboration-label { font-size: 14.5px; font-weight: 650; color: var(--ink); line-height: 1.5; }
.story-corroboration-lead { font-weight: 650; }
.story-corroboration-outlet { color: var(--ink); font-weight: 700; }
a.story-corroboration-outlet { color: var(--navy-light); text-decoration: underline; text-underline-offset: 2px; }
.story-corroboration-confirms { font-size: 13.5px; color: var(--ink-soft); line-height: 1.6; }

/* The pages folded into one outlet. Shown because "one outlet" otherwise looks
   like the engine found a single page and gave up — it found five here and
   judged them the same outlet's own pages or reports crediting it, which is a
   stronger finding than a bare count and is checkable by eye. */
.story-corroboration-folded { display: flex; flex-direction: column; gap: 6px; margin-top: 3px; }
.story-corroboration-folded-label {
  font-size: 10.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.12em; color: var(--muted);
}
.story-corroboration-list { list-style: none; display: flex; flex-direction: column; gap: 5px; }
.story-corroboration-page { border-left: 2px solid var(--border-strong); padding-left: 12px; }
.story-corroboration-page-link {
  font-size: 12.5px; color: var(--navy-light); line-height: 1.5;
  word-break: break-all; text-decoration: none;
}
.story-corroboration-page-link:hover { text-decoration: underline; }

/* The quiet half of the source-match finding: one line for a link that does
   carry the story, and one for a link that could not be checked. Deliberately
   understated — the loud version is the notice at the top of the card, and a
   link behaving as expected is not news. */
.story-source-line { font-size: 13px; color: var(--ink-soft); line-height: 1.55; }

/* ── The linked article, when it is about something else ── */
/* The card keeps its full weight — it is a complete and correct verdict — but
   it stops presenting itself as the answer. The heading says which article it
   is about; this softens the frame that made it read as the headline finding. */
#resultCard.linked-article { border-color: var(--border); border-width: 1px; }
#resultCard.linked-article .indicator-heading { color: var(--muted); }

@media print {
  /* 1. The light theme's tokens, whatever the screen was showing. Matched at
     the same weight as the dark rules above and placed after them, so these
     win for the system preference and the explicit choice alike. */
  :root:not(.theme-light), :root.theme-light {
    color-scheme: light;
    --bg: #FFFFFF;
    --bg-sunken: #F6F4EE;
    --card: #FFFFFF;
    --input: #FDFCF9;
    --border: #D9D2C3;
    --border-strong: #C4BAA4;
    --ink: #15263D;
    --ink-soft: #33445E;
    --muted: #5F6878;
    --quote-bg: #1E3A5E;
    --quote-ink: #F2F0E8;
    --ring-track: #E6DFCF;
    --tone-good-bg: #E7F2E9;   --tone-good-fg: #1F6B3A;   --tone-good-solid: #2E7D4F;
    --tone-severe-bg: #FAEAE5; --tone-severe-fg: #A83C28; --tone-severe-solid: #C0492F;
    --tone-neutral-bg: #ECEEF3; --tone-neutral-fg: #3E5170; --tone-neutral-solid: #48628A;
    --tone-info-bg: #F1EFE8;   --tone-info-fg: #5F6158;   --tone-info-solid: #98988C;
    --tone-error-bg: #FAEAE5;  --tone-error-fg: #A83C28;  --tone-error-solid: #C0492F;
    --amber-bg: #FAF2E1;
    --amber-fg: #8A5A00;
    --amber-border: #E7D3A6;
    --link: #1F5C8F;
    --mark-bg: #15263D;
    --shadow: none;
  }
  /* The score rings are drawn with backgrounds, which browsers drop from a
     print unless told otherwise. */
  * { print-color-adjust: exact; -webkit-print-color-adjust: exact; }
  body { background: #FFFFFF; font-size: 13px; }
  .page { max-width: none; padding: 0; gap: 14px; }
  .result-card, .load-bearing-card, .media-card, .intake-card,
  .abstention-card, .currency-card { box-shadow: none; }

  /* 2. Chrome and controls. */
  .page-header, .analyze-form, .loading, .score-pending, .error-box,
  .report-actions, .next-article,
  .theme-toggle, .btn-primary, .btn-secondary, .btn-text,
  .source-fulltext-toggle, .abstention-next,
  .chevron { display: none !important; }
  .collapsible-header { cursor: auto; padding: 12px 0 8px; }

  .print-only { display: block; }
  .report-print-head {
    border-bottom: 2px solid var(--ink); padding-bottom: 12px; margin-bottom: 4px;
    display: flex; flex-direction: column; gap: 5px;
  }
  .report-print-brand {
    font-size: 9pt; font-weight: 800; text-transform: uppercase;
    letter-spacing: 0.14em; color: var(--muted);
  }
  .report-print-title {
    font-family: var(--font-serif); font-size: 20pt; font-weight: 600;
    line-height: 1.2; color: var(--ink);
  }
  .report-print-source { font-size: 10pt; color: var(--ink-soft); overflow-wrap: anywhere; }
  .report-print-source:empty { display: none; }
  .report-print-date { font-size: 10pt; font-weight: 700; color: var(--ink); }
  .report-print-note { font-size: 9pt; color: var(--muted); max-width: 80ch; }

  /* 3. Every collapsible open, with the layouts the .open rules would have
     given them, and every source's full text shown. `.hidden` on a whole
     section still wins: that section had nothing in it. */
  .collapsible .collapsible-body { display: block; }
  .collapsible .criteria-list { display: grid; }
  .collapsible .justification-block,
  .collapsible .key-evidence-list,
  .collapsible .sources-list { display: flex; }
  .source-card-snippet.hidden { display: block !important; margin-top: 4px; }

  /* 4. Whole claims, whole sources. A block taller than a page still breaks —
     there is nowhere else for it to go — but nothing shorter will. */
  .load-bearing-item, .claim-head, .source-card, .criteria-item,
  .media-entry, .document-verdict, .claim-rollup, .abstention-card,
  .currency-card, .fidelity-body, .delta-box, .report-print-head,
  /* The story card's blocks, on the same rule: a corroboration finding split
     across a page break loses the outlet it belongs to, and the mismatch
     notice split from its reason is an accusation with no account of itself. */
  .story-mismatch, .story-corroboration {
    break-inside: avoid; page-break-inside: avoid;
  }
  .collapsible-header { break-after: avoid; page-break-after: avoid; }

  /* Links: visibly links on paper, where nothing else says so. */
  a { color: var(--link); text-decoration: underline; }

  /* Verdicts in greyscale: the word is already there; the outline keeps the
     badge a badge when the tinted ground does not print. */
  .pill, .tally-chip, .fidelity-pill { border: 1px solid currentColor; }
}
