/* ============================================================
   LOOP FARMSTEAD — UX / ACCESSIBILITY FIX PACK
   Additive. Nothing here deletes or rewrites an existing rule.

   WHY THIS OVERRIDES TOKENS INSTEAD OF SELECTORS
   -----------------------------------------------
   A first attempt set `body .kicker { color: ... }` and similar.
   It failed across most of the site, because:
     * pages carry bespoke inline <style> blocks, and
     * several use COMPOUND selectors on those rules
       (`.home-hero .kicker`, `.featured-copy .sub`, `.solar-take .lbl`),
       so a one-class override loses on specificity.
   Chasing 342 pages' worth of selectors is unmaintainable and was
   measurably incomplete. Every one of those rules, however, reads its
   colour from `var(--terra)` / `var(--olive)` / `var(--amber)`. So the
   fix is applied once, at the token level, using `html:root` (0,1,1)
   which outranks a page's own `:root` (0,1,0) without `!important`.

   MEASURED BASELINE (live site, Chromium 1440x900 + 390x844, 13 routes)
     --terra #B85C38 small text  3.53-4.25:1   (needs 4.5)
     --olive #6B7F3B small text  3.45-4.16:1   (needs 4.5)
     --amber #E8A849 tag text    1.61-1.94:1   (needs 4.5)
     nav wrapped to 2 rows at every viewport 768-1440px
     ~24-42 low-contrast text runs per page
   ============================================================ */

/* ------------------------------------------------------------
   1. ACCENT TOKENS — same hue family, darkened only to AA.
   Ratios below are measured against --bg #F4EFE6, --bg-deep #EAE2D2
   and --card #FBF7EF respectively.
   ------------------------------------------------------------ */
html:root {
  --terra: #9A4522;   /* 5.64 / 5.02 / 6.05  (was 3.96 / 3.53 / 4.25) */
  --olive: #55662E;   /* 5.51 / 4.90 / 5.91  (was 3.88 / 3.45 / 4.16) */
  --amber: #8A5A00;   /* 5.18 / 4.60 / 5.55  (was 1.81 / 1.61 / 1.94) */

  /* Bright originals are KEPT — the palette is not blanket-darkened.
     These are for large display type, fills, and dark grounds, where
     3:1 is the correct threshold and the richer colour is wanted. */
  --terra-bright: #B85C38;
  --olive-bright: #6B7F3B;
  --amber-bright: #E8A849;
  --terra-btn:    #A94F2C;  /* fill for #fff text: 5.47:1 (was 4.54) */

  --measure: 68ch;
  --space-section: clamp(2.5rem, 6vw, 4.5rem);
}

/* ------------------------------------------------------------
   2. RESTORE BRIGHT ACCENTS ON DARK GROUNDS
   The one place deep accents are wrong: indigo backgrounds. Deep
   amber #8A5A00 on --indigo measures 2.9:1. Measured per-container
   ratios on #1A1A2E:
     --soil #3B2F1E      1.31:1  <- the actual bug on /articles/,
                                     /ledger/ and /signals/, where
                                     `.tagline` inherited soil on an
                                     indigo topbar
     --wheat #D4A843     7.70:1
     --amber #E8A849     8.23:1
     --olive #55662E     2.70:1
   So: any text on an indigo ground must use wheat/amber, never the
   deep tokens and never --soil.
   ------------------------------------------------------------ */
body .signals-banner .eyebrow,
body .signals-banner .kicker,
body .dark .eyebrow,
body .dark .kicker { color: var(--amber-bright); }

body .topbar, body .topbar *,
body .art-topbar, body .art-topbar *,
body .site-footer, body .site-footer *,
body .footer, body .footer * {
  color: var(--wheat);
}
body .topbar a:hover, body .art-topbar a:hover,
body .site-footer a:hover, body .footer a:hover { color: var(--amber); }
/* Re-assert the CTA fill after the blanket dark-ground rule above,
   or the blanket rule (0,2,1) would repaint button labels wheat. */
