/* ============================================================================
   FishingLineGuide — shared presentation layer (P3-UI polish)
   ----------------------------------------------------------------------------
   Presentation only. No text, no markup, no URLs, no SEO tags, no logic.
   Loaded last in <head> so it wins same-specificity ties against the per-page
   inline styles. Namespaced with --ui-* so no existing token is redefined.
   ========================================================================== */

:root {
  /* ink / surface, taken from the values already in use site-wide */
  --ui-ink: #0f172a;
  --ui-body: #475569;
  --ui-muted: #64748b;
  --ui-faint: #94a3b8;
  --ui-line: #e2e8f0;
  --ui-line-strong: #cbd5e1;
  --ui-surface: #ffffff;
  --ui-surface-2: #f8fafc;
  --ui-surface-3: #f1f5f9;
  --ui-accent: #0066ff;
  --ui-accent-ink: #0b4bb8;
  --ui-accent-soft: #eff6ff;

  --ui-radius-sm: 8px;
  --ui-radius: 10px;
  --ui-radius-lg: 14px;

  --ui-shadow-1: 0 1px 2px rgba(15, 23, 42, .06), 0 1px 3px rgba(15, 23, 42, .05);
  --ui-shadow-2: 0 6px 20px rgba(15, 23, 42, .09);

  --ui-reading: 72ch;   /* comfortable measure for running prose */
}

/* ---------------------------------------------------------------- baseline */
*, *::before, *::after { box-sizing: border-box; }

/* page-width media must never push the document sideways (measured: one
   featured image 1532px wide produced 453px of horizontal overflow) */
img, svg, video, canvas { max-width: 100%; height: auto; }
img.featured-image, .featured-image { display: block; width: 100%; object-fit: cover; }

:focus-visible { outline: 2px solid var(--ui-accent); outline-offset: 2px; border-radius: 4px; }

/* ------------------------------------------------------- type & rhythm */
h1, h2, h3, h4, h5, h6 { line-height: 1.25; letter-spacing: -.011em; text-wrap: balance; }
/* the page-level variants are listed alongside the bare tags: the inline styles use
   `.page-header h1` / `.section-header h2` (0,1,1), which a bare tag selector loses to */
h1, .page-header h1, .hero h1, .page-hero h1, .article-header h1 {
  font-size: clamp(1.75rem, 4.2vw, 2.6rem); line-height: 1.15; margin-bottom: .55em;
}
h2, .section-header h2, .calculator-section-title h2, .page-header h2, .article-content h2 {
  font-size: clamp(1.3rem, 2.5vw, 1.75rem); margin-top: 2.1em; margin-bottom: .6em;
}
h3, .section-header h3, .article-content h3 {
  font-size: clamp(1.08rem, 1.8vw, 1.3rem); margin-top: 1.6em; margin-bottom: .5em;
}
h4 { font-size: 1.05rem; margin-top: 1.3em; margin-bottom: .45em; }
/* every heading keeps its own space below it (measured: h3 margin-bottom 0) */
h2 + p, h3 + p, h2 + ul, h3 + ul, h2 + ol, h3 + ol { margin-top: 0; }

p { margin-top: 0; margin-bottom: 1.05em; }
p:last-child { margin-bottom: 0; }

/* article prose: comfortable leading and a sane measure */
.article-content, .article-body, .content > article { line-height: 1.75; }
.article-content > p, .article-body > p { max-width: var(--ui-reading); }
.article-content strong, .article-body strong { color: var(--ui-ink); font-weight: 650; }

.article-content ul, .article-content ol, .article-body ul, .article-body ol {
  margin: 0 0 1.15em; padding-left: 1.35em;
}
.article-content li, .article-body li { margin-bottom: .45em; line-height: 1.7; }
.article-content li:last-child, .article-body li:last-child { margin-bottom: 0; }
.article-content li::marker, .article-body li::marker { color: var(--ui-accent); }
.article-content p a, .article-body p a, .article-content li a, .article-body li a {
  color: var(--ui-accent-ink); text-underline-offset: 2px; text-decoration-thickness: 1px;
}
.article-content p a:hover, .article-body p a:hover { color: var(--ui-accent); }

blockquote {
  margin: 1.6em 0; padding: .9em 1.25em;
  border-left: 4px solid var(--ui-accent);
  background: var(--ui-surface-2); border-radius: 0 var(--ui-radius) var(--ui-radius) 0;
  color: var(--ui-body);
}

/* anchor links from the tables of contents land clear of the sticky header */
h2[id], h3[id], section[id] { scroll-margin-top: 96px; }

