/* viewer.v2.css — extracted from build_viewer.py and adapted for the
   API-driven browser. Same visual model as the embedded-JSON viewer,
   minus the layout shell which lives in base.html.
   (renamed from viewer.css 2026-06-24 to cache-bust the .appendix-lineage
    banner styling at the Cloudflare edge — golden rule #5. Referenced from
    templates/viewer.html.) */

:root {
  --del: #b22222; --del-bg: #fff0f0;
  --ins: #1e6e1e; --ins-bg: #f0fff0;
  --annot: #5a5a60;
  --toc-w: 240px;
  /* Greys tightened 2026-04-27 for readability — the previous values
     (--fg-soft #4b4b50, --muted #8a8a8f) washed out against white.
     The new values still read as "soft" / "secondary" but with enough
     contrast to be legible at small font sizes. */
  --fg: #0f0f12;
  --fg-soft: #2e2e33;
  --bg-soft: #f7f7f8;
  --border: #d8d8dc;
  --border-soft: #ededee;
  /* Free Movement orange is the viewer accent — links, headings and
     chrome — standardised with the other tools. The date axis is the one
     exception: real commencement-date ticks keep the legislation.gov.uk
     navy so the synthetic orange 'Current' tick reads as provisional (the
     navy-vs-orange contrast is the real-vs-provisional signal). See
     .date-ticks below, which hardcode that navy rather than --accent. */
  --accent: #c94907;
  --accent-soft: #fff7ed;
  --muted: #5a5a60;
}

#viewer-root .loading {
  text-align: center; color: var(--muted); padding: 60px 0;
  font-style: italic;
}

#viewer-root.ready { display: flex; min-height: 80vh; margin: -24px -20px 0; }