body .site-nav .btn-donate, body .site-nav a.btn-donate,
body .footer .btn, body .site-footer .btn { background: var(--terra-btn); color: #fff; }

/* `.tagline` in /articles/ is `.site-footer .tagline` (0,2,0) with
   --olive on the indigo ground = 3.84:1. It is a SIBLING of the
   topbar, so the blanket dark-ground rule does not reach it, and a
   `body .tagline` override (0,1,1) loses to it. Match the full
   selector. Same class name is used in /ledger/. */
body .tagline, body .site-footer .tagline { color: var(--wheat); }

/* DO NOT restyle `.cta-thumb`. It measures 2.07:1 against --card only
   because its actual background is a `linear-gradient`, and
   `backgroundColor` is transparent for gradients — so an
   ancestor-walking contrast check reports parchment. Real ratio is
   --wheat on --indigo = 7.70:1, which passes. Verified by reading
   articles/styles.css line 105. A first pass "fixed" this and would
   have put dark amber on an indigo gradient. */

/* ------------------------------------------------------------
   2b. /ledger/ CATEGORY CHIPS AND BANDS
   `.cat` gets its colour from an INLINE style, injected by JS from
   the CAT_COLORS map in the page (`AID:'#D4A843'` etc). Only an
   !important override or editing that map can beat an inline style.
   The map is the cleaner fix; this is the CSS-only stopgap.
   NOTE: the .band elements carry `opacity: 0.16` and `.blabel` is
   INSIDE them, so labels are intentionally faint by design. A first
   pass repainted them white, which at 16% opacity is invisible on
   parchment — measured and REVERTED. Do not "fix" these.
   ------------------------------------------------------------ */
body .cat, body .ev .card .cat { color: var(--olive-deep) !important; }

/* ------------------------------------------------------------
   3. BUTTON FILLS
   Measured failures: nav Donate = wheat on terra (2.05:1) and
   signals .btn-donate = soil on terra (2.87:1) and .cta on
   signals = wheat on terra (2.05:1). Fixed at the fill, not the
   label, so the white text reaches 5.47:1.
   `body` prefix is required: these pages set `.btn-donate` and
   `.cta` in their inline blocks at equal specificity.
   ------------------------------------------------------------ */
body .btn, body .btn-hero, body .btn-donate, body .cta,
body .signals-banner .btn {
  background: var(--terra-btn);
  color: #fff;
}
body .btn:hover, body .btn-hero:hover, body .btn-donate:hover,
body .cta:hover, body .signals-banner .btn:hover {
  background: var(--soil);
  color: #fff;
}

/* ------------------------------------------------------------
   4. TAP TARGETS — WCAG 2.2 AA is 24x24; Apple/Material say 44x44.
   Measured: nav links 17px tall, footer links 22px, cart close
   28x25, inline "Read →" 17px tall.
   NOTE: padding on an `inline` element grows the box but NOT the
   hit area — `display: inline-flex`/`inline-block` is what actually
   creates a 44px target. Padding alone measured 181x17px.
   ------------------------------------------------------------ */
body .site-nav .nav-links a,
body .nav-links a,
body .read, body .card a, body .pillar a,
body .video-link, body .footer-links a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}
body .cart-close, body .welcome-close, body [aria-label="Close"],
body .nav-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
}
/* TRAP: making .nav-toggle an inline-flex container with the default
   `flex-direction: row` lays its three <span> bars out SIDE BY SIDE,
   so the hamburger renders as one long line. Measured in a screenshot
   after the 44x44 change. The bars must be stacked. */
body .nav-toggle { flex-direction: column; }
body .nav-toggle span { width: 24px; height: 3px; background: var(--wheat); margin: 2px 0; display: block; }
body .footer-links { display: flex; flex-wrap: wrap; gap: 0.25rem 1.1rem; justify-content: center; }

/* ------------------------------------------------------------
   5. NAV — one row on desktop, hamburger before it can wrap.
   Measured: 9 links + Donate = 848px of links in an 1100px bar,
   and .nav-links had flex-wrap: wrap, so Shop + Donate dropped to
   a second row at EVERY viewport from 768px to 1440px.
   Two separate traps are handled here; both were found by
   measurement after looking correct in the stylesheet:
     (a) container `flex-wrap: nowrap` is not enough — the
         two-word item "THE LEDGER" still breaks internally, so
         the <li> needs white-space: nowrap too.
     (b) the collapse threshold must be re-measured whenever you
         change what makes the row wide. Adding nowrap pushed the
         overflow floor from ~1040px to ~1070px. Measured:
         overflow at 1061-1070px, clean from 1080px. Hence 1080.
   ------------------------------------------------------------ */
body .site-nav .nav-container { gap: 0.75rem; padding-inline: 1rem; }
body .site-nav .nav-links { gap: clamp(0.45rem, 0.85vw, 1.1rem); flex-wrap: nowrap; }
body .site-nav .nav-links a { font-size: 1rem; }   /* unchanged: 17px */
body .site-nav .nav-links li { white-space: nowrap; }