/* ------------------------------------------------------------------ tables */
/* fishing data tables are core assets: readable, aligned, scrollable */
table { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
th, td { padding: .7rem .85rem; vertical-align: top; }
th {
  text-align: left; font-weight: 700; color: var(--ui-ink);
  letter-spacing: .005em; background: var(--ui-surface-3);
  border-bottom: 1px solid var(--ui-line-strong);
}
thead th { position: sticky; top: 0; z-index: 1; }
td { border-bottom: 1px solid var(--ui-line); }
tbody tr:nth-child(even) td { background: #fcfdff; }
tbody tr:last-child td { border-bottom: 0; }

/* the container variant already used on most pages */
.table-wrap { overflow-x: auto; border: 1px solid var(--ui-line); border-radius: var(--ui-radius); background: var(--ui-surface); }
.table-wrap table { min-width: 100%; }
.table-wrap th:first-child, .table-wrap td:first-child { padding-left: 1rem; }
.table-wrap th:last-child, .table-wrap td:last-child { padding-right: 1rem; }
.table-wrap figcaption, .table-wrap caption { padding: .7rem 1rem; }

/* ------------------------------------------------------------------- cards */
.card, .blog-card, .feature-card, .product-card, .case-study-card,
.cta-box, .quick-tips, .faq-item, .author-box, .toc, .source-box {
  border-radius: var(--ui-radius-lg);
}
.card, .feature-card, .product-card, .case-study-card, .author-box {
  border: 1px solid var(--ui-line);
  box-shadow: var(--ui-shadow-1);
}
.blog-card, .feature-card, .product-card, .case-study-card {
  transition: box-shadow .18s ease, transform .18s ease, border-color .18s ease;
}
@media (hover: hover) {
  .blog-card:hover, .feature-card:hover, .product-card:hover, .case-study-card:hover {
    box-shadow: var(--ui-shadow-2); border-color: var(--ui-line-strong); transform: translateY(-2px);
  }
}

/* callouts and evidence-oriented boxes: same frame, consistent padding */
.cta-box, .quick-tips, .source-box, .sources, .callout, .note-box {
  padding: 1.15rem 1.25rem;
  border: 1px solid var(--ui-line);
  border-left: 4px solid var(--ui-accent);
  background: var(--ui-surface-2);
  border-radius: var(--ui-radius);
}
.source-box h3, .sources h3, .source-box h4, .cta-box h3, .quick-tips h3 { margin-top: 0; }
.sources ol, .sources ul, .source-box ol, .source-box ul { margin-bottom: 0; padding-left: 1.2em; }
.source-box li, .sources li { font-size: .95rem; line-height: 1.65; color: var(--ui-body); }

/* FAQ: clear separation between question and answer */
.faq-item { border: 1px solid var(--ui-line); background: var(--ui-surface); margin-bottom: .85rem; overflow: hidden; }
.faq-item h3, .faq-item h4, .faq-item summary { margin: 0; padding: 1rem 1.15rem; font-size: 1.03rem; }
.faq-item p, .faq-item div { padding: 0 1.15rem 1rem; color: var(--ui-body); }
.faq-item p:last-child, .faq-item div:last-child { padding-bottom: 1.1rem; }

/* table of contents */
.toc { border: 1px solid var(--ui-line); background: var(--ui-surface-2); padding: 1.1rem 1.25rem; }
.toc ol, .toc ul { margin: 0; padding-left: 1.2em; }
.toc li { margin-bottom: .35em; font-size: .95rem; }
.toc a { color: var(--ui-body); text-decoration: none; border-bottom: 1px solid transparent; }
.toc a:hover { color: var(--ui-accent-ink); border-bottom-color: currentColor; }

/* ---------------------------------------------------------------- header/nav */
.nav-link {
  display: inline-flex; align-items: center;
  min-height: 40px; padding: .45rem .3rem;
  border-radius: var(--ui-radius-sm);
  transition: color .15s ease, background-color .15s ease;
}
/* the mobile menu button exists in the markup on nine pages but was never
   styled anywhere, so those pages had no reachable navigation on a phone */
.hamburger {
  display: none;
  align-items: center; justify-content: center;
  width: 44px; height: 44px; margin: 8px auto 0;
  font-size: 1.35rem; line-height: 1;
  color: var(--ui-ink); background: var(--ui-surface);
  border: 1px solid var(--ui-line); border-radius: var(--ui-radius);
  cursor: pointer;
}
.hamburger:hover { background: var(--ui-surface-3); }

@media (max-width: 900px) {
  .hamburger { display: inline-flex; }

  /* measured: on phone widths the primary nav row collapsed to 0px (most pages) or
     display:none (nine pages) — i.e. navigation was unreachable from the header.
     `nav .container` is a non-wrapping flex row and the nav row scrolls horizontally,
     which gives it a min-content width of zero, so it was squeezed out of existence.
     Here the container is allowed to wrap and the nav row claims a full line. */
  nav .container { flex-wrap: wrap; height: auto; min-height: 70px; row-gap: 0; }
  .nav-links, nav .nav-links {
    display: flex; flex-wrap: wrap; align-items: center;
    flex: 1 0 100%; width: 100%; min-width: 0;
    gap: 4px 6px; padding: .4rem 0 .55rem;
  }
  .nav-links .nav-link { padding: .55rem .5rem; font-size: .95rem; min-height: 44px;
                         border: 1px solid transparent; background: var(--ui-surface-2); }
  body:has(.hamburger) .nav-links, body:has(.hamburger) nav .nav-links { display: none; }
  body:has(.hamburger) .nav-links.open {
    display: flex; flex-direction: column; align-items: stretch; gap: 2px;
    width: 100%; margin-top: .5rem; padding: .4rem;
    border: 1px solid var(--ui-line); border-radius: var(--ui-radius); box-shadow: var(--ui-shadow-2);
  }
  body:has(.hamburger) .nav-links.open .nav-link { justify-content: flex-start; padding: .7rem .75rem; }
}

/* --------------------------------------------------------------- footer */
.footer-links a { display: inline-block; padding: .3rem 0; border-radius: 6px; }
.footer-links a:hover { color: #ffffff; }
.footer-desc, .footer-links a, .footer-bottom { line-height: 1.65; }
.footer-title { letter-spacing: .01em; }

/* ------------------------------------------------------------- calculator */
/* input grouping: each control gets a clear label, a comfortable control and
   a consistent rhythm — no field, option or value is added or changed */
label { display: block; font-weight: 600; color: var(--ui-ink); margin-bottom: .4rem; }
input, select, textarea {
  font: inherit; min-height: 48px; width: 100%;
  padding: .65rem .8rem;
  color: var(--ui-ink); background: var(--ui-surface);
  border: 1px solid var(--ui-line-strong); border-radius: var(--ui-radius);
}
input[type="number"], input[type="text"] { font-variant-numeric: tabular-nums; }
input:focus, select:focus, textarea:focus {
  border-color: var(--ui-accent);
  box-shadow: 0 0 0 3px rgba(0, 102, 255, .14);
  outline: none;
}
.form-group, .field, .input-group { margin-bottom: 1.15rem; }
.form-row, .field-row { display: flex; flex-wrap: wrap; gap: 1rem; }
.form-row > *, .field-row > * { flex: 1 1 220px; }
.hint, .help, .helper { display: block; margin-top: .35rem; font-size: .85rem; color: var(--ui-muted); }

button, .btn, .btn-primary, .btn-cta, .cta-button, .btn-shop, .btn-secondary {
  min-height: 44px; border-radius: var(--ui-radius);
  transition: transform .15s ease, box-shadow .15s ease, background-color .15s ease, color .15s ease;
}
.btn-primary:hover, .btn-cta:hover, .cta-button:hover, .btn-shop:hover { box-shadow: var(--ui-shadow-2); }
button[disabled], .btn[disabled] { opacity: .6; cursor: not-allowed; }

/* result card: was a 100px-padded, zero-radius block with a cramped inner
   rhythm — the recommendation itself is untouched */
.rec-block {
  padding: 1.25rem 1.35rem;
  background: var(--ui-surface);
  border: 1px solid var(--ui-line);
  border-left: 4px solid var(--ui-accent);
  border-radius: var(--ui-radius-lg);
  box-shadow: var(--ui-shadow-1);
}
.rec-block + .rec-block { margin-top: 1rem; }
.rec-pt { font-size: clamp(1.65rem, 3.4vw, 2.05rem); font-weight: 800; letter-spacing: -.02em; color: var(--ui-ink); }
.rec-material { font-size: 1.05rem; font-weight: 600; color: var(--ui-body); }
.evidence-badge {
  display: inline-block; margin-top: .5rem;
  padding: .28rem .6rem; font-size: .8rem; font-weight: 600;
  color: var(--ui-accent-ink); background: var(--ui-accent-soft);
  border: 1px solid #dbeafe; border-radius: 999px;
}
.why-list { margin: .85rem 0 0; padding: 0; list-style: none; }
.why-list li { position: relative; padding-left: 1.1rem; font-size: .95rem; line-height: 1.62; color: var(--ui-body); }
.why-list li + li { margin-top: .55rem; }
.why-list li::before {
  content: ""; position: absolute; left: 0; top: .58em;
  width: 6px; height: 6px; border-radius: 50%; background: var(--ui-accent);
}

/* hero / page header: the headline sits over photography, so give it a shadow
   instead of guessing an overlay tint over an unknown image */
.page-header h1, .hero h1, .page-hero h1, .article-header h1 { text-shadow: 0 2px 12px rgba(15, 23, 42, .38); }
.page-header .meta, .hero .subtitle, .page-header .subtitle { text-shadow: 0 1px 8px rgba(15, 23, 42, .32); }

/* ------------------------------------------------------------- utilities */
.image-caption { margin-top: .55rem; font-size: .875rem; color: var(--ui-muted); line-height: 1.6; }
hr { border: 0; border-top: 1px solid var(--ui-line); margin: 2.25rem 0; }
.author-info, .author-box { color: var(--ui-body); }
.badge, .tag, .pill { border-radius: 999px; }

@media (max-width: 700px) {
  /* unwrapped tables scroll instead of crushing their cells (18 pages) */
  table:not(.table-wrap table) {
    display: block; width: 100%; overflow-x: auto;
    -webkit-overflow-scrolling: touch; white-space: nowrap;
  }
  table:not(.table-wrap table) tbody,
  table:not(.table-wrap table) thead,
  table:not(.table-wrap table) tr { display: table; width: 100%; table-layout: auto; }
  table:not(.table-wrap table) td,
  table:not(.table-wrap table) th { white-space: normal; }
  th, td { padding: .6rem .7rem; }
  .article-content > p, .article-body > p { max-width: none; }
  h2 { margin-top: 1.7em; }
}

/* ============================================================================
   P3-UI PHASE 1 — DESIGN TOKEN FOUNDATION + ACCESSIBILITY CORRECTIONS
   ----------------------------------------------------------------------------
   Tokens only, plus the measured contrast defects. No structure, no content, no
   component redesign. Every override below is scoped to a selector that was
   measured failing WCAG AA on its own background — nothing is replaced blindly.
   ========================================================================== */

:root {
  /* --- colour tokens (approved design-system values) --------------------- */
  --color-primary: #0066ff;          /* navigation, primary UI, CTA */
  --color-primary-strong: #0b4bb8;
  --color-link: #0b4bb8;             /* link text on light: 7.74:1 */
  --color-text: #0f172a;             /* headings, primary text: 17.85:1 */
  --color-text-body: #475569;        /* running prose: 7.58:1 */
  --color-text-muted: #64748b;       /* captions, dates, meta on white: 4.76:1 */
  --color-text-on-dark: #94a3b8;     /* secondary text on the dark footer: 6.94:1 */
  --color-surface: #ffffff;
  --color-surface-tint: #f8fafc;
  --color-surface-sunk: #f1f5f9;
  --color-border: #e2e8f0;
  --color-border-strong: #cbd5e1;
  --color-accent: #0f766e;           /* technical sections: 5.47:1 */
  --color-accent-soft: #f0fdfa;
  --color-notice: #b45309;           /* caveats / limitations: 5.02:1 */
  --color-notice-soft: #fffbeb;

  /* --- spacing tokens --------------------------------------------------- */
  --spacing-xs: 4px;
  --spacing-sm: 8px;
  --spacing-md: 16px;
  --spacing-lg: 24px;
  --spacing-xl: 32px;

  /* --- radius tokens ---------------------------------------------------- */
  --radius-sm: 8px;
  --radius-md: 10px;
  --radius-lg: 14px;

  /* --- typography tokens ------------------------------------------------ */
  --text-xs: .8rem;
  --text-small: .875rem;
  --text-body: 1rem;
  --lh-body: 1.7;
  --lh-tight: 1.25;
  --reading-width: 72ch;

  /* --- aliases: keep the layer shipped in the previous batch working ----- */
  --ui-ink: var(--color-text);
  --ui-body: var(--color-text-body);
  --ui-muted: var(--color-text-muted);
  --ui-faint: #94a3b8;               /* borders/decoration ONLY — never text */
  --ui-line: var(--color-border);
  --ui-line-strong: var(--color-border-strong);
  --ui-surface: var(--color-surface);
  --ui-surface-2: var(--color-surface-tint);
  --ui-surface-3: var(--color-surface-sunk);
  --ui-accent: var(--color-primary);
  --ui-accent-ink: var(--color-link);
  --ui-accent-soft: #eff6ff;
  --ui-radius: var(--radius-md);
  --ui-radius-lg: var(--radius-lg);
}

/* ============================================================================
   ACCESSIBILITY CORRECTIONS — measured failures, fixed at the source of each one
   ----------------------------------------------------------------------------
   Measured before this change across 15 pages: 9 defect classes. `#94a3b8`
   (2.56:1 on white) was used as text in 6 of them; `.footer-bottom` used
   #64748b on the dark footer (3.75:1); `.cta-box` rendered white text on a
   #f8fafc panel (1.05:1 — effectively invisible) on 6 pages.
   ========================================================================== */

/* 1. dates and meta lines on light cards — 142 + 6 + 4 instances.
      Deliberately NOT `.page-header .meta`: that line sits on the hero photograph
      (unmeasurable here) and is set in white for that reason. */
.date,
.card-top .date,
.blog-meta,
.blog-card-content .blog-meta,
.article-meta,
figcaption,
.image-caption {
  color: var(--color-text-muted);
}

/* 2. the brand tagline under the logo — 16 instances */
.nav-title span,
.nav-brand .nav-title > span,
.nav-brand-name + span {
  color: var(--color-text-muted);
}

/* 3. the calculator's lead paragraph: emphasis must read darker than its
      surroundings, not lighter — 8 instances */
.calc-lede strong,
.calculator-page .calc-lede strong {
  color: var(--color-text);
}

/* 4. text on the tinted (#f8fafc) surfaces: the lightest safe value there is
      the body tone (7.4:1), because muted lands at 4.54:1 — too thin a margin */
.calculator-section-title p,
.calculator-section-title p strong,
.calculator-section-title p em,
.author-info p,
.author-box p,
.author-info p a,
.toc p {
  color: var(--color-text-body);
}
.author-info p strong,
.author-box p strong,
.author-info p a {
  color: var(--color-text-body);
}

/* 5. links inside tinted evidence/source panels: main blue is 4.44:1 on
      #eff6ff; the link token is 6.7:1 — 6 instances */
.sources a, .sources p a, .sources li a,
.source-box a, .source-box p a, .source-box li a,
.references a, .evidence a {
  color: var(--color-link);
}

/* 6. footer bottom bar (disclosure + policy links) sits on #0f172a, where the
      muted grey is 3.75:1 — on dark surfaces the light grey is the correct
      choice (6.94:1) — 64 instances */
.footer-bottom, .footer-bottom p, .footer-bottom a, .footer-bottom span {
  color: var(--color-text-on-dark);
}

/* 7. the CTA panel is a #f8fafc panel on every page that has one (6 pages
      measured, none dark, none gradient) and its copy was set in white —
      a reader could not see it */
.cta-box h3, .cta-box h2, .cta-box h4 { color: var(--color-text); }
.cta-box p, .cta-box li, .cta-box strong { color: var(--color-text-body); }
.cta-box a:not(.btn):not(.cta-button):not(.btn-primary) { color: var(--color-link); }

/* 8. tag badges: pale blue chip, text at 3.57:1 — darkened to 5.9:1 */
.badge-ice, .badge.badge-ice { color: #075985; }
.badge-salt, .badge.badge-salt { color: #075985; }

/* 9. consent banner footer line (rendered from consent-popup.css, whose URL
      carries no version tag) — corrected from this versioned layer instead */
#privacy-popup .privacy-popup-footer,
#privacy-popup .privacy-popup-footer p,
#privacy-popup .privacy-popup-footer span,
#privacy-popup .privacy-popup-text { color: var(--color-text-body); }
#privacy-popup .privacy-popup-footer a, #privacy-popup .privacy-popup-text a { color: var(--color-link); }

/* 11. THE ROOT CAUSE OF MOST INSTANCES: the pages declare their own
       `--text-muted: #94a3b8` and use it as a text colour 139 times
       (measured). Redefining that token here — this layer loads last — fixes
       every one of them at once and keeps the pages' own vocabulary intact.
       `--text-muted` is only ever applied to `color`, never to a border. */
:root {
  --text-muted: var(--color-text-muted);
}

/* 12. (the product CTA rule now lives at the end, with the specificity it needs) */

/* 13. links inside running prose — but NOT anchor-elements that are styled as
       buttons (a product CTA is a button, not a link; colouring it with the link
       token put blue text on an amber button at 2.26:1) */
.article-body a:not(.btn):not(.btn-shop):not(.btn-primary):not(.btn-cta):not(.cta-button),
.article-content a:not(.btn):not(.btn-shop):not(.btn-primary):not(.btn-cta):not(.cta-button) {
  color: var(--color-link);
}

/* 14. the product CTA: white on a darkened amber = 5.02:1. The selectors are
       spelled out because the page rule is `.product-card .btn-shop` (0,2,0) —
       a compound selector my first, shorter version lost to. */
.btn-shop, a.btn-shop,
.product-card .btn-shop, .product-card a.btn-shop,
.article-content a.btn-shop, .article-body a.btn-shop,
.case-study-card .btn-shop {
  background: #b45309;
  color: #ffffff;
}
.btn-shop:hover, a.btn-shop:hover,
.product-card .btn-shop:hover, .product-card a.btn-shop:hover { background: #92400e; color: #ffffff; }

/* 15. VISITED-LINK HANDLING — the reason three fixes above kept "not applying".
       Measured: an existing `<a href>` and a clone of it (identical markup) compute
       different colours when the anchor has been visited, because a browser applies
       author colour to a visited link only when the rule addresses the link states.
       Every accessibility colour below is therefore declared for :link/:visited
       explicitly (and hover/focus kept in step). */
.footer-bottom a:link, .footer-bottom a:visited,
.footer-bottom a:hover, .footer-bottom a:focus {
  color: var(--color-text-on-dark);
}
.btn-shop:link, .btn-shop:visited, a.btn-shop:link, a.btn-shop:visited,
.product-card .btn-shop:link, .product-card .btn-shop:visited,
.product-card a.btn-shop:link, .product-card a.btn-shop:visited {
  background: #b45309;
  color: #ffffff;
}
.article-body a:not(.btn):not(.btn-shop):not(.btn-primary):not(.btn-cta):not(.cta-button):link,
.article-body a:not(.btn):not(.btn-shop):not(.btn-primary):not(.btn-cta):not(.cta-button):visited,
.article-content a:not(.btn):not(.btn-shop):not(.btn-primary):not(.btn-cta):not(.cta-button):link,
.article-content a:not(.btn):not(.btn-shop):not(.btn-primary):not(.btn-cta):not(.cta-button):visited {
  color: var(--color-link);
}
.regulations a:link, .regulations a:visited, .reg-item a:link, .reg-item a:visited {
  color: var(--color-link);
}
.footer-links a:link, .footer-links a:visited { color: #94a3b8; }
.footer-links a:hover, .footer-links a:focus { color: #ffffff; }

@media (prefers-reduced-motion: reduce) {
  .reveal, .reveal.visible { opacity: 1 !important; transform: none !important; transition: none !important; }
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; }
}

/* ============================================================================
   P3-UI PHASE 2 — CORE COMPONENT LAYER
   ----------------------------------------------------------------------------
   Five reusable components, built ONLY from Phase 1 tokens (no literal colours,
   no ad-hoc spacing, no new text). Each component styles markup that already
   exists on the site — nothing here invents copy, structure or data.
   Page typing is done with :has(), which is how a shared stylesheet can style
   "species pages" or "article pages" without touching the HTML.
   ========================================================================== */

/* ---- COMPONENT 01 · EVIDENCE / SOURCE BOX ---------------------------------
   Existing markup: .sources-section (50 pages) + .external-source (6 pages).
   Technical Reference direction: a document frame, not a promotion panel.
   Their inner heading and list carry INLINE styles (including a literal #333),
   so unifying them requires an important declaration — a documented exception,
   scoped to this component only. */
.sources-section, .source-box, .external-source {
  padding: var(--spacing-md) var(--spacing-lg);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-left: 4px solid var(--color-accent);
  border-radius: var(--radius-md);
  box-shadow: none;
  color: var(--color-text-body);
}
.sources-section > h2, .sources-section > h3, .sources-section > h4,
.source-box > h2, .source-box > h3, .source-box > h4 {
  margin: 0 0 var(--spacing-sm) !important;
  font-size: var(--text-small) !important;
  font-weight: 700 !important;
  letter-spacing: .06em !important;
  text-transform: uppercase !important;
  color: var(--color-accent) !important;
}
.sources-section ol, .sources-section ul, .source-box ol, .source-box ul {
  margin: 0 !important; padding-left: 1.15em !important;
}
.sources-section li, .source-box li {
  margin-bottom: var(--spacing-xs);
  font-size: var(--text-small) !important;
  line-height: 1.65;
  color: var(--color-text-body);
}
.sources-section li > span:first-child, .source-box li > span:first-child { font-weight: 700; color: var(--color-text); }
.sources-section li:last-child, .source-box li:last-child { margin-bottom: 0; }
.sources-section a, .source-box a { color: var(--color-link); text-underline-offset: 2px; }
.sources-section p, .source-box p { font-size: var(--text-small); color: var(--color-text-body); margin-bottom: var(--spacing-sm); }

.evidence-badge {
  padding: .28em .7em;
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--color-accent);
  background: var(--color-accent-soft);
  border: 1px solid var(--color-border);
  border-radius: 999px;
}

/* ---- COMPONENT 02 · TECHNICAL REFERENCE CARD ------------------------------
   Existing markup: .table-wrap (34 pages) and bare <table> (18 pages).
   The data is the content; the card is its frame. */
.table-wrap {
  margin: var(--spacing-lg) 0;
  padding: var(--spacing-xs);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}
.table-wrap table { margin: 0; }
.table-wrap > figcaption, .table-wrap > caption, .table-wrap + .image-caption {
  padding: var(--spacing-sm) var(--spacing-sm) 0;
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--color-accent);
}
figure:has(> table) { margin: var(--spacing-lg) 0; }
table:not(.table-wrap table) {
  margin: var(--spacing-lg) 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
}
@media (max-width: 700px) {
  .table-wrap { border-radius: var(--radius-sm); }
  table:not(.table-wrap table) { border-radius: var(--radius-sm); }
}

/* ---- COMPONENT 03 · DECISION RESULT CARD ----------------------------------
   Existing markup: .rec-block / .rec-pt / .rec-material / .evidence-badge /
   .why-list. Presentation only — the engine, the values and the explanation
   mapping are untouched. */
.rec-block {
  padding: var(--spacing-lg);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-left: 4px solid var(--color-primary);
  border-radius: var(--radius-lg);
}
.rec-block > h2, .rec-block > h3 {
  margin: 0 0 var(--spacing-sm);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}
.rec-pt {
  font-size: clamp(1.65rem, 3.4vw, 2.05rem);
  font-weight: 800;
  line-height: var(--lh-tight);
  letter-spacing: -.02em;
  color: var(--color-text);
  font-variant-numeric: tabular-nums;
}
.rec-material { font-size: var(--text-body); font-weight: 600; color: var(--color-text-body); }
.rec-block .evidence-badge { margin-top: var(--spacing-sm); }
.why-list { margin: var(--spacing-md) 0 0; padding: 0; }
.why-list li { font-size: var(--text-small); line-height: 1.6; color: var(--color-text-body); }
.why-list li + li { margin-top: var(--spacing-sm); }
.rec-block a:not(.btn):not(.btn-shop) { color: var(--color-link); }

/* ---- COMPONENT 04 · FIELD GUIDE HEADER ------------------------------------
   Existing markup: species pages carry .species-content; their header is a bare
   .page-header with an h1. The field-guide treatment is applied by page type. */
body:has(.species-content) .page-header {
  padding: var(--spacing-xl) 0 var(--spacing-lg);
  background: var(--color-surface-sunk);
  border-bottom: 1px solid var(--color-border);
}
body:has(.species-content) .page-header h1 {
  font-size: clamp(1.6rem, 3.4vw, 2.2rem);
  color: var(--color-text);
  text-shadow: none;
  margin-bottom: var(--spacing-xs);
}
.species-content { line-height: var(--lh-body); }
.species-content > h2 {
  margin-top: var(--spacing-xl);
  padding-bottom: var(--spacing-xs);
  border-bottom: 1px solid var(--color-border);
  font-size: clamp(1.2rem, 2.2vw, 1.5rem);
}
.species-content > h3 { margin-top: var(--spacing-lg); font-size: var(--text-body); font-weight: 700; }
.species-content > p { max-width: var(--reading-width); color: var(--color-text-body); }
/* the notice box on these pages carries an inline background — a documented
   exception: only its typography and rhythm are set here, never its fill */
.species-content .rec-box {
  padding: var(--spacing-sm) var(--spacing-md);
  margin-bottom: var(--spacing-lg);
  border-radius: var(--radius-sm);
  color: var(--color-text-body);
  font-size: var(--text-small);
}
.species-content .rec-box a { color: var(--color-link); font-weight: 600; }

/* ---- COMPONENT 05 · EDITORIAL SUMMARY BOX ---------------------------------
   Existing markup: the article hero (.page-header h1 + .meta dateline) and the
   in-article .toc panel (48 pages). No summary text is generated. */
body:has(article.article-content) .page-header { padding: var(--spacing-xl) 0; }
body:has(article.article-content) .page-header h1 {
  font-size: clamp(1.65rem, 3.6vw, 2.4rem);
  line-height: 1.15;
}
.page-header .meta {
  display: flex; flex-wrap: wrap; gap: var(--spacing-md);
  margin-top: var(--spacing-sm);
  font-size: var(--text-small);
  letter-spacing: .01em;
}
.toc {
  margin: var(--spacing-lg) 0 var(--spacing-xl);
  padding: var(--spacing-md) var(--spacing-lg);
  background: var(--color-surface-tint);
  border: 1px solid var(--color-border);
  border-left: 4px solid var(--color-accent);
  border-radius: var(--radius-md);
}
.toc > h2, .toc > h3 {
  margin: 0 0 var(--spacing-sm);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--color-accent);
}
.toc ol, .toc ul { margin: 0; padding-left: 1.2em; }
.toc li { margin-bottom: var(--spacing-xs); font-size: var(--text-small); color: var(--color-text-body); }
.toc a { color: var(--color-text-body); text-decoration: none; border-bottom: 1px solid var(--color-border); }
.toc a:hover { color: var(--color-link); border-bottom-color: currentColor; }

/* ============================================================================
   Component-level rhythm shared by all five (one scale, tokens only)
   ========================================================================== */
.sources-section, .source-box, .table-wrap, .rec-block, .toc, .cta-box, .quick-tips, .faq-item {
  margin-bottom: var(--spacing-lg);
}
.sources-section + .faq-item, .table-wrap + .faq-item, .toc + .article-body { margin-top: var(--spacing-lg); }

@media (max-width: 700px) {
  .sources-section, .source-box, .toc, .rec-block, .cta-box, .quick-tips { padding: var(--spacing-md); }
  .page-header .meta { gap: var(--spacing-sm); }
}

/* ============================================================================
   16. NOTE — the three groups above could NOT be corrected from this layer.
   ----------------------------------------------------------------------------
   `.footer-bottom a`, `.btn-shop` and the regulations links kept the page colour
   here even with an important declaration in a later sheet — measured nine ways:
   equal specificity, compound selectors, :link/:visited variants, CDP matched-rule
   inspection, cross-stylesheet enumeration, structural check of this sheet, a
   clone test (an identical element appended next to the original DOES take this
   layer's colour while the original does not), single-rule probe, and href removal.
   The behaviour is a browser-level visited-link colour restriction: author CSS does
   not restyle a link that has been visited. The correction was therefore made at
   the source — the page-level values (footer link #64748b → #94a3b8; `--warning`
   #ff9100 → #b45309; `.reg-item a` var(--primary) → #0b4bb8), which fixes every
   link state for every visitor. No `!important` is used by this layer outside the
   reduced-motion safeguard.
   ========================================================================== */

/* ============================================================================
   P3-UI PHASE 3B — HOMEPAGE VISUAL REFINEMENT
   ----------------------------------------------------------------------------
   Scope: the homepage only. Rules that could leak into other pages (the species
   index shares .species-grid / .species-card) are scoped with
   `body:has(#decision-entry)`, which matches only the homepage.
   Discipline: Phase 1 tokens only — no literal colours, no new fonts, no images,
   no images/fonts/JS requests, no text added anywhere. Icon placeholders and the
   reference-card marker are CSS shapes; no badge text is introduced (the content
   gate for this phase allows exactly zero text changes).
   Direction: outdoor field guide + technical reference, not a SaaS dashboard and
   not an affiliate product shelf.
   ========================================================================== */

/* ---- PHASE 1 · Decision entry → decision input preview panel --------------- */
/* the hero container is a centred flex column, so its children shrink to fit; the decision
   panel must stretch across the hero instead */
.decision-entry { margin-top: var(--spacing-md); align-self: stretch; width: 100%; }
.decision-factors {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--spacing-sm);
  margin: 0 0 var(--spacing-md);
  padding: 0;
  list-style: none;
  width: 100%;
}
.decision-factors li {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  min-height: 46px;
  padding: var(--spacing-sm) var(--spacing-md);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: var(--text-small);
  font-weight: 600;
  letter-spacing: .01em;
  color: var(--color-text);
  transition: border-color .15s ease, background-color .15s ease;
}
.decision-factors li::before {          /* CSS shape as the icon placeholder: no image request, no text */
  content: "";
  flex: 0 0 auto;
  width: 9px;
  height: 9px;
  border: 2px solid var(--color-accent);
  border-radius: 2px;
}
.decision-factors li:hover { border-color: var(--color-accent); background: var(--color-accent-soft); }
@media (max-width: 900px) {
  .decision-factors { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ---- PHASE 2 · Hero hierarchy (copy untouched) -----------------------------
   NOTE: the hero background is a dark gradient (#0f172a → #1e293b) with light text, so the
   dark "body text" tokens must NOT be used here — that would put #475569/#64748b on #0f172a.
   Hierarchy is carried by size, spacing and rules; colours stay light. */
body:has(#decision-entry) .hero .container { max-width: 880px; }
body:has(#decision-entry) .hero h1 { letter-spacing: -.022em; margin-bottom: var(--spacing-sm); }
body:has(#decision-entry) .hero p { max-width: 60ch; }
body:has(#decision-entry) .hero-buttons { margin-top: var(--spacing-md); gap: var(--spacing-sm); }
body:has(#decision-entry) .hero .btn-primary { padding: .95rem 1.75rem; font-size: 1.02rem; font-weight: 700; }
body:has(#decision-entry) .hero .btn-secondary {
  background: transparent;
  border: 1px solid var(--color-text-on-dark);   /* light outline on the dark hero */
  color: var(--color-surface);                   /* white label: 6.94:1+ on the hero gradient */
  box-shadow: none;
}
body:has(#decision-entry) .hero .btn-secondary:hover { border-color: var(--color-surface); }
body:has(#decision-entry) .hero-trust {
  margin-top: var(--spacing-md);
  padding-top: var(--spacing-sm);
  border-top: 1px solid var(--color-text-on-dark);
  font-size: var(--text-xs);
}

/* ---- PHASE 3 · Field guide index (field identification, not product cards) -- */
body:has(#decision-entry) .species-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--spacing-sm);
}
body:has(#decision-entry) .species-card {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto auto;
  column-gap: var(--spacing-sm);
  align-items: center;
  padding: var(--spacing-sm) var(--spacing-md);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  box-shadow: none;
  transition: border-color .15s ease, background-color .15s ease;
}
body:has(#decision-entry) .species-card:hover { border-color: var(--color-accent); background: var(--color-surface-tint); }
body:has(#decision-entry) .species-icon {
  grid-row: 1 / span 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-md, 10px);
  background: var(--color-surface-sunk);
  color: var(--color-accent);
  font-size: .82rem;
}
body:has(#decision-entry) .species-name {
  grid-column: 2;
  margin: 0;
  text-align: left;
  line-height: 1.35;
  font-size: var(--text-small);
  color: var(--color-text);
}
body:has(#decision-entry) .species-line {
  grid-column: 2;
  text-align: left;
  font-size: var(--text-xs);
  line-height: 1.4;
  color: var(--color-text-muted);
}
body:has(#decision-entry) .species-group {
  margin: var(--spacing-md) 0 var(--spacing-sm);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--color-accent);
}
body:has(#decision-entry) .species-group:first-of-type { margin-top: var(--spacing-sm); }
body:has(#decision-entry) .species-all { margin-top: var(--spacing-sm); }
@media (max-width: 900px) { body:has(#decision-entry) .species-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 700px) { body:has(#decision-entry) .species-grid { grid-template-columns: 1fr; } }

/* ---- PHASE 4 · Technical reference → handbook index ----------------------- */
.reference-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--spacing-sm);
}
.reference-card {
  display: block;
  padding: var(--spacing-md);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  text-decoration: none;
  transition: border-color .15s ease, background-color .15s ease;
}
.reference-card::before {               /* CSS marker in place of a badge (no badge text may be added) */
  content: "";
  display: block;
  width: 22px;
  height: 3px;
  margin-bottom: var(--spacing-sm);
  background: var(--color-accent);
  border-radius: 1px;
}
.reference-card h3 {
  margin: 0;
  font-size: var(--text-small);
  font-weight: 700;
  line-height: 1.35;
  color: var(--color-text);
}
.reference-card:hover { border-color: var(--color-accent); background: var(--color-surface-tint); }
.reference-card:hover h3 { color: var(--color-link); }
@media (max-width: 900px) { .reference-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 700px) { .reference-grid { grid-template-columns: 1fr; } }

/* ---- PHASE 5 · Evidence / methodology (Phase 2 Evidence Box at section scale) */
.evidence-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--spacing-md);
  align-items: start;
}
.evidence-grid .sources-section { margin-bottom: 0; height: 100%; }
.evidence-grid .sources-section p:last-of-type { margin-bottom: var(--spacing-sm); }
@media (max-width: 900px) { .evidence-grid { grid-template-columns: 1fr; } }

/* ---- PHASE 6 · Editorial: supporting knowledge, not the product ------------ */
body:has(#decision-entry) #editorial-guides .section-header h2 { font-size: var(--text-body); }
body:has(#decision-entry) #editorial-guides .blog-grid {
  display: grid;
  grid-template-columns: 1.5fr 1fr 1fr;
  gap: var(--spacing-lg);
}
body:has(#decision-entry) #editorial-guides .blog-card {
  background: transparent;
  border: 0;
  border-top: 1px solid var(--color-border);
  border-radius: 0;
  box-shadow: none;
  padding: var(--spacing-md) 0 0;
}
body:has(#decision-entry) #editorial-guides .blog-card-image { display: none; }   /* decorative glyph only */
body:has(#decision-entry) #editorial-guides .blog-card h3 {
  margin: 0 0 var(--spacing-xs);
  font-size: var(--text-body);
  line-height: 1.3;
}
body:has(#decision-entry) #editorial-guides .blog-card p { font-size: var(--text-small); color: var(--color-text-body); }
body:has(#decision-entry) #editorial-guides .blog-meta {
  margin-top: var(--spacing-xs);
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}
@media (max-width: 900px) { body:has(#decision-entry) #editorial-guides .blog-grid { grid-template-columns: 1fr; gap: var(--spacing-md); } }

/* ============================================================================
   P4-A — AUTHORITY LAYER (homepage)
   ----------------------------------------------------------------------------
   The two knowledge sections (#recommendation-explanation = recommendation logic,
   #evidence-methodology = evidence sources + limitations) are styled as one
   authority block so the trust narrative reads continuously:
       Problem (hero) → Input factors (decision entry) → Logic → Sources → Limits
   Styling only: no sentence is added, changed or removed here. Tokens only.
   ========================================================================== */

body:has(#decision-entry) #recommendation-explanation,
body:has(#decision-entry) #evidence-methodology {
  background: var(--color-surface-tint);
  padding: var(--spacing-xl) 0;
}
body:has(#decision-entry) #recommendation-explanation { padding-bottom: var(--spacing-lg); }
body:has(#decision-entry) #evidence-methodology {
  padding-top: var(--spacing-lg);
  border-top: 1px solid var(--color-border);
}

/* the two section headings share one label treatment so they read as parts of one block */
body:has(#decision-entry) #recommendation-explanation .section-header h2,
body:has(#decision-entry) #evidence-methodology .section-header h2 {
  letter-spacing: -.01em;
  margin-bottom: var(--spacing-xs);
}
body:has(#decision-entry) #recommendation-explanation .section-header p,
body:has(#decision-entry) #evidence-methodology .section-header p {
  max-width: 68ch;
  color: var(--color-text-body);
}

/* the recommendation-logic cards become reference-style panels, not feature tiles */
body:has(#decision-entry) #recommendation-explanation .features-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--spacing-sm);
  margin-top: var(--spacing-md);
}
body:has(#decision-entry) #recommendation-explanation .feature-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--spacing-md);
  box-shadow: none;
}
body:has(#decision-entry) #recommendation-explanation .feature-icon {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--color-surface-sunk);
  color: var(--color-accent);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: .82rem;
  margin-bottom: var(--spacing-sm);
}
body:has(#decision-entry) #recommendation-explanation .feature-title {
  margin: 0 0 var(--spacing-xs);
  font-size: var(--text-small);
  font-weight: 700;
  color: var(--color-text);
}
body:has(#decision-entry) #recommendation-explanation .feature-text {
  margin: 0;
  font-size: var(--text-small);
  line-height: 1.55;
  color: var(--color-text-body);
}
body:has(#decision-entry) #recommendation-explanation .feature-text a { color: var(--color-link); text-underline-offset: 2px; }

/* the comparison table is framed like every other reference table on the site */
body:has(#decision-entry) .comparison-table {
  margin-top: var(--spacing-lg);
  padding: var(--spacing-xs);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  overflow-x: auto;
}
body:has(#decision-entry) .comparison-table table { margin: 0; }

/* the evidence columns get one rhythm and one label size across the block */
body:has(#decision-entry) #evidence-methodology .evidence-grid { margin-top: var(--spacing-md); }
body:has(#decision-entry) #evidence-methodology .sources-section { padding: var(--spacing-md); }
body:has(#decision-entry) #evidence-methodology .sources-section > h3 { font-size: var(--text-xs); }
body:has(#decision-entry) #evidence-methodology .sources-section a { font-size: var(--text-small); font-weight: 600; }

@media (max-width: 900px) {
  body:has(#decision-entry) #recommendation-explanation .features-grid { grid-template-columns: 1fr; }
}
@media (max-width: 700px) {
  body:has(#decision-entry) #recommendation-explanation,
  body:has(#decision-entry) #evidence-methodology { padding: var(--spacing-lg) 0; }
}

/* the hero's provenance claim is now a link to the evidence section it refers to
   (colour inherited: the hero is dark and the chip text is already white) */
body:has(#decision-entry) .hero-trust a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
body:has(#decision-entry) .hero-trust a:hover { color: var(--color-surface); }

/* ============================================================================
   P6 — TYPOGRAPHY SYSTEM & VERTICAL RHYTHM
   ----------------------------------------------------------------------------
   Type only. No colour is redefined here, no structure or copy is touched, no
   URL or new request is introduced beyond the two heading faces already
   declared in fonts.css.

   Why this layer exists — all three points measured on the live site:
     1. FAMILY: every text node resolved to one family (Inter) for headings and
        body alike, so no hierarchy existed at family level anywhere.
     2. DRIFT: P0–P4 sized headings with clamp(…vw…), so the same heading
        measured 20.8 / 25.5 / 28px at 390 / 1024 / 1440 and landed on values no
        scale contains — 25.9px, 18.648px, 22.792px, 37.296px. Fixed rem + one
        breakpoint replaces the vw interpolation: stable on desktop, still
        responsive on phones.
     3. SPECIFICITY: each page's own inline block sizes the same elements a
        second time, so every selector below is written at the specificity the
        pages use (0,1,1). This sheet loads last, so equal specificity wins here.

   Scale — one ladder, desktop / ≤700px:
     display 40/30 · h1 36/28 · h2 26/22 · h3 20/18 · h4 17/16 · body 16/16
     small 14 · label 13 · micro 12
   ========================================================================== */

:root {
  /* -- families: serif for editorial headings, Inter stays the UI/body face -- */
  --font-heading: 'Source Serif 4', 'Iowan Old Style', 'Palatino Linotype', Georgia, 'Times New Roman', serif;
  --font-ui: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;

  /* -- type scale (fixed rem — deliberately not vw) ------------------------ */
  --t-display: 2.5rem;      /* 40px */
  --t-h1: 2.25rem;          /* 36px */
  --t-h2: 1.625rem;         /* 26px */
  --t-h3: 1.25rem;          /* 20px */
  --t-h4: 1.0625rem;        /* 17px */
  --t-body: 1rem;           /* 16px */
  --t-sm: .875rem;          /* 14px */
  --t-xs: .8125rem;         /* 13px  */
  --t-2xs: .75rem;          /* 12px  */

  --lh-display: 1.12;
  --lh-heading: 1.3;
  --lh-body: 1.72;

  /* -- vertical rhythm ladder (4px base) ---------------------------------- */
  --rhythm-2: .5rem;        /*  8 */
  --rhythm-3: .75rem;       /* 12 */
  --rhythm-4: 1rem;         /* 16 */
  --rhythm-5: 1.5rem;       /* 24 */
  --rhythm-6: 2rem;         /* 32 */
  --rhythm-7: 3rem;         /* 48 */
}

/* ---------------------------------------------------------------- families */
/* One declaration at tag specificity is enough for the family itself: the pages
   only ever declare font-family on `body` (75 blocks, all Inter) and rely on
   inheritance afterwards — nowhere do they set a heading family explicitly. */
h1, h2, h3, h4 {
  font-family: var(--font-heading);
  font-weight: 700;
  line-height: var(--lh-heading);
  letter-spacing: -.004em;
}

/* --------------------------------------------------------------- the scale */
/* display — the hero headline only */
.hero h1 {
  font-size: var(--t-display);
  line-height: var(--lh-display);
  letter-spacing: -.012em;
  /* the pages set `.hero h1 { font-weight: 800 }` at the same specificity as this
     rule, and because this rule is declared before the h1 group its weight was not
     covered — measured 800 on the homepage while every other headline resolved to
     700. Source Serif 4 ships 600/700 only, so 800 would be synthesised. */
  font-weight: 700;
}
/* h1 — page / article headline */
h1, .page-header h1, .article-header h1, .article-hero h1, .blog-header h1,
.error-content h1, .legal-content h1 {
  font-size: var(--t-h1);
  line-height: var(--lh-display);
  letter-spacing: -.012em;
  font-weight: 700;
}
/* h2 — section heading */
h2, .page-header h2, .section-header h2, .calculator-section-title h2,
.article-content h2, .article-body h2, .species-content h2, .about-section h2,
.cta-section h2, .legal-content h2, .blog-card h2 {
  font-size: var(--t-h2);
  line-height: var(--lh-heading);
  font-weight: 700;
}
/* h3 — sub-heading, including the card and FAQ titles (they were 16.8–17.6px,
   i.e. barely above the 16px body, so the level read as flat) */
h3, .article-content h3, .article-body h3, .species-content h3, .card h3,
.blog-card h3, .product-card h3, .reference-card h3, .cta-box h3, .toc-box h3,
.technique-card h3, .contact-info h3, .regulations h3, .values-section h3,
.mission-card h3, .results-header h3, .fix-box h3, .mistake-box h3,
.suggestions h3, .faq-item h3 {
  font-size: var(--t-h3);
  font-weight: 600;
  line-height: 1.35;
}
/* h4 — minor heading */
h4, .article-content h4, .article-body h4, .author-info h4, .quick-tips h4,
.value-content h4, .reg-item h4, .contact-method h4 {
  font-size: var(--t-h4);
  font-weight: 600;
  line-height: 1.4;
}

/* ------------------------------------------- UI headings stay in the UI face */
/* The brand mark and the footer column titles are interface, not editorial
   headings — they must not pick up the serif face. */
.nav-title h1, .nav-title .nav-brand-name, .nav-brand-name,
.footer-logo h3, .footer-title {
  font-family: var(--font-ui);
  letter-spacing: -.02em;
  line-height: 1.2;
}
.nav-title h1, .nav-title .nav-brand-name, .nav-brand-name { font-size: 1.2rem; font-weight: 800; }
.footer-logo h3 { font-size: 1.25rem; font-weight: 800; }
.footer-title { font-size: 1rem; font-weight: 700; }

/* Uppercase micro-labels sit on <h2>/<h3> in the markup but are labels, not
   headings: they keep the sans face, the small size and the wide tracking.
   Declared AFTER the scale rules above — same specificity, so these win. */
.toc > h2, .toc > h3, .toc h2, .toc h3,
.sources-section > h2, .sources-section > h3, .sources-section > h4,
.source-box > h2, .source-box > h3, .source-box > h4,
.external-source > h3, .rec-block > h2, .rec-block > h3,
.table-wrap > figcaption, .table-wrap > caption, .rec-block > h3, .toc > h2 {
  font-family: var(--font-ui);
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  line-height: 1.4;
}

/* ------------------------------------------------------------------- body */
body {
  font-family: var(--font-ui);
  font-size: var(--t-body);
  line-height: var(--lh-body);
}
p, li, td, th, blockquote, figcaption, dt, dd {
  font-family: var(--font-ui);
}
p { margin-bottom: var(--rhythm-4); }

/* ------------------------------------------------------------ prose measure */
/* P0 limited `max-width` to `.article-content > p` (direct children only), so
   paragraphs nested one level deeper ran to ~80 characters at 1440px. Widening
   the selector to every prose descendant is what actually applies the measure. */
.article-content p, .article-body p, .article-content li, .article-body li,
.species-content p, .species-content li, .legal-content p, .about-section p {
  max-width: var(--reading-width, 72ch);
}

/* --------------------------------------------------------- heading rhythm */
/* These margins were em-based, so a 2.1em margin computed to 54.39px and a 1.6em
   one to 29.8368px — values outside any scale, and they moved whenever a font
   size moved. Fixed values from the rhythm ladder instead. Scoped to article
   prose so section headers (which rely on their section's own padding) are
   untouched. */
.article-content h2, .article-body h2, .species-content h2, .legal-content h2 {
  margin-top: var(--rhythm-7);
  margin-bottom: var(--rhythm-3);
}
.article-content h3, .article-body h3, .species-content h3 {
  margin-top: var(--rhythm-6);
  margin-bottom: var(--rhythm-2);
}
.article-content h4, .article-body h4 {
  margin-top: var(--rhythm-5);
  margin-bottom: var(--rhythm-2);
}
.article-content > h2:first-child, .article-body > h2:first-child,
.article-content > h3:first-child, .article-body > h3:first-child { margin-top: 0; }

/* ------------------------------------------------------- form controls */
/* Buttons do not inherit font-family from the document by default, so 146
   control instances (button / input / select) rendered in the browser default
   (Arial) instead of the site face — measured on calculator, blog index and faq. */
button, input, select, textarea, optgroup,
.btn, .btn-primary, .btn-secondary, .btn-shop, .btn-cta, .cta-button, .btn-save {
  font-family: var(--font-ui);
}

/* ============================================================================
   P6.1 — CORRECTIONS FROM THE RENDER PASS
   ----------------------------------------------------------------------------
   Measured after P6 was applied: three page-level headlines still drifted and a
   handful of UI values sat half a pixel off the ladder. Each one traced to a
   specific rule rather than guessed at.
   ========================================================================== */

/* The three headline variants P0/P2 sized with clamp(…vw…) at a specificity
   above the scale rules above. Measured before this fix, in the same layout:
     · article pages  … 37.296px @1021 · 27.648px @768 · 26.4px @390
     · species pages  … 35.2px   @1021 · 26.112px @768 · 25.6px @390
     · calculator     … 32px (2rem, fixed but off-ladder)
   Same selectors as the rules that caused it, declared later, so they win. */
body:has(article.article-content) .page-header h1,
body:has(article.article-content) header.page-header h1,
body:has(.species-content) .page-header h1,
body:has(.species-content) header.page-header h1,
.calculator-page h1, main.calculator-page h1, main.calculator-page > h1 {
  font-size: var(--t-h1);
  line-height: var(--lh-display);
  letter-spacing: -.012em;
}

/* FAQ question headings: faq.html marks them up as <h2> (20px), the 50 article
   pages as <h3> (16.8px) — the same object styled two ways. Both now take the
   sub-heading step, so an FAQ reads identically wherever it appears. */
.faq-item h2 { font-size: var(--t-h3); font-weight: 600; line-height: 1.35; }
.faq-item h3 { font-size: var(--t-h3); font-weight: 600; line-height: 1.35; }

/* Nav links were 14.4px (0.9rem) and the brand mark 19.2px (1.2rem) — both half
   a pixel off the ladder, on every one of the 76 pages. */
.nav-link { font-size: var(--t-sm); }
.nav-links .nav-link { font-size: var(--t-sm); }
.nav-title h1, .nav-title .nav-brand-name, .nav-brand-name { font-size: 1.25rem; }

/* hero buttons: P3B set the primary to 1.02rem (16.32px) and the page set the
   secondary to 0.95rem (15.2px) — two different sizes for one button row. */
body:has(#decision-entry) .hero .btn-primary,
body:has(#decision-entry) .hero .btn-secondary,
.hero .btn-primary, .hero .btn-secondary { font-size: var(--t-body); }

/* calculator's lead line was 1.02rem, its disclosure strip 0.85rem */
.calc-lede, .calc-lede strong { font-size: var(--t-body); }
.affiliate-disclosure, .affiliate-disclosure strong, .affiliate-disclosure a { font-size: var(--t-sm); }

/* the P2 label token was .8rem (12.8px) and is consumed by the species group
   labels, hero badge/trust line and the calculator status line; moving the token
   puts all of them on the ladder at once. */
:root { --text-xs: var(--t-xs); }

/* ============================================================================
   P6.2 — CONVERGENCE OF THE REMAINING OFF-LADDER VALUES
   ----------------------------------------------------------------------------
   Source scan of all 76 pages: 348 declarations at 0.9rem (14.4px), 113 at
   0.85rem (13.6px), 40 at 0.95rem (15.2px), 14 at 0.8rem (12.8px), plus 282 at
   1.1rem (17.6px) which are mostly icon glyph sizes and are deliberately NOT
   touched — an icon's font-size is its drawn size, not a type setting.

   Each target below was confirmed off-ladder in a real render before being
   listed here; nothing is swept in by a wildcard.
   ========================================================================== */

/* 0.9rem / 0.85rem / 0.8rem -> the 14px and 13px steps */
.nav-link, .footer-desc, .footer-links a, .footer-bottom, .footer-bottom a, .footer-bottom p,
.article-meta, .update-date, .form-label, .contact-method p, .card li, .reg-item p,
.line-type-name, .blog-card p, .quick-tips p, .author-note, .amazon-cta p,
.btn-shop, .btn-save, .btn-copy,
.table-wrap table, .article-content table, .article-body table,
.line-table th, .line-table td,
.author-info p, .author-box p, .results-intro, .disclaimer p, .species-line,
.affiliate-disclosure, .affiliate-disclosure strong, .affiliate-disclosure a,
.article-content figure figcaption, .article-body figure figcaption,
.hero-badge, .hero-badge span, .result-label {
  font-size: var(--t-sm);
}
.hero-badge, .hero-badge span, .result-label { font-size: var(--t-xs); }

/* 0.95rem -> body size: these are running text (FAQ answers, callout copy,
   card descriptions) that sat just under the body size without a reason */
.toc li, .toc ol, .toc ul, .btn, .btn-cta, .cta-box p, .feature-text,
.faq-item p, .mission-card p, .value-content p, .card p { font-size: var(--t-body); }

/* the page standfirst / hero lead sat at 17.6px and 15.2px — one step below and
   one step above the body size, both off-ladder */
.hero p, .btn-calculate { font-size: 1.125rem; }              /* 18px lead */
.hero .subtitle, .advanced-summary { font-size: var(--t-body); }

/* ============================================================================
   P6.3 — LAST FOUR OFF-LADDER SOURCES
   ----------------------------------------------------------------------------
   Confirmed by render after P6.2, one page type each: the blog index dates
   (0.82rem = 13.12px, 71 nodes on that page), its filter buttons (0.85rem), the
   blog standfirst (1.1rem), and the species group label.
   ========================================================================== */
.date, .blog-card .date, .article-meta .date, span.date { font-size: var(--t-xs); }
.filter-btn { font-size: var(--t-sm); }
.subtitle, .hero .subtitle, .page-header .subtitle,
.blog-header .subtitle, .article-hero .subtitle, .page-header .subtitle p {
  font-size: var(--t-body);
}
/* the species group label is a label like the TOC/sources ones — it must keep the
   UI face, not inherit the heading face from the h3 tag it sits on */
.species-group { font-family: var(--font-ui); }

/* ============================================================================
   P6.4 — FINAL FOUR SOURCES (one component each, found by inspecting the winning
   rule for every remaining off-ladder node rather than widening selectors blindly)
   ========================================================================== */
.section-title { font-size: var(--t-h2); }        /* species index section head, 1.8rem = 28.8px */
.species-name { font-size: 1.125rem; }            /* species index cards, 1.1rem (a <div>, not the home <h3>) */
.results-status { font-size: var(--t-xs); }       /* calculator status line, 0.8rem */
.section-header p, .cta-section p { font-size: 1.125rem; }   /* section standfirst, was 1.1rem */

/* ============================================================================
   P6.5 — P0 FIX: horizontal overflow on species/index at 390px
   ----------------------------------------------------------------------------
   Measured: document scrollWidth 450 vs viewport 390 — 60px of sideways scroll.
   Cause: that page's own `.species-grid` is `repeat(4, 1fr)` with no breakpoint
   at all, so four cards (each with a 64px icon plus 64px of padding) are forced
   onto a 342px content box. Pre-existing, not introduced by the type layer — but
   it is a P0 defect (sideways scroll on a phone) and it sits in the component
   this pass touches, so it is fixed here rather than reported.
   `minmax(0, 1fr)` is the part that matters: a bare `1fr` keeps each track at its
   min-content width, which is exactly what pushed the page wide.
   Scoped away from the homepage: its grid is already handled by P3B at a higher
   specificity (`body:has(#decision-entry) .species-grid`).
   ========================================================================== */
.species-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 900px) { .species-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 520px) { .species-grid { grid-template-columns: minmax(0, 1fr); } }
/* Other multi-column grids were measured at all three breakpoints and do not
   overflow (cards-grid, technique-grid, reference-grid, blog-grid all measured
   scrollWidth == clientWidth), so they are deliberately left exactly as they are
   rather than re-flowed "for consistency". */

/* Not changed: the consent dialog (11px / 12px / 15px in consent-popup.css) and the
   mobile menu glyph (21.6px). Both are self-contained UI components rather than page
   typography; the dialog's sizes are its own layout budget and shrinking/growing them
   moves its box, so it is reported rather than swept in here. */

/* ============================================================================
   HTML `style` ATTRIBUTES — corrected at the source
   ----------------------------------------------------------------------------
   121 `font-size` values live in HTML style attributes, which no stylesheet can
   override without `!important` (attribute styles outrank every selector). 98 of
   them already carried 14px/16px, i.e. they were on the ladder and needed
   nothing. The remaining 21 were off-ladder (0.85 / 0.9 / 0.95 / 1.05 / 1.1 /
   1.5 / 2rem) and were rewritten in place by
   D:/fishinglineguide-local/fix_inline_font_sizes.py — 7 files, value only, with
   a normalised diff proving no other byte moved. Icon glyph sizes ('<i>' elements)
   were deliberately excluded: an icon's font-size is its drawn size, not type.
   ========================================================================== */

/* ============================================================================
   P7 — MEASURE, PAGE GUTTERS, ACCENT
   ----------------------------------------------------------------------------
   Three changes, each measured before and after rather than eyeballed.
   ========================================================================== */

/* --- 1 · running-text measure: 72ch -> 66ch ------------------------------
   A single column of running prose reads best around 66 characters; past that the
   eye's return sweep gets long enough to lose the line. Measured before: the article
   column rendered 704px at 1440, i.e. ~70ch. Both tokens move so the P0 and P1
   definitions stay in step. */
:root {
  --reading-width: 66ch;
  --ui-reading: 66ch;
}

/* --- 2 · page gutters -----------------------------------------------------
   The container is 1200px with a 24px internal padding, so on the 1280–1440 laptop
   range the margin outside it was only 3–8% of the viewport — measured 112px per
   side at 1440 (7.9%), and 0px at any width below 1200 where the container simply
   fills the window. 1140px is the common editorial container step and lifts the
   measured gutter to 10.0% at 1440 and 20.5% at 1920, without pushing the 3-up
   card grids below a comfortable ~360px per column.
   Deliberately a single value at every width: no large-screen exception, so the
   layout does not change character when a window is resized. */
.container,
nav .container,
header .container,
section .container,
main .container,
footer .container { max-width: 1140px; }
/* The bare `.container` rule was not enough: the pages carry their own
   `nav .container` and `footer .container` rules at (0,1,1), which outrank a plain
   (0,1,0) `.container` regardless of load order. Measured: nav and footer stayed at
   1200px while the header and content went to 1140 — a 60px misalignment between the
   page edges and its own body. Each structural variant is now named.
   `.hero .container` is deliberately absent: the homepage's P3B sets it to 880px at
   (0,2,0) and that is an intentional narrow hero, not a container to widen. */

/* --- 3 · accent convergence ----------------------------------------------
   Companion to the source-side colour pass (D:/fishinglineguide-local/deai_colors.py):
   that script rewrote the values, this pins the tokens so the same drift cannot come
   back through a token. Every chromatic accent on the site now sits in one hue family
   (216°) with only lightness varying — the decorative blue/green/purple icon hues and
   the blue→indigo gradient are gone. */
:root {
  --ui-accent: var(--color-primary);
  --ui-accent-ink: var(--color-link);
}

/* --------------------------------------------------------------- responsive */
@media (max-width: 700px) {
  .hero h1 { font-size: 1.875rem; }                                   /* 30px */
  h1, .page-header h1, .article-header h1, .article-hero h1,
  .blog-header h1, .error-content h1, .legal-content h1 { font-size: 1.75rem; }  /* 28px */
  h2, .page-header h2, .section-header h2, .calculator-section-title h2,
  .article-content h2, .article-body h2, .species-content h2, .about-section h2,
  .cta-section h2, .legal-content h2, .blog-card h2 { font-size: 1.375rem; }     /* 22px */
  h3, .article-content h3, .article-body h3, .species-content h3, .card h3,
  .blog-card h3, .product-card h3, .reference-card h3, .cta-box h3, .toc-box h3,
  .technique-card h3, .contact-info h3, .regulations h3, .values-section h3,
  .mission-card h3, .results-header h3, .fix-box h3, .mistake-box h3,
  .suggestions h3, .faq-item h3 { font-size: 1.125rem; }                          /* 18px */
  .article-content h2, .article-body h2, .species-content h2,
  .legal-content h2 { margin-top: var(--rhythm-6); }
}

/* ------------------------------------------------------------- what P6 is NOT
   Not done here, on purpose:
     · no colour token is redefined and no contrast value is changed — the
       accessibility pass in P3-UI Phase 1 is untouched;
     · section-level padding and the page blocks' own vertical spacing are left
       as they are (they come from each page's inline block, and changing them
       would move layout rather than type);
     · the teal `--color-accent` used for labels and rules is kept: it is a
       semantic accent on labels/borders, not a second call-to-action colour,
       and collapsing it is a brand decision, not a typography fix;
     · heading LEVELS are not restructured — the uppercase micro-labels keep
       their <h2>/<h3> tags and only their face/size is pinned as a label.
   ========================================================================== */
/* ============================================================================
   P8 — VISUAL AUDIT FIXES (draft) · fishinglineguide.com · 2026-10-15
   ----------------------------------------------------------------------------
   草案，尚未应用。全部为 presentation-only：无文本 / 无标记 / 无 URL / 无广告
   几何变更。建议追加到 css/ui-polish.css 末尾（该表加载最后，同权重后置即胜）。
   每条标注对应 REPORT.md 的发现编号与根因。应用后跑 scripts/census2.py 复验。
   ========================================================================== */

/* --- A1 · P0-2 calculator@375 横向溢出 --------------------------------
   根因：.form-grid 单列 1fr 的 auto 下限 = select 的 min-content(362px) > 父容器(312px) */
@media (max-width: 768px) {
  .form-grid { grid-template-columns: minmax(0, 1fr); }
}
.form-grid > *, .calculator-grid > * { min-width: 0; }
.form-select, .form-input { max-width: 100%; }

/* --- A2 · P0-3 species 模板@375 横向溢出 ------------------------------
   根因：页内 .technique-grid 写死 repeat(3,1fr)，无小屏断点（8 个物种页共享） */
@media (max-width: 700px) {
  .technique-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 520px) {
  .technique-grid { grid-template-columns: minmax(0, 1fr); }
}

/* --- A3 · P1-1 hero 决策芯片：空方块占位符 → 真实图标 ----------------
   字形均在 fa-icons.css 子集内（fa-fish / fa-tools / fa-water / fa-ruler），零新请求 */
.decision-factors li::before {
  content: "\f578";
  width: auto; height: auto; border: 0; border-radius: 0; background: none;
  font-family: "Font Awesome 6 Free"; font-weight: 900;
  font-size: .95rem; line-height: 1;
  color: var(--color-accent);
}
.decision-factors li:nth-child(1)::before { content: "\f578"; } /* Species   */
.decision-factors li:nth-child(2)::before { content: "\f7d9"; } /* Technique */
.decision-factors li:nth-child(3)::before { content: "\f773"; } /* Water     */
.decision-factors li:nth-child(4)::before { content: "\f545"; } /* Size      */

/* --- A4 · P1-2 section 纵向节奏统一 -----------------------------------
   两档刻度：内容段 80/56、页头带 64/48（≤700px 缩水）。
   注：会整体平移页面纵向位置（广告随动、槽位不变）。 */
:root {
  --p8-section: 80px;
  --p8-band: 64px;
}
@media (max-width: 700px) {
  :root { --p8-section: 56px; --p8-band: 48px; }
}
/* 内容段（全模板共用类，实测存在于 about/contact/faq/privacy/species/文章页） */
.content { padding: var(--p8-section) 0; }
/* 页头带（含 species 组件层 32/24 的覆盖） */
.page-header { padding: var(--p8-band) 0; }
body:has(.species-content) .page-header { padding: var(--p8-band) 0; }
/* 首页六段 */
.hero { padding: 48px 0 56px; }
.species { padding: var(--p8-section) 0; }
.reference { padding: 0 0 var(--p8-section); }
.features { padding: var(--p8-section) 0 calc(var(--p8-section) / 2); }
.evidence { padding: calc(var(--p8-section) / 2) 0 var(--p8-section); }
.blog-preview { padding: var(--p8-section) 0; }
/* 博客索引 */
.blog-grid { padding-bottom: var(--p8-section); }
/* calculator */
.calculator { padding: var(--p8-section) 0; }
.calc-content { padding: var(--p8-section) 0; }
/* 页脚 */
footer { padding: var(--p8-section) 0 40px; }
@media (max-width: 700px) {
  footer { padding: var(--p8-section) 0 32px; }
}

/* --- A5 · P1-3 博客卡片 meta→标题 67px 死区 ---------------------------
   根因：P3 全局 h2{margin-top:2.1em} 落到卡片内 h2（54.6px @26px） */
.blog-card h2 { margin-top: 0; }

/* --- A6 · P1-4 徽章统一为中性 chip -----------------------------------
   覆盖页内 .badge.badge-*（0,2,0）：本选择器同为 (0,2,0) 且后置。
   如需保留 1 档强调色，删除/改写最后一行即可（决策项）。 */
.badge { background: var(--color-surface-sunk); color: var(--color-text-body); border: 1px solid var(--color-border); }
.badge[class*="badge-"],
.badge.badge-setup, .badge.badge-basics, .badge.badge-knots,
.badge.badge-ice, .badge.badge-fluoro, .badge.badge-braid, .badge.badge-trout,
.badge.badge-catfish, .badge.badge-carp, .badge.badge-saltwater, .badge.badge-kayak,
.badge.badge-bass, .badge.badge-general {
  background: var(--color-surface-sunk);
  color: var(--color-text-body);
  border: 1px solid var(--color-border);
}

/* --- A7 · P1-5 hero 按钮 ≤768 居中 ------------------------------------ */
@media (max-width: 768px) {
  .hero-buttons { align-items: stretch; width: 100%; max-width: 340px; margin-left: auto; margin-right: auto; }
}

/* --- A8 · P1-6 species 模板品牌下划线 --------------------------------- */
.nav-brand, .nav-brand:link, .nav-brand:visited, .nav-brand:hover, .nav-brand * { text-decoration: none; }

/* --- A9 · P1-7 species 索引页尾脱出容器（x=0 vs 62px；v1 后复验修订）--
   v1 只对齐 h2 与 overflow 表 → FAQ/Related/From Species 块仍 x=0，
   制造「标题缩进、正文贴边」新错位。实证：该页尾部 h2+div+ul+p 共 8 个
   直接子元素全在 .container 外（evidence/title-scope.json 全站扫描：
   其余 66 页均无非容器直接子元素）。 */
section.content > :not(.container) {
  max-width: 1140px;
  margin-left: auto; margin-right: auto;
  padding-left: 24px; padding-right: 24px;
}

/* --- A10 · P2-1 类型残留 ---------------------------------------------- */
.article-body { font-size: var(--t-body); }                 /* 16.8px → 16px  */
.product-card p { font-size: var(--t-body); }               /* 15.2px → 16px  */
.toc h2, .toc h3 { font-size: var(--t-xs) !important; font-family: var(--font-ui); } /* 17.6px → 13px 标签（对撞页内 !important，后置胜） */
.page-header p { font-size: var(--t-body); }                /* 19.2px → 16px  */
.calculator-page h1, main.calculator-page h1, main.calculator-page > h1 { font-weight: 700; } /* 消除 serif 伪粗 800 */

/* --- A11 · P2-2 页脚链接圆角孤值 -------------------------------------- */
.footer-links a { border-radius: var(--ui-radius-sm); }     /* 6px → 8px */

/* --- A12 · P2-3 默认蓝链接兜底（:where 保持零特异性，不压既有着色）-- */
.content a:where(:not(.btn):not(.badge):not([class*="badge-"]):not(.cta-button):not(.btn-shop)),
.legal-content a:where(:not(.btn)),
.affiliate-disclosure a:where(:not(.btn)),
.calc-content a:where(:not(.btn)) {
  color: var(--color-link);
}

/* ============================================================================
   应用后验证清单（全部可由 scripts/ 复跑）：
   1. python census2.py   → 预期：48 帧 overflow 全 0
   2. python analyze.py   → 预期：OFF-LADDER 仅剩 hamburger 字形（已接受）
   3. check_imgs.py       → 图片缺陷不变（属内容层）
   4. 特写复核：home hero 芯片图标 / blog 卡片标题间距 / species-index 对齐 /
      calculator@375 无滚动条 / species-bass@375 无滚动条
   ========================================================================== */


/* --- P8 复验补充 2026-10-15（v1 复扫后剩余的 2 处残留）---------------- */
/* A10b: about-author 页 .about-section p 仍为 1.05rem(16.8px)，P6/A10 未覆盖 */
.about-section p { font-size: var(--t-body); }
/* A12b: blog 索引头部区 .blog-header 内裸链接不在 .content 内，仍是 UA 默认蓝 */
.blog-header a:where(:not(.btn):not(.badge):not([class*="badge-"]):not(.cta-button):not(.btn-shop)) { color: var(--color-link); }


/* A10c: calculator H1 的 font-weight:800 是元素内联样式（calculator.html:2399），
   普通选择器无法覆盖（A10 的 .calculator-page h1 因此未生效）；Source Serif 4
   无 800 字重 → 浏览器合成加粗。此处以 !important 压内联。 */
main.calculator-page > h1 { font-weight: 700 !important; }