.toc {
  width: var(--toc-w); flex-shrink: 0;
  border-right: 1px solid var(--border); background: var(--bg-soft);
  position: sticky; top: 0; height: 100vh; overflow-y: auto;
  font-size: 13px;
}
.toc.collapsed { width: 36px; }
.toc.collapsed .toc-list, .toc.collapsed .toc-header span { display: none; }
.toc.toc-empty { display: none; }   /* no sections to show (e.g. the Parts) */
.toc-header {
  display: flex; align-items: center; padding: 12px;
  border-bottom: 1px solid var(--border); font-weight: 600;
  position: sticky; top: 0; background: var(--bg-soft); z-index: 1;
}
.toc-header button {
  background: none; border: none; color: var(--fg-soft); cursor: pointer;
  padding: 0; margin-right: 8px; font-size: 14px; line-height: 1;
}
.toc-list { list-style: none; margin: 0; padding: 8px 0; }
.toc-list li a {
  display: block; padding: 4px 12px 4px 16px; color: var(--fg-soft);
  text-decoration: none; border-left: 3px solid transparent;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.toc-list li a:hover { background: rgba(201,73,7,0.06); color: var(--fg); }
.toc-list li a.active {
  color: var(--accent); font-weight: 600;
  border-left-color: var(--accent); background: rgba(201,73,7,0.08);
}
.toc-list li.toc-top { position: relative; }
.toc-list li.toc-top > a {
  font-weight: 600; color: var(--fg); padding-left: 28px;
}
.toc-list li.toc-top .chev {
  position: absolute; left: 6px; top: 4px; width: 16px; height: 16px;
  line-height: 16px; text-align: center; cursor: pointer;
  color: var(--muted); font-size: 10px; user-select: none;
}
.toc-list li.toc-top .chev:hover { color: var(--fg); }
.toc-list li.toc-top.expanded .chev { transform: rotate(90deg); }
.toc-subs { list-style: none; margin: 0; padding: 0; display: none; }
.toc-list li.toc-top.expanded > .toc-subs { display: block; }
.toc-subs li a {
  display: block; padding: 3px 12px 3px 36px; font-size: 12px;
  color: var(--muted); text-decoration: none;
  border-left: 3px solid transparent; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
.toc-subs li a:hover { background: rgba(201,73,7,0.06); color: var(--fg); }
.toc-subs li a.active {
  color: var(--accent); font-weight: 600;
  border-left-color: var(--accent); background: rgba(201,73,7,0.08);
}

.viewer-main { flex: 1; min-width: 0; }
.top-sticky {
  position: sticky; top: 0; z-index: 10; background: white;
  box-shadow: 0 1px 0 var(--border), 0 2px 8px rgba(0,0,0,0.04);
}
.viewer-header {
  padding: 10px 28px; border-bottom: 1px solid var(--border-soft);
}
.viewer-header h2 { margin: 0; font-size: 19px; font-weight: 600; }
.viewer-header .meta { font-size: 13px; color: var(--muted); margin-top: 2px; }
.viewer-header .back-link {
  font-size: 14px; color: var(--accent); text-decoration: none;
  font-weight: 600; display: inline-block; padding: 2px 0;
}
.viewer-header .back-link:hover { text-decoration: underline; }

.slider-wrap {
  padding: 10px 28px 12px; background: white;
  border-bottom: 1px solid var(--border);
}
.slider-row {
  display: flex; align-items: center; gap: 16px; margin-bottom: 6px;
  font-size: 13px; color: var(--fg-soft); flex-wrap: wrap;
}
.slider-row .current-date { color: var(--accent); font-weight: 600; font-size: 14px; }
/* 2026-05-22 (SoC-axis): the per-stop honest caption — names the
   Statement and how the displayed text relates to it. Kept subtle so
   it does not compete with the date itself. */
.slider-row .stop-caption {
  font-weight: 400; font-size: 12px; color: var(--fg-soft);
  margin-left: 4px;
}
.slider-row .stop-caption.verif-no_archive,
.slider-row .stop-caption.verif-superseded,
.slider-row .stop-caption.verif-unattributed,
.slider-row .stop-caption.verif-forthcoming {
  color: #9a6700;
}
/* Forthcoming (not-yet-in-force) commencement — 2026-07-09, HC 259: a
   small amber pill next to the date so a future stop can never be
   misread as the law in force today. Same amber register as the
   superseded/unattributed captions. */
.forthcoming-flag {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 8px;
  border-radius: 10px;
  border: 1px solid #d9a514;
  background: #fff8e1;
  color: #9a6700;
  font-size: 11px;
  font-weight: 600;
  vertical-align: 1px;
  white-space: nowrap;
}
/* 2026-05-22: the per-stop verification caption now lives BELOW the
   slider (#stop-caption-row), not in .slider-row. Its text length
   varies between stops; keeping it out of the row stops it pushing the
   slider down while dragging. min-height reserves ~2 lines so the
   reading column below does not reflow either. */
.stop-caption-row {
  min-height: 2.7em;
  margin-top: 4px;
  font-size: 12px;
  line-height: 1.35;
  color: var(--fg-soft);
}
.stop-caption-row .stop-caption.verif-no_archive,
.stop-caption-row .stop-caption.verif-superseded,
.stop-caption-row .stop-caption.verif-unattributed,
.stop-caption-row .stop-caption.verif-forthcoming {
  color: #9a6700;
}
.stop-caption-row .stop-caption.verif-forthcoming { font-weight: 600; }
.slider-row .toggles { margin-left: auto; display: flex; gap: 16px; }
.slider-row .toggles label { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; }
.slider-row .toggles input { accent-color: var(--accent); }
/* The "Options" disclosure button is a mobile-only affordance — on
   desktop the toggles + date box are always shown inline, so the button
   is hidden. The mobile media block at the foot of this file flips it
   on and collapses the controls behind it. */
.options-toggle { display: none; }
input[type=range] { width: 100%; accent-color: var(--accent); }
/* Scroll affordance for the date row. Two-part: (a) a wider, more
   aggressive white fade at each end so text near the edge clearly
   washes out — needed because a soft white-to-transparent on a white
   background with small grey text is otherwise imperceptible; (b) a
   small chevron arrow (‹ / ›) sitting at each edge as the visible
   "more this way" cue. Both fade in/out together based on scroll
   position. */
.date-ticks-wrap {
  position: relative;
  margin-top: 4px;
}
.date-ticks-wrap::before,
.date-ticks-wrap::after {
  position: absolute;
  top: 0; bottom: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.18s ease-out;
  z-index: 2;
  display: flex; align-items: center; justify-content: center;
  width: 36px;
  font-size: 18px;
  line-height: 1;
  color: var(--accent);
  font-family: -apple-system, BlinkMacSystemFont, sans-serif;
  font-weight: 600;
}
.date-ticks-wrap::before {
  content: "‹";
  left: 0;
  /* Stay fully white for the first 16px, then fade. */
  background: linear-gradient(to right,
    rgba(255,255,255,1) 0,
    rgba(255,255,255,1) 16px,
    rgba(255,255,255,0) 100%);
  padding-left: 4px;
  justify-content: flex-start;
}
.date-ticks-wrap::after {
  content: "›";
  right: 0;
  background: linear-gradient(to left,
    rgba(255,255,255,1) 0,
    rgba(255,255,255,1) 16px,
    rgba(255,255,255,0) 100%);
  padding-right: 4px;
  justify-content: flex-end;
}
.date-ticks-wrap.can-scroll-left::before { opacity: 1; }
.date-ticks-wrap.can-scroll-right::after { opacity: 1; }

.date-ticks {
  display: flex; justify-content: space-between; font-size: 11px;
  color: var(--muted); gap: 8px;
  flex-wrap: nowrap; white-space: nowrap; overflow-x: auto;
  padding: 2px 24px 2px 6px;
  /* Hide the horizontal scrollbar — on macOS scrollbars appear at the
     bottom of the scroll container during scroll and partially struck
     through the active-state pill. Scroll behaviour is preserved
     (touchpad swipe, mouse wheel, keyboard arrow keys); the fade
     overlays above signal that more content exists. */
  scrollbar-width: none;          /* Firefox */
  -ms-overflow-style: none;       /* legacy Edge / IE */
}
.date-ticks::-webkit-scrollbar { display: none; } /* Chrome / Safari / new Edge */
/* Date ticks are <button>s so keyboard users can tab + activate them.
   Tap target raised to ~32px tall (was ~16px) to be comfortable on
   touch — still smaller than the 44px WCAG comfort target but a real
   improvement, and full WCAG-comfortable would push the date row off
   one viewport line. */
.date-ticks button {
  cursor: pointer; padding: 6px 8px; border-radius: 4px;
  flex-shrink: 0;
  background: transparent; border: 0; color: inherit;
  font: inherit; font-size: 11px;
  transition: background-color 0.1s, color 0.1s;
  min-height: 32px;
  position: relative;
}
/* Per-date reliability marker (Unit 2). Small dot tucked above the
   tick label; same RAG palette as the contents-page rag-dot so a
   given (key, date) shows the same colour everywhere. The dot is
   purely decorative — accessibility info is on the button's
   aria-label/title via viewer.js. */
.date-ticks button::before {
  content: "";
  position: absolute;
  top: 2px;
  left: 50%;
  transform: translateX(-50%);
  width: 6px; height: 6px;
  border-radius: 50%;
  background: transparent;
  border: 1px solid rgba(0,0,0,0.15);
  pointer-events: none;
}
.date-ticks button.tick-rag-green::before  { background: #1e9c5a; border-color: #156c3f; }
.date-ticks button.tick-rag-amber::before  { background: #e3a008; border-color: #a06200; }
.date-ticks button.tick-rag-red::before    { background: #c0413c; border-color: #802a26; }
.date-ticks button.tick-rag-thin::before   { background: #b3b3b3; border-color: #6f6f6f; }
.date-ticks button.tick-rag-unknown::before { background: transparent; border-style: dashed; }
.date-ticks button.active::before { transform: translateX(-50%) scale(1.25); }

/* The date axis stays in the legislation.gov.uk navy register: real
   commencement-date ticks are navy, the synthetic 'Current' tick below is
   orange — that navy-vs-orange contrast is the real-vs-provisional signal,
   so these hardcode navy rather than follow the (now orange) --accent. */
.date-ticks button:hover { background: #e8f1fa; color: #004a99; }
.date-ticks button:focus { outline: none; }
.date-ticks button:focus-visible {
  outline: 2px solid #004a99;
  outline-offset: 1px;
}
.date-ticks button.active {
  background: #004a99; color: white; font-weight: 600;
  box-shadow: 0 0 0 1px #004a99;
}
/* Synthetic 'Current' tick — visually distinct from real-date ticks
   so users see at a glance that the rightmost position is "as in
   force today" rather than another commencement date. Uses the FM
   accent (orange) instead of the navy accent used for real dates. */
.date-ticks button.current-tick {
  background: #fff7ed;
  color: #c94907;
  font-weight: 700;
  border: 1px solid #fed7aa;
}
.date-ticks button.current-tick:hover {
  background: #fed7aa;
  color: #c94907;
}
.date-ticks button.current-tick.active {
  background: #c94907;
  color: white;
  border-color: #c94907;
  box-shadow: 0 0 0 1px #c94907;
}
/* Forthcoming (not-yet-in-force) commencement tick — 2026-07-09, HC 259.
   Amber + dashed border: visibly provisional against both the navy real
   dates and the orange 'Current' tick, in the same amber register as the
   superseded/unattributed captions. Selectable like any other tick. */
.date-ticks button.forthcoming-tick {
  background: #fffbeb;
  color: #9a6700;
  font-weight: 600;
  border: 1px dashed #d9a514;
}
.date-ticks button.forthcoming-tick:hover {
  background: #fff3c4;
  color: #7a5200;
}
.date-ticks button.forthcoming-tick.active {
  background: #9a6700;
  color: white;
  border: 1px solid #9a6700;
  box-shadow: 0 0 0 1px #9a6700;
}
.diff-disabled-note {
  font-size: 11px; color: var(--muted); font-style: italic; margin-top: 4px;
}

.viewer-body { padding: 24px 28px 96px; }
.reading-column { max-width: 880px; margin: 0 auto; }
.preamble {
  padding: 0; margin-bottom: 20px;
  white-space: pre-wrap; font-size: 13px; color: var(--fg-soft);
}
.section-heading {
  font-size: 13px; font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.05em; color: var(--accent);
  margin: 28px 0 8px; padding-bottom: 4px;
  border-bottom: 1px solid var(--border);
}
.section-heading:first-child { margin-top: 0; }
.subsection-heading {
  font-size: 13px; font-weight: 600; color: #1d1d1f;
  margin: 18px 0 6px;
}

.para {
  display: grid; grid-template-columns: 64px 1fr;
  gap: 14px; padding: 1px 0; align-items: baseline;
}
.para.cont .pid { color: var(--muted); }
.para.cont[data-depth="0"] .pbody { padding-left: 0; }
.para[data-cont-child="1"] .pbody { padding-left: 1em; }
.para[data-cont-child="2"] .pbody { padding-left: 2em; }
.para[data-cont-child="3"] .pbody { padding-left: 3em; }
.para + .para[data-depth="1"], .para + .para[data-depth="2"],
.para + .para[data-depth="3"], .para + .para[data-depth="4"] {
  padding-top: 0;
}
.para[data-depth="0"] { padding-top: 6px; }
/* Paragraph id labels are plain, non-interactive text (monospace, no
   border/background). Not clickable — no copy affordance (Colin,
   2026-06-14: "turn off clickable pointer"). */
.para .pid {
  font-family: "SF Mono", Menlo, Monaco, Consolas, monospace;
  font-size: 11px; color: #57575c; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; text-align: left;
}
.para .pbody { white-space: pre-wrap; font-size: 14.5px; color: #1d1d1f; }

.para[data-depth="1"], .para[data-depth="2"],
.para[data-depth="3"], .para[data-depth="4"] {
  grid-template-columns: 48px 1fr;
}
.para[data-depth="1"] .pid, .para[data-depth="2"] .pid,
.para[data-depth="3"] .pid, .para[data-depth="4"] .pid {
  text-overflow: clip; overflow: visible;
}
/* Sub-paragraph indents reduced 2026-06-04 (Colin: deep paragraphs were
   sidelined into a narrow right strip). Gentler, less-compounding steps keep the
   nesting visible without pushing the text off to the side. */
.para[data-depth="1"] { padding-left: 40px; }
.para[data-depth="2"] { padding-left: 68px; }
.para[data-depth="3"] { padding-left: 96px; }
.para[data-depth="4"] { padding-left: 124px; }

/* Definition parents (Interp: <term>, Annex1: <term>) — the id IS the
   definition's term, so we render it as a heading-style label spanning
   the row rather than crushing it into the 110px id slot. The body sits
   below, indented. Sub-clauses (Interp: <term>(a) etc.) keep the
   ordinary depth-1 layout so their (a)/(b) leaves render normally. */
.para.definition-parent {
  grid-template-columns: 1fr;
  gap: 4px;
  padding-top: 14px;
}
.para.definition-parent .pid {
  font-family: inherit;
  font-size: 15px; font-weight: 600;
  color: var(--text, #1d1d1f);
  white-space: normal;
  overflow: visible; text-overflow: clip;
}
.para.definition-parent .pbody { padding-left: 1.4em; }

.pbody del { color: var(--del); text-decoration: line-through; background: var(--del-bg); }
.pbody ins { color: var(--ins); text-decoration: none; background: var(--ins-bg); }

/* Diff mode: a paragraph present at the previous served version but
   absent from this page (snap.diff_removed). Struck-through body with a
   left rule so a Statement's deletions are visible, not silently gone. */
.para.diff-removed { border-left: 3px solid var(--del); padding-left: 8px; opacity: 0.8; }
.para.diff-removed .diff-removed-note {
  display: block; font-size: 11px; font-weight: 600; color: var(--del);
  text-transform: uppercase; letter-spacing: 0.03em; margin-bottom: 2px;
}
.para.diff-removed .pbody del { text-decoration: line-through; }

.para.deleted { opacity: 0.55; }
.para.deleted .pbody { font-size: 12px; font-style: italic; color: var(--muted); }
.para.deleted .pbody::before {
  content: "[deleted] "; font-weight: 600; color: var(--del);
  font-style: normal; margin-right: 4px;
}

.pbody .annot-mark { font-weight: 600; font-size: 0.78em; color: var(--annot); vertical-align: super; line-height: 0; }
.pbody .annot-bracket { color: var(--annot); }
.footnotes { margin-top: 4px; font-size: 11.5px; color: var(--muted); font-style: italic; }
.footnotes .fn-mark { font-weight: 600; color: var(--annot); margin-right: 4px; font-style: normal; }
.footnotes .fn-soc { font-style: normal; font-weight: 600; color: var(--annot); }

/* A Statement-of-Changes id hyperlinked to its VERIFIED gov.uk
   publication page (socHtml). Subtle underline so the affordance is
   visible without shouting; the inner .fn-soc keeps its context
   colour. */
.fn-soc-link { text-decoration: none; }
.fn-soc-link .fn-soc {
  text-decoration: underline;
  text-decoration-style: dotted;
  text-underline-offset: 2px;
  cursor: pointer;
}
.fn-soc-link:hover .fn-soc { text-decoration-style: solid; }

/* Diff-mode banner: shown above the body when "Show changes since
   previous version" is on. Names the two SoC commencements being
   compared so the user sees the citation context at a glance. */
.diff-mode-banner {
  margin-top: 6px;
  padding: 6px 10px;
  border-radius: 4px;
  background: #fff7ed;
  color: #c94907;
  border-left: 3px solid #c94907;
  font-size: 12.5px;
}

/* Appendix-level deletion banner: warns a practitioner reading the
   page that the Part / Appendix is no longer in force. Used for cases
   like Part 14, which was actively deleted by HC_246 and replaced by
   Appendix Statelessness. Coloured red rather than the orange used for
   creation banners — this is a hazard signal, not informational. */
.appendix-deletion {
  margin: 8px 0 4px;
  padding: 8px 12px;
  border-radius: 4px;
  background: #fef2f2;
  color: #7f1d1d;
  border-left: 4px solid #dc2626;
  font-size: 13px;
  line-height: 1.45;
}
.appendix-deletion .fn-soc {
  font-weight: 600;
  color: #b91c1c;
}

/* Appendix-level §2 fallback banner: the LOUD, visually-unmistakable warning
   (CLAUDE.md §2) shown when an appendix's text is archived gov.uk wording that the
   Statement-of-Changes chain has NOT yet reconstructed — never a quiet badge. The
   definition / sub-clause-heavy appendices (FM, EU, ...) are the current fallbacks;
   this is the count to drive toward zero. Stronger than the deletion banner: a
   full amber border + tinted block so a practitioner cannot miss that the text is
   not reconstructed law. */
.appendix-fallback {
  margin: 10px 0 6px;
  padding: 10px 14px;
  border-radius: 4px;
  background: #fffbeb;
  color: #7c2d12;
  border: 2px solid #d97706;
  border-left-width: 6px;
  font-size: 13px;
  line-height: 1.5;
}
.appendix-fallback strong { color: #9a3412; }

/* Appendix-level creation banner: a single notice at the top of an
   appendix that was inserted into the rules in one SoC act (e.g.
   Appendix Long Residence inserted by HC_590). Replaces what would
   otherwise be a redundant per-paragraph "Inserted by HC_X" footnote
   on every rule in the appendix. */
.appendix-creation {
  margin: 6px 0 4px;
  padding: 5px 9px;
  border-radius: 3px;
  background: #fff7ed;
  color: #7a2e05;
  border-left: 3px solid #c94907;
  font-size: 12.5px;
  font-style: italic;
}

/* Migration lineage cross-link — informational (NOT a hazard): for an
   Appendix that took a topic over from an earlier container (Simplification
   migrations, e.g. Appendix Long Residence ← Part 7), a single link back to
   where the rules lived before. Neutral blue-grey to read as a navigation
   aid, distinct from the orange creation banner and the red fallback hazard. */
.appendix-lineage {
  margin: 6px 0 4px;
  padding: 5px 9px;
  border-radius: 3px;
  background: #f1f5f9;
  color: #334155;
  border-left: 3px solid #64748b;
  font-size: 12.5px;
}
.appendix-lineage a { color: #1d4ed8; }

/* RAG (red/amber/green) reliability dot — shared with home.html.
   Used inline next to the appendix title in the viewer header. Same
   palette as the contents page so the colour is consistent end-to-
   end. */
.rag-dot {
  display: inline-block;
  width: 9px; height: 9px;
  border-radius: 50%;
  margin-right: 4px;
  vertical-align: 2px;
  background: #b3b3b3;
  border: 1px solid rgba(0,0,0,0.10);
  flex: none;
}
.rag-dot.rag-green { background: #1e9c5a; border-color: #156c3f; }
.rag-dot.rag-amber { background: #e3a008; border-color: #a06200; }
.rag-dot.rag-red   { background: #c0413c; border-color: #802a26; }
.rag-dot.rag-thin  { background: #b3b3b3; border-color: #6f6f6f; }
.rag-dot.rag-unknown { background: transparent; border-style: dashed; }

/* RAG dot near the appendix title temporarily disabled 2026-05-18:
   parts+introduction campaign brought every in-window appendix to GREEN
   so the inline dot conveys nothing useful. Reactivate by removing the
   rule below when work shifts to earlier dates where reliability varies. */
.rag-dot { display: none !important; }

/* Closed-alpha WIP banner shown on every appendix viewer page —
   tighter than the contents-page version because vertical real
   estate matters in the slider area. */
.wip-banner-viewer {
  background: #fff7ed;
  border: 1px solid #fed7aa;
  border-left: 3px solid #c94907;
  padding: 7px 11px;
  margin: 6px 0 4px;
  border-radius: 3px;
  color: #3a3a3f;
  font-size: 12.5px;
  line-height: 1.45;
}
.wip-banner-viewer strong { color: #c94907; }

/* Pre-2020 window note. Shown when the viewed SoC date falls before
   the engine's two-sided verification window. Slate-grey palette (not
   the warning-orange WIP banner) — this is a calibration note, not an
   alert. Hidden by default; the renderer toggles .visible when the
   viewer lands on a pre-2020 stop. */
.pre2020-window-note {
  background: #f7f7f8;
  border: 1px solid #e2e8f0;
  border-left: 3px solid #65656a;
  padding: 7px 11px;
  /* Sits below the slider/ticks now; a little top margin separates it
     from the controls above. */
  margin: 8px 0 0;
  border-radius: 3px;
  color: #3a3a3f;
  font-size: 12.5px;
  line-height: 1.45;
  display: none;
}
.pre2020-window-note.visible { display: block; }
.pre2020-window-note strong { color: #0f0f12; }

/* Collapsible section wrappers (Unit 5). Each top-level appendix
   section is wrapped in a <details>; the <summary> hosts the
   existing h3 section heading. Default open on desktop, closed on
   mobile (≤720px) — set via the markup's `open` attribute, not
   CSS, so the open/closed state persists across slider movements
   without a layout flicker. */
details.section-block {
  margin: 14px 0;
  border-top: 1px solid #ededee;
}
details.section-block:first-of-type {
  border-top: 0;
  margin-top: 4px;
}
details.section-block > summary.section-summary {
  cursor: pointer;
  list-style: none;
  padding: 6px 0 4px;
  display: flex;
  align-items: center;
  gap: 8px;
}
details.section-block > summary.section-summary::-webkit-details-marker {
  display: none;
}
/* Custom triangle marker that rotates on open. Sits before the
   heading text so the heading stays visually aligned with other
   ones the user expects. */
details.section-block > summary.section-summary::before {
  content: "▸";
  color: #c94907;
  font-size: 12px;
  width: 12px;
  display: inline-block;
  flex: none;
  transform: rotate(0deg);
  transition: transform 0.12s;
}
details.section-block[open] > summary.section-summary::before {
  transform: rotate(90deg);
}
details.section-block > summary.section-summary > .section-heading {
  margin: 0;
  flex: 1;
}
details.section-block > summary.section-summary:hover {
  background: #fff7ed;
}
details.section-block > .section-body {
  padding-left: 0;
}
.appendix-creation .fn-soc {
  font-style: normal;
  font-weight: 600;
  color: var(--annot);
}

/* Pipe-separated table rows from the baseline parser, rendered as a
   real HTML table rather than as a run of cramped paragraph rows. */
.rules-table {
  border-collapse: collapse;
  width: 100%;
  margin: 12px 0 18px;
  font-size: 13.5px;
}
.rules-table th, .rules-table td {
  border: 1px solid var(--border);
  padding: 6px 10px;
  vertical-align: top;
  text-align: left;
}
.rules-table thead th {
  background: var(--bg-soft);
  font-weight: 600;
  color: var(--fg);
}
.rules-table tbody td:first-child { font-weight: 500; }

.empty { color: var(--muted); font-style: italic; padding: 60px 0; text-align: center; }
.error-banner {
  background: #ffe5e5; color: #8a1d1d; border: 1px solid #f5b5b5;
  padding: 12px 18px; margin: 0 28px 20px; border-radius: 4px; font-size: 13px;
}

/* ---------------------------------------------------------------- */
/* Mobile TOC drawer button — hidden on desktop, shown on narrow.    */
/* Lives in the .viewer-header-top row (opposite the back-link) and   */
/* scrolls away with the rest of the header chrome, rather than       */
/* floating fixed over the reading column. The base is hidden; the    */
/* mobile media block turns it on as an in-flow pill.                 */
.mobile-toc-toggle {
  display: none;
}
/* Row at the top of the viewer header holding the "All sections"    */
/* back-link and (on mobile) the "Sections" drawer trigger.          */
.viewer-header-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

/* ---------------------------------------------------------------- */
/* Archive verification: per-paragraph badge + link + side-by-side.  */
/*                                                                    */
/* Brief CODE_BRIEF_PATH_1_ARCHIVE_VERIFY_UI.md: never hide          */
/* divergence from the user. The badge and link are always visible    */
/* on every paragraph; the side-by-side panel is rendered uncollapsed */
/* whenever matches_archive is false.                                  */

/* 2026-05-18 UI cleanup: per-paragraph tier badge + archive link
   replaced by:
     - single page-top coverage banner (.coverage-banner)
     - inline tier marker on COARSE / engine_only paragraphs
       (.tier-marker), no marker on FINE
     - muted background wrapper on engine_only paragraphs
       (.para.engine-only)
   Legacy .archive-meta / .tier-badge / .archive-link selectors retained
   as no-ops so anyone re-enabling them doesn't break the layout. */

.coverage-banner {
  margin: 0 0 14px 0;
  padding: 10px 14px;
  background: #f5f7fa;
  border-left: 3px solid #b0bcc7;
  border-radius: 3px;
  color: #4a5560;
  font-size: 12.5px;
  line-height: 1.45;
}
.coverage-banner-link {
  color: #2563eb;
  text-decoration: none;
  border-bottom: 1px dotted #2563eb;
  margin-left: 4px;
  white-space: nowrap;
}
.coverage-banner-link:hover { text-decoration: underline; }

/* §2 visible provenance (2026-06-18 v2). The honesty floor is the always-on
   page-level summary (.provenance-summary). Per-paragraph dots are OPT-IN (the
   "Show provenance" toggle) so the law reads clean by default (Colin
   2026-06-04). When shown, a SINGLE archived marker (burnt amber) flags every
   archive-sourced paragraph — reconstructed/seed carry no dot. (v1 used two
   amber/red dots; Colin: too similar AND too dense, and the audit showed the
   dated/no-Statement split is not a reliability gradient — so one marker, with
   the nuance in the tooltip.) */
.prov-dot {
  display: inline-block;
  width: 7px; height: 7px;
  border-radius: 50%;
  margin-right: 5px;
  vertical-align: 1px;
  flex: none;
}
.prov-dot.prov-archived { background: #c2710c; border: 1px solid #8a4f08; }

/* Calm, always-on page-level provenance summary, shown only on pages that
   actually serve archived wording (a fully-reconstructed page stays clean). */
.provenance-summary {
  margin: 0 0 14px 0;
  padding: 8px 12px;
  background: #fbfaf6;
  border: 1px solid #ece6d8;
  border-left: 3px solid #c9a227;
  border-radius: 3px;
  color: #5a5346;
  font-size: 12px;
  line-height: 1.55;
}
.provenance-summary strong { color: #3a3530; }
.provenance-summary .prov-key { color: #5a5346; }
.provenance-summary .prov-dot { margin-left: 2px; }

.tier-marker {
  display: inline-block;
  margin: 0 0 4px 0;
  font-size: 11px;
  letter-spacing: 0.02em;
  font-style: italic;
}
.tier-marker.tier-coarse {
  color: #7a6a40;
}
.tier-marker.tier-engine-only {
  color: #8a2418;
  font-weight: 500;
}

/* The reconstruction IS the law (CLAUDE.md §2), not a downgraded tier — so
   engine-only paragraph bodies render plain, with no background shade or
   left-border "sideline". (Was: cream bg + rose border-left flagging them as
   lower-confidence; Colin: "shaded and sidelined for no reason".) */
.para.engine-only .pbody {
  background: none;
  border-left: none;
}

/* Legacy selectors kept as no-ops in case any path re-renders the
   old markup. The new render path does not emit these. */
.archive-meta { display: none; }
.tier-badge { display: none; }
.tier-help { display: none; }
.archive-link { display: none; }
.archive-link-unavailable { display: none; }

.archive-divergence {
  margin: 10px 0 4px 0;
  border: 1px solid #f1c1bb;
  border-left: 4px solid #c83a2a;
  border-radius: 4px;
  background: #fdf3f1;
  font-size: 13px;
}

.archive-divergence-header {
  padding: 8px 12px;
  border-bottom: 1px solid #f1c1bb;
  background: #fae8e3;
  color: #5a1d12;
  line-height: 1.4;
}

.archive-divergence-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  background: #f1c1bb;
}

.archive-divergence-col {
  background: #fff;
  padding: 10px 12px;
  min-width: 0;
}

.archive-divergence-label {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: #6b6b6b;
  margin-bottom: 6px;
}

.archive-divergence-body {
  white-space: pre-wrap;
  word-wrap: break-word;
  line-height: 1.5;
  color: #1f2937;
}

.archive-divergence-body ins.diff-engine {
  background: #fde7e7;
  color: #7a1f14;
  text-decoration: none;
  padding: 0 1px;
  border-radius: 2px;
}

.archive-divergence-body ins.diff-archive {
  background: #d8eedc;
  color: #1e5e2c;
  text-decoration: none;
  padding: 0 1px;
  border-radius: 2px;
}

@media (max-width: 720px) {
  .archive-divergence-grid {
    grid-template-columns: 1fr;
  }
  .archive-divergence-col + .archive-divergence-col {
    border-top: 1px solid #f1c1bb;
  }
}

/* v376 (2026-05-15): archive_defect state footnote. The engine output
   is verified-correct; the divergence is in the archive PDF / HTML
   extraction, not the engine. Render as a small subdued note (not the
   alarming red side-by-side panel used for engine_suspect). */
.archive-defect-footnote {
  margin: 6px 0 4px 0;
  padding: 6px 10px;
  border-left: 3px solid #d7a73a;
  background: #fdf6e3;
  color: #5b4b15;
  font-size: 12px;
  line-height: 1.4;
  border-radius: 3px;
}

.archive-defect-marker {
  display: inline-block;
  margin-right: 4px;
  color: #d7a73a;
  font-weight: 600;
}

.archive-defect-text {
  font-style: italic;
}

/* ---------------------------------------------------------------- */
/* Mobile responsive layout (≤ 720px). Three changes:                */
/*  1. Sidebar TOC moves out of flow into a slide-in drawer.         */
/*  2. Mobile-toc-toggle button shows in the viewer header.          */
/*  3. Paragraph layout collapses: ID stacks above body rather       */
/*     than living in a wide left margin, so depth-3/4 sub-paras     */
/*     have real room for text.                                      */
@media (max-width: 720px) {
  /* TOC becomes an off-canvas drawer that slides in from the left   */
  /* when the .mobile-open class is present. Sticky positioning is   */
  /* dropped (it would collapse to 0 height without content).        */
  .toc {
    position: fixed;
    top: 0; left: 0;
    height: 100vh;
    width: 80vw; max-width: 320px;
    transform: translateX(-100%);
    transition: transform 0.2s ease-out;
    z-index: 100;
    box-shadow: 2px 0 16px rgba(0,0,0,0.18);
  }
  .toc.mobile-open { transform: translateX(0); }

  /* In-flow pill in the header row (no longer fixed/floating, so it      */
  /* never sits over the body text). It scrolls away with the header;     */
  /* tapping it still opens the off-canvas .toc drawer.                   */
  .mobile-toc-toggle {
    display: inline-flex; align-items: center;
    flex: none;
    background: var(--accent); color: white; border: 0;
    padding: 5px 12px; font-size: 12.5px; font-weight: 600;
    border-radius: 4px;
    cursor: pointer;
  }
  .mobile-toc-toggle[hidden] { display: none; }
  .mobile-toc-toggle:focus { outline: none; }
  .mobile-toc-toggle:focus-visible {
    outline: 2px solid white;
    outline-offset: 2px;
  }

  /* Paragraph layout: stack ID above body. Drop the wide hanging    */
  /* margins so sub-paragraphs have real text width.                 */
  .para {
    display: block;
    grid-template-columns: none;
    padding: 6px 0;
  }
  .para[data-depth="0"] { padding-left: 0; padding-top: 8px; }
  .para[data-depth="1"] { padding-left: 1em; }
  .para[data-depth="2"] { padding-left: 2em; }
  .para[data-depth="3"] { padding-left: 3em; }
  .para[data-depth="4"] { padding-left: 4em; }
  .para .pid {
    display: block;
    text-align: left;
    margin-bottom: 2px;
    font-weight: 600;
    overflow: visible;
    white-space: normal;
  }
  .para .pbody { display: block; }
  /* The .cont children indent rule still applies but at a smaller   */
  /* scale to match the new leading.                                  */
  .para[data-cont-child="1"] .pbody { padding-left: 0.5em; }
  .para[data-cont-child="2"] .pbody { padding-left: 1em; }
  .para[data-cont-child="3"] .pbody { padding-left: 1.5em; }

  /* Headings sized down a touch on mobile.                          */
  .section-heading { font-size: 12px; }
  .subsection-heading { font-size: 12.5px; }

  /* Reading column: zero side margins on mobile.                    */
  .viewer-body { padding: 16px 14px 80px; }
  .reading-column { max-width: 100%; }

  /* Slider chrome a little tighter.                                  */
  .slider-wrap { padding: 8px 14px 10px; }
  .viewer-header { padding: 10px 14px; }

  /* The headline mobile fix (user feedback 2026-06-15: "the top
     date/warning bars take up more than half the screen, leaving little
     room to read the rules"). On desktop .top-sticky pins the whole
     ~509px control stack at top:0, which on a phone permanently covers
     >half the viewport while scrolling through the text. On mobile we
     drop the stickiness so the controls scroll away and the reading
     column gets the full screen; the date controls are reached again by
     scrolling back up. The bottom shadow is kept as a separator. */
  .top-sticky {
    position: static;
    padding-left: 0; padding-right: 0;
  }

  /* Declutter the pre-scroll stack so the first rule appears sooner.   */
  .viewer-header h2 { font-size: 16px; }
  /* "N effective dates" is redundant on mobile — the date ticks below
     already enumerate every date. */
  .viewer-header .meta { display: none; }
  /* Compact the work-in-progress banner.                              */
  .wip-banner-viewer { padding: 5px 9px; font-size: 12px; margin: 5px 0 2px; }
  /* The per-stop caption reserves ~2.7em even when empty; one line is
     enough on mobile now the controls scroll away (no sticky reflow to
     guard against). */
  .stop-caption-row { min-height: 1.4em; }

  /* --- Display toggles (mobile) ------------------------------------ */
  /* 2026-06-18 (Colin): the "Options" disclosure button was removed — its
     purpose was unclear. The three toggles now show on their face at every
     width; on mobile they stack full-width under the slider, with their short
     labels. */
  .slider-wrap .slider-row .toggles {
    display: flex; flex-wrap: wrap; gap: 6px 16px;
    width: 100%; margin-left: 0; margin-top: 6px;
  }
}

/* Typed date box under the viewer slider (2026-05-23 UI pass). Mirrors
   the contents-page "Or type a date" control. */
.date-jump-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
  font-size: 12.5px;
  color: #65656a;
}
.date-jump-row label { white-space: nowrap; }
.date-jump-row input {
  font-family: inherit;
  font-size: 13px;
  padding: 4px 8px;
  border: 1px solid #cbd5e1;
  border-radius: 4px;
  width: 130px;
}
.date-jump-row input:focus {
  outline: none;
  border-color: #c94907;
  box-shadow: 0 0 0 2px #fed7aa;
}
.date-jump-row input.invalid {
  border-color: #c0413c;
  background: #fef2f2;
}
.date-jump-error {
  color: #802a26;
  font-size: 12px;
}