@media (max-width: 1080px) {
  body .site-nav .nav-container { flex-wrap: wrap; }
  body .site-nav .nav-links {
    display: none;
    flex-direction: column;
    width: 100%;
    gap: 0.8rem;
    padding: 0.5rem 0 1rem;
    flex-wrap: wrap;
  }
  body .site-nav .nav-links.active { display: flex; }
  body .site-nav .nav-toggle { display: inline-flex; }
}

/* ------------------------------------------------------------
   6. BODY TEXT FLOOR
   style.css already sets `html, body { font-size: 17px }`; the
   pages that measured 16px did so via their own inline CSS, and
   /chat/ measured 14px.
   TRAP: do NOT raise the root em. `body { font-size: 1.0625rem }`
   on a 17px root produced an 18.06px body while leaving `1rem`
   nav links at 15.1px — it worsens the small/large RATIO. Fix the
   body only; leave `rem` alone.
   ------------------------------------------------------------ */
body { font-size: max(17px, 1rem); }
body .chat-page, body .auth-page, body .bbs-chat, body .chat { font-size: 0.95rem; }

/* ------------------------------------------------------------
   7. IMAGE DELIVERY
   meditations-front-cover.png is 1800x2701 rendered into a ~300px
   box (6x oversampled), with no width/height/loading/decoding, so
   it also shifts layout on the LCP element.
   ------------------------------------------------------------ */
img { max-width: 100%; }
body img[src$="-cover.png"], body .featured-inner img, body .book-cover img {
  height: auto;
  aspect-ratio: 1800 / 2701;   /* reserve the box => no layout shift */
  background: var(--card);
}

/* ------------------------------------------------------------
   8. KEYBOARD ACCESS
   ------------------------------------------------------------ */
a:focus-visible, button:focus-visible, [onclick]:focus-visible {
  outline: 3px solid var(--terra);
  outline-offset: 2px;
  border-radius: 2px;
}
body .site-nav a:focus-visible, body .footer a:focus-visible { outline-color: var(--wheat); }
.skip-link {
  position: absolute; left: -9999px; top: 0;
  background: var(--indigo); color: var(--wheat);
  padding: 0.75rem 1.25rem; z-index: 200;
}
.skip-link:focus { left: 0; }

/* ------------------------------------------------------------
   9. MOBILE READING
   /signals/ measured 16,438px tall at 390px wide — ~20 screens
   with no in-page navigation. Scale headings to the viewport and
   open up line-height on the long editorial pages.
   ------------------------------------------------------------ */
@media (max-width: 760px) {
  body .prose p, body .signals-list p, body .signal p, body .item p { line-height: 1.65; }
  body h1 { font-size: clamp(2rem, 9vw, 2.75rem); }
  body h2 { font-size: clamp(1.4rem, 6vw, 1.85rem); }
}

/* ------------------------------------------------------------
   10. /ledger/ SAFETY
   `.track` measures 30,750px wide (left edge -30,047px) at every
   viewport. body.scrollWidth currently equals the viewport so it
   is clipped today, but documentElement overflow-x is `visible`,
   so this is one CSS change away from a 30,000px scrollbar. Pin
   the axis so the element can never become one.
   ------------------------------------------------------------ */
body .ledger-track, body .timeline-track { overflow-x: auto; max-width: 100%; }

/* ------------------------------------------------------------
   11. BREADCRUMB + /learn/ CARD LINKS
   Measured failures: `.breadcrumb a` renders 30x17px and 19x13.94px
   (fails WCAG 2.2 AA's 24x24), and `.topic a` on /learn/ is 14.45px
   at well under 24px tall.
   EXCEPTION, deliberately not "fixed": the 257 link rows in the
   /wv-guide/ index measure 556x30px. 30px already CLEARS the WCAG 2.2
   AA minimum of 24x24, so forcing them to 44 would add roughly 3,600px
   of page length to a 260-item index for no accessibility standard
   actually gained. 44px is Apple/Material guidance, not a requirement.
   Leave dense indexes alone once they clear 24x24.
   ------------------------------------------------------------ */
body .breadcrumb a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}
body .topic a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

/* ------------------------------------------------------------
   12. STANDALONE CARD / FOOTER LINKS (the remaining true failures)
   Fixed: `.frame a` on /philosophy/ ("Read more →", 95x17px) —
   standalone block links, not inline in a sentence, so they DO need
   24x24. Also the `.fblock a` footer stack on /signals/
   (357x22px).

   DELIBERATELY NOT FIXED, and why — these are WCAG 2.2 SC 2.5.8
   "Inline" exception cases: "the target is in a sentence or its size
   is otherwise constrained by the line-height of non-target text."
     /signals/  18px headline links inside prose sentences
     /ledger/   a bare URL inside a sentence
     /learn/    "supporting the work" inside a paragraph
     /may.html  "April ←" / "June →" prev-next nav
     /manifesto/ "← Back to Manifesto" inline nav
   Inflating these would push the line-height of the surrounding text
   and make the pages worse. 24px is the AA floor; 44px is Apple/
   Material guidance, not a requirement — apply it to controls, not to
   every link in a sentence.
   ------------------------------------------------------------ */
body .frame a { display: inline-flex; align-items: center; min-height: 44px; }
body .fblock a { display: inline-flex; align-items: center; min-height: 44px; }

/* ------------------------------------------------------------
   13. TABLE SCROLL CONTAINERS
   Measured: the "Quick Reference" tables on the preservation guides
   render 472px wide inside a 390px viewport and pushed the whole page
   into horizontal overflow. A scroll container keeps the table at full
   size (no shrinking the type) while the page stays put.
   ------------------------------------------------------------ */
body .table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  max-width: 100%;
  margin: 1.2rem 0;
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
body .table-scroll table { margin: 0; border: 0; min-width: 100%; }
body .table-scroll th, body .table-scroll td { white-space: nowrap; }
body .article-content table { width: 100%; border-collapse: collapse; }

/* ------------------------------------------------------------
   14. BUTTON SPACING IN CONTENT
   Measured on the preservation guides at 390px: two stacked `.btn`
   inline-blocks sat at y=96262-96318 and y=96318-96374 — adjacent with
   ZERO gap, which reads as overlapping/merged buttons. They are not
   actually overlapping; they just need breathing room.
   ------------------------------------------------------------ */
body .article-content .btn { margin: 0 0.5rem 0.75rem 0; }
body .article-content .btn + .btn { margin-left: 0; }

/* ------------------------------------------------------------
   15. IN-PAGE TABLE OF CONTENTS
   Five published guides run 18,878-23,889 words on one URL (the largest
   is 161KB). At 390px that is roughly 20,000px of scroll with no
   navigation. The TOC is generated from the page's own h2s so the
   anchors cannot drift from the headings.
   ------------------------------------------------------------ */
body .page-toc {
  background: var(--bg-deep);
  border: 1px solid var(--line);
  border-left: 4px solid var(--olive);
  border-radius: var(--radius);
  padding: 1.3rem 1.6rem;
  margin: 1.6rem 0 2.2rem;
}
body .page-toc-title {
  font-family: var(--mono);
  font-size: 0.8rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--olive);
  margin-bottom: 0.7rem;
}
body .page-toc ol { margin: 0; padding-left: 1.3rem; }
body .page-toc li { margin: 0.32rem 0; line-height: 1.45; }
body .page-toc a { color: var(--terra); text-decoration: none; }
body .page-toc a:hover { text-decoration: underline; }
body .page-toc a:focus-visible { outline: 3px solid var(--terra); outline-offset: 2px; }

/* Anchored headings must not hide under any sticky header on jump. */
body h2[id], body h3[id] { scroll-margin-top: 1.25rem; }

/* Back-to-top: a real 44px control, hidden until it is useful. */
body .to-top {
  position: fixed;
  right: 1rem;
  bottom: 1rem;
  z-index: 120;
  display: none;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 0 0.9rem;
  background: var(--indigo);
  color: var(--wheat);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  font-family: var(--mono);
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  box-shadow: 0 6px 18px rgba(26,26,46,0.28);
}
body .to-top.show { display: inline-flex; }
body .to-top:hover { background: var(--soil); color: var(--wheat); }

/* ------------------------------------------------------------
   16. COLLAPSIBLE TOC
   cucumbers.html has 21 sections and sauerkraut 24, so the TOC box ran
   past the fold and became its own scrolling problem. Collapse it to a
   fixed height with a fade, and let it scroll internally.
   ------------------------------------------------------------ */
body .page-toc ol {
  max-height: 15.5rem;
  overflow-y: auto;
  padding-right: 0.4rem;
  scrollbar-width: thin;
}
body .page-toc ol::-webkit-scrollbar { width: 8px; }
body .page-toc ol::-webkit-scrollbar-thumb { background: var(--line); border-radius: 4px; }
