@font-face {
  font-family: "Charis SIL";
  src: url("fonts/charis-sil-400.woff2") format("woff2");
  font-display: swap;
  font-style: normal;
  font-weight: 400;
}

@font-face {
  font-family: "Charis SIL";
  src: url("fonts/charis-sil-700.woff2") format("woff2");
  font-display: swap;
  font-style: normal;
  font-weight: 600 700;
}

@font-face {
  font-family: "IBM Plex Sans";
  src: url("fonts/ibm-plex-sans-var.woff2") format("woff2");
  font-display: swap;
  font-style: normal;
  font-weight: 400 600;
}

/*
  Role tokens mirror design-system/colors_and_type.css light-theme roles.
  Static Gazette builds cannot @import the package at publish time, so keep
  these hex values byte-aligned with that file's primitives/roles. Explorer's
  designTokens.ts sync test covers the same palette for MapLibre/Plot.
*/
:root {
  --canvas: #f5f7f1;
  --evidence: #ffffff;
  --evidence-inset: #eaeee3;
  --ink: #12241a;
  --ink-prose: #3d5044;
  --ink-quiet: #5a6d61;
  --rule: #d5ddcd;
  --rule-strong: #3f8f52;
  --action: #166534;
  --action-strong: #14572f;
  --mark: #faff69;
  --pending: #a8781f;
  --serif: "Charis SIL", "Iowan Old Style", charter, cambria, georgia, serif;
  --sans: "IBM Plex Sans", system-ui, sans-serif;
  --mono: ui-monospace, "SF Mono", menlo, consolas, monospace;
  --t-h1: clamp(28px, 3.5vw, 44px);
  --t-h2: clamp(23px, 2.5vw, 31px);
  --t-figure: 27px;
  --t-lede: 17px;
  --t-src: 11.5px;
  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  color: var(--ink);
  background: var(--canvas);
  font: 16px/1.6 var(--sans);
  -webkit-font-smoothing: antialiased;
}

.skip {
  position: fixed;
  z-index: 10;
  top: 0.5rem;
  left: 0.5rem;
  padding: 0.5rem 0.75rem;
  background: var(--ink);
  color: var(--canvas);
  transform: translateY(-150%);
}

.skip:focus {
  color: var(--canvas);
  transform: translateY(0);
}

a {
  color: var(--action);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}

a:hover {
  color: var(--action-strong);
}

:focus-visible {
  outline: 2px solid var(--action);
  outline-offset: 3px;
}

.site-nav {
  display: flex;
  width: min(73.75rem, calc(100% - 2.5rem));
  min-height: 4rem;
  margin-inline: auto;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  border-bottom: 1px solid var(--rule);
  font: 0.78rem/1.4 var(--mono);
}

.site-nav > div {
  display: flex;
  min-height: 44px;
  align-items: center;
  gap: 1.25rem;
}

.site-nav a {
  display: inline-flex;
  min-height: 44px;
  align-items: center;
}

.site-brand {
  color: var(--ink);
  font-family: var(--serif);
  font-size: 1.15rem;
  font-weight: 600;
  text-decoration: none;
}

.masthead,
main,
footer {
  width: min(73.75rem, calc(100% - 2.5rem));
  margin-inline: auto;
}

.masthead {
  padding: 3.5rem 0 1.5rem;
  border-bottom: 3px double var(--ink);
}

.masthead h1,
h2,
h3 {
  margin: 0;
  font-family: var(--serif);
  font-weight: 600;
  letter-spacing: -0.012em;
}

.masthead h1 {
  max-width: 19ch;
  font-size: var(--t-h1);
  line-height: 1;
}

.masthead .issue-date {
  max-width: 65ch;
  margin: 0.75rem 0 0;
  color: var(--ink-prose);
}

.disclaimer {
  max-width: 52ch;
  margin: 0.85rem 0 0;
  color: var(--ink-quiet);
  font-family: var(--sans);
  font-size: 12.5px;
  line-height: 1.65;
}

.disclaimer b {
  color: var(--ink);
  font-weight: 600;
}

.src {
  margin: 0.55rem 0 0;
  max-width: 36ch;
  color: var(--ink-quiet);
  font-family: var(--mono);
  font-size: var(--t-src);
  letter-spacing: 0.02em;
  line-height: 1.55;
}

.eyebrow,
.issue-date,
figcaption,
.receipts,
footer,
time {
  font-family: var(--mono);
}

.eyebrow {
  margin: 0 0 0.6rem;
  color: var(--action);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

main {
  padding: 2rem 0 4rem;
}

section {
  padding: 2rem 0;
  border-bottom: 1px solid var(--rule);
}

h2,
h3 {
  line-height: 1.15;
}

h2 {
  max-width: 24ch;
  font-size: var(--t-h2);
}

h3 {
  font-size: 1.25rem;
}

.lede,
.why,
.price-caveats {
  max-width: 70ch;
}

.lede {
  font-size: var(--t-lede);
}

.headline-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0;
  margin-top: 1rem;
  padding: 0;
  border: 1px solid var(--rule);
  background: var(--evidence);
}

.headline-grid article {
  min-width: 0;
  padding: 1.25rem;
  border-right: 1px solid var(--rule);
}

.headline-grid article:last-child {
  border-right: 0;
}

.headline-grid strong {
  display: block;
  font-family: var(--serif);
  font-size: var(--t-figure);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  line-height: 1;
}

.headline-grid span {
  display: block;
  margin-top: 0.35rem;
  color: var(--ink-quiet);
  font: 0.72rem/1.35 var(--mono);
}

figure {
  margin: 2rem 0 3.25rem;
}

.chart {
  display: block;
  width: 100%;
  height: auto;
  color: var(--action);
  overflow: visible;
}

.chart-axis {
  color: var(--ink);
}

.chart-axis line {
  stroke: var(--rule);
  stroke-width: 1;
}

.chart-axis text,
.axis-labels {
  fill: var(--ink-quiet);
  font: 12px var(--sans);
}

figcaption {
  margin-top: 0.6rem;
  color: var(--ink-quiet);
  font-size: 0.75rem;
}

.receipts {
  max-width: 72ch;
  margin-top: 0.8rem;
  padding-top: 0.65rem;
  border-top: 1px solid var(--rule);
  color: var(--ink-quiet);
  font-size: 0.6875rem;
  line-height: 1.5;
}

.receipts p {
  margin: 0.35rem 0;
}

.document-list li,
.finding-list li,
.issue-list li {
  margin: 0.7rem 0;
}

.issue-list a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

.document-list time {
  display: block;
  color: var(--ink-quiet);
  font-size: 0.72rem;
}

.price-check {
  border-block: 3px double var(--ink);
}

.price-scope,
.price-pin {
  color: var(--ink-quiet);
  font: 0.75rem/1.5 var(--mono);
}

.price-spread {
  margin: 1.5rem 0 2.5rem;
  padding: 1.25rem 1.5rem;
  border: 1px solid var(--rule);
  background: var(--evidence-inset);
}

.price-spread h3 {
  margin: 0.25rem 0 0.75rem;
}

.price-spread-ratio {
  font-size: 2.2em;
  font-weight: 700;
  margin-right: 0.35rem;
}

.price-spread-caveats {
  margin: 0.75rem 0;
  padding-left: 1.25rem;
  font-size: 0.85rem;
}

.price-service {
  margin: 2.25rem 0 3rem;
}

.price-table-wrap {
  max-width: 100%;
  overflow-x: auto;
}

.price-check table {
  width: 100%;
  min-width: 58rem;
  border-collapse: collapse;
  font: 0.78rem/1.4 var(--sans);
}

.price-check th,
.price-check td {
  padding: 0.7rem;
  border-bottom: 1px solid var(--rule);
  text-align: right;
  vertical-align: top;
}

.price-check thead th {
  color: var(--ink-quiet);
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.04em;
}

.price-check th:first-child,
.price-check td:first-child {
  text-align: left;
}

.price-detail td {
  padding: 0.8rem 1rem 1.1rem;
  text-align: left;
  background: var(--evidence-inset);
}

.price-detail p {
  margin: 0.35rem 0;
}

.price-receipt code {
  overflow-wrap: anywhere;
}

footer {
  padding: 1.75rem 0 3rem;
  color: var(--ink-quiet);
  font-size: 0.72rem;
}

@media (max-width: 700px) {
  .site-nav {
    width: min(100% - 2rem, 73.75rem);
    align-items: flex-start;
    flex-direction: column;
    gap: 0;
    padding-block: 0.65rem;
  }

  .site-nav > div {
    width: 100%;
    overflow-x: auto;
  }

  .site-nav > div > a {
    flex: 0 0 auto;
    white-space: nowrap;
  }

  .masthead,
  main,
  footer {
    width: min(100% - 2rem, 73.75rem);
  }

  .headline-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .headline-grid article:nth-child(2) {
    border-right: 0;
  }

  .headline-grid article:nth-child(-n + 2) {
    border-bottom: 1px solid var(--rule);
  }

  .chart-axis text {
    font-size: 10px;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    scroll-behavior: auto !important;
    transition-duration: 1ms !important;
  }
}

@media print {
  :root {
    --canvas: oklch(99.8% 0.001 122);
    --evidence: oklch(99.8% 0.001 122);
    --evidence-inset: oklch(96% 0.006 122);
    --ink: oklch(16% 0.012 155);
    --ink-prose: oklch(28% 0.012 155);
    --ink-quiet: oklch(38% 0.012 155);
    --rule: oklch(58% 0.016 140);
    --action: oklch(22% 0.03 152);
  }

  body {
    font-size: 11pt;
  }

  a {
    color: inherit;
  }

  figure {
    break-inside: avoid;
  }

  .price-table-wrap {
    overflow: visible;
  }

  .price-check table {
    min-width: 0;
    font-size: 7.5pt;
  }

  .price-service {
    break-before: page;
  }

  .hospital-price-row,
  .price-detail {
    break-inside: avoid;
  }
}

/* Public field guide. Shared color/type roles are appended by the renderer. */
.site-nav{width:100%;padding:22px max(20px,calc((100vw - 1280px)/2));background:var(--maroon);color:var(--paper);border:0;font-family:var(--sans);flex-wrap:wrap}
.site-nav a{color:var(--paper);font-family:var(--sans)}
.site-nav .site-brand{font-size:32px;letter-spacing:-.045em;font-weight:750;color:var(--gold)}
.site-nav a:hover{color:var(--gold)}
.site-nav :focus-visible{outline-color:var(--gold)}
.masthead{border-bottom:2px solid var(--maroon);padding-block:48px 32px}
h1,h2,h3{font-family:var(--sans);letter-spacing:-.035em;color:var(--maroon);font-weight:650}
.masthead h1{font-size:clamp(36px,5vw,64px);line-height:1.08}
.eyebrow{font-family:var(--sans);font-weight:600}
footer{background:var(--maroon);color:var(--paper);padding:36px max(20px,calc((100vw - 1180px)/2));max-width:none;width:100%}
footer a,footer .disclaimer{color:var(--paper)}
footer a:hover{color:var(--gold)}
footer :focus-visible{outline-color:var(--gold)}
@media(max-width:640px){.site-nav{gap:14px;padding:20px}.site-nav>div{flex-wrap:wrap;gap:0 20px}.site-nav .site-brand{width:100%}.masthead{padding-block:32px}.masthead h1{font-size:38px}}

/* Motion: ink on paper, the same vocabulary as avonlake.city (see
   design-system/FIELD_GUIDE.md). The masthead rule inks in on arrival,
   section rules are drawn as the reader reaches them, links thicken on
   hover. Figures never count up and no content waits on a scroll. Tokens
   (--ease-out, --d-fast, --d-state, --d-ink) arrive with the appended
   field-guide tokens. */
a {
  text-decoration-thickness: 1px;
  transition: color var(--d-fast) var(--ease-out),
    text-decoration-thickness var(--d-fast) var(--ease-out);
}
a:hover { text-decoration-thickness: 2px; }
.skip { transition: transform var(--d-fast) var(--ease-out); }
.masthead {
  position: relative;
  border-bottom-color: transparent;
}
.masthead::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -2px;
  height: 2px;
  background: var(--maroon);
  transform-origin: left;
  animation: ink-rule var(--d-ink) var(--ease-out) .1s both;
  pointer-events: none;
}
@keyframes ink-rule {
  from { transform: scaleX(0); }
}
@supports (animation-timeline: view()) {
  main > section:not(.price-check) {
    position: relative;
    border-bottom-color: transparent;
  }
  main > section:not(.price-check)::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: -1px;
    height: 1px;
    background: var(--rule);
    transform-origin: left;
    animation: ink-rule linear both;
    animation-timeline: view();
    animation-range: cover 0% cover 38%;
    pointer-events: none;
  }
}
@media (prefers-reduced-motion: reduce) {
  .masthead::after,
  main > section:not(.price-check)::after { animation: none !important; }
}
@media print {
  .masthead::after,
  main > section:not(.price-check)::after { animation: none !important; }
}
/* avonlake.city public field guide: maroon ink, gold, warm paper. */

@font-face {
  font-family: 'Field Guide Sans';
  src: url('fonts/ibm-plex-sans-var.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  color-scheme: light;
  --paper: oklch(96.8% .015 83);
  --sheet: oklch(98.5% .009 83);
  --maroon: oklch(30% .096 17);
  --gold: oklch(78% .139 84);
  --gold-hover: oklch(83% .13 84);
  --line: oklch(83% .029 65);
  --muted: oklch(46% .035 25);
  --bg: var(--paper);
  --surface: var(--sheet);
  --surface-2: oklch(93% .028 81);
  --ink-band: var(--maroon);
  --fg: oklch(25% .04 20);
  --fg-2: oklch(40% .035 25);
  --meta: var(--muted);
  --border: var(--line);
  --border-soft: oklch(88% .02 65);
  --forest-deep: var(--maroon);
  --forest: oklch(39% .105 17);
  --leaf: oklch(48% .105 17);
  --moss: oklch(57% .095 17);
  --sage: oklch(66% .07 17);
  --pale: oklch(76% .04 17);
  --mist: oklch(85% .02 17);
  --amber: var(--gold);
  --amber-ink: oklch(46% .085 70);
  --pending: var(--amber-ink);
  --volt: var(--gold);
  --volt-hover: var(--gold-hover);
  --volt-ink: var(--maroon);
  --stamp-live-bg: oklch(92% .025 17);
  --stamp-prep-bg: oklch(94% .04 84);
  --canvas: var(--paper);
  --evidence: var(--sheet);
  --evidence-inset: var(--surface-2);
  --ink: var(--fg);
  --ink-prose: var(--fg-2);
  --ink-quiet: var(--muted);
  --ink-margin: var(--muted);
  --rule: var(--line);
  --rule-soft: var(--border-soft);
  --rule-strong: var(--maroon);
  --action: var(--forest);
  --action-strong: var(--maroon);
  --action-on: var(--paper);
  --action-edge: var(--sage);
  --focus: var(--maroon);
  --focus-on-dark: var(--gold);
  --mark: var(--gold);
  --mark-ink: var(--maroon);
  --callout-ink: var(--maroon);
  --figure-lead: var(--gold);
  --cta-dark: var(--gold);
  --wordmark-tld: var(--gold);
  --slab: var(--maroon);
  --slab-feature: var(--maroon);
  --on-dark: var(--paper);
  --on-dark-1: oklch(93% .018 80);
  --on-dark-2: oklch(85% .025 70);
  --on-dark-3: oklch(82% .025 70);
  --on-ink-1: var(--paper);
  --on-ink-2: var(--on-dark-1);
  --on-ink-3: var(--on-dark-2);
  --on-ink-4: var(--on-dark-3);
  --panel-top-ink: var(--paper);
  --on-dark-rule: oklch(56% .065 20);
  --reg-1: var(--forest-deep);
  --reg-2: var(--forest);
  --reg-3: var(--leaf);
  --reg-4: var(--moss);
  --reg-5: var(--sage);
  --reg-6: var(--pale);
  --reg-7: var(--gold);
  --reg-8: var(--mist);
  --sans: 'Field Guide Sans','IBM Plex Sans',system-ui,sans-serif;
  --serif: var(--sans);
  --r-card: 4px;
  --r-tab: 4px;
  --bw-accent: 0px;
  --shadow: none;
  --shadow-sm: none;
  --shadow-lg: none;
  --shadow-in: none;
  --m-prose: 70ch;
  --t-h1: clamp(32px,4vw,48px);
  --t-h2: clamp(28px,3vw,44px);
  --t-h3: 24px;
  --t-figure: 27px;
  --t-src: 12px;
  --t-body: 17px;
  --maxw: 1360px;
  /* Motion: ink settles, it never bounces. Scroll-linked draws are linear;
     timed ones use the exponential ease-out. Reduced motion zeroes all of it. */
  --ease-out: cubic-bezier(.22, 1, .36, 1);
  --ease-in: cubic-bezier(.7, 0, .84, 0);
  --d-fast: .18s;
  --d-state: .24s;
  --d-ink: .7s;
}
/* ==========================================================================
   avonlake.city — Public Record Design System
   tokens.css — spacing, radius, elevation, motion, layout

   Source of truth: index.html (the redesigned home page).
   Load AFTER colors_and_type.css:
     <link rel="stylesheet" href="colors_and_type.css">
     <link rel="stylesheet" href="tokens.css">
   ========================================================================== */

:root{
  /* ---- Spacing -----------------------------------------------------------
     The home page runs an unrounded, document-derived scale. Nothing here is
     invented: these are the values actually used, deduped and named. */
  --sp-1:  4px;   /* record-field cell gap                     */
  --sp-2:  8px;   /* icon gap, chip padding                    */
  --sp-3:  12px;  /* button padding-block, panel row padding-y */
  --sp-4:  16px;  /* card grid gap                             */
  --sp-5:  20px;  /* card padding-inline (mobile gutter)       */
  --sp-6:  22px;  /* nav gap, issue-card padding-top           */
  --sp-7:  26px;  /* section head → content                    */
  --sp-8:  28px;  /* page gutter                               */
  --sp-9:  38px;  /* margin-note → content column              */
  --sp-10: 48px;  /* hero column gap                           */
  --sp-11: 64px;  /* band padding-block                        */
  --sp-12: 66px;  /* dark featured band padding-block          */

  /* Vertical rhythm, as shipped */
  --band-y:       var(--sp-11);  /* 64px · section.band padding-block */
  --band-y-dark:  var(--sp-12);  /* 66px · .feat padding-block        */
  --field-y:      60px;   /* .field padding-block                     */
  --hero-y:       56px;   /* .hero padding-top                        */
  --footer-y:     52px;   /* footer padding-top (56px bottom)         */
  --gutter:       var(--sp-8);   /* 28px · .wrap padding-inline       */
  --gutter-sm:    20px;

  /* ---- Layout ------------------------------------------------------------ */
  --maxw:      1180px;  /* .wrap                                            */
  --col-note:  172px;   /* .doc margin-note column                          */
  --col-cap:   240px;   /* .fieldhead right caption column                  */
  --hero-split: 1.12fr .88fr;
  --feat-split: 1.1fr .9fr;
  --foot-split: 1.5fr .8fr .8fr;
  --method-split: 64px 1fr 1.15fr;
  --header-h:  62px;
  --topline-h: 3px;
  --cell:      13px;    /* record-field square (11px ≤560px)                */

  /* ---- Radius ------------------------------------------------------------
     Low and deliberate. 8px is the card; 4px is the control; 2–3px is data.
     999px exists ONLY on the register legend chips. Nothing else is a pill. */
  --r-card:   8px;
  --r-ctrl:   4px;
  --r-bar:    3px;
  --r-cell:   2px;
  --r-inset:  0 6px 6px 0;   /* callout rule, right-rounded only  */
  --r-tab:    0 8px 8px 8px; /* filing-tab card: top-left square  */
  --r-pill:   999px;         /* legend chips only                 */

  /* ---- Elevation ---------------------------------------------------------
     Shadows are green-tinted (rgba of --fg), never neutral black.
     Two-layer: a tight contact shadow plus a wide ambient one. */
  --shadow-sm: 0 1px 2px rgba(18,36,26,.05);
  --shadow:    0 2px 4px rgba(18,36,26,.04), 0 12px 28px rgba(18,36,26,.07);
  --shadow-lg: 0 4px 10px rgba(18,36,26,.06), 0 24px 48px rgba(18,36,26,.10);
  --shadow-in: inset 0 3px 10px rgba(0,0,0,.22);   /* :active press only     */

  /* ---- Borders ----------------------------------------------------------- */
  --bw:       1px;   /* every structural rule                                */
  --bw-note:  2px;   /* margin-note top rule (1px under 1000px)              */
  --bw-accent:3px;   /* callout left rule                                    */

  /* ---- Motion ------------------------------------------------------------
     One easing curve for everything. Four durations, all sub-second except
     the two narrative ones (the highlighter swipe and the split bar). */
  --ease:     cubic-bezier(.2,.7,.2,1);
  --d-fast:   .18s;   /* buttons, chips, rows, nav underline                 */
  --d-mid:    .25s;   /* record-field cell isolate                           */
  --d-reveal: .65s;   /* .rv scroll reveal (14px rise)                       */
  --d-count:  1000ms; /* count-up, cubic ease-out                            */
  --d-bar:    1.1s;   /* split-bar fill                                      */
  --d-hl:     .95s;   /* highlighter swipe, .3s delay                        */
  --lift:     -4px;   /* issue-card hover translateY (-1px for buttons)      */

  /* ---- Z ----------------------------------------------------------------- */
  --z-sticky: 50;
  --z-skip:   100;
}

/* --------------------------------------------------------------------------
   Primitives shared by every surface in this system.
   -------------------------------------------------------------------------- */
*{ box-sizing:border-box }

.wrap{ max-width:var(--maxw); margin:0 auto; padding:0 var(--gutter) }
@media(max-width:560px){ .wrap{ padding:0 var(--gutter-sm) } }

.card{ background:var(--evidence); border:var(--bw) solid var(--rule); border-radius:var(--r-card) }

/* Focus is a hard requirement, not a reset. Volt on dark, forest on light. */
:focus-visible{ outline:2px solid var(--focus); outline-offset:3px; border-radius:2px }
.on-dark :focus-visible{ outline-color:var(--focus-on-dark) }

/* Scroll reveal — an enhancement, never a precondition for reading content.
   The hidden state is gated on .js-rv, which app.js sets on <html> only once
   it has an observer attached for every .rv on the page. Blocked, failed or
   absent JS therefore leaves content visible rather than blank, and authors
   no longer have to remember to omit .rv on anything that matters. */
.rv{ transition:opacity var(--d-reveal) var(--ease), transform var(--d-reveal) var(--ease) }
.js-rv .rv{ opacity:0; transform:translateY(14px) }
.js-rv .rv.in{ opacity:1; transform:none }

@media(prefers-reduced-motion:reduce){
  *{ animation-duration:.001ms!important; animation-iteration-count:1!important;
     transition-duration:.001ms!important }
  .js-rv .rv{ opacity:1; transform:none }
  /* Rule 6: nothing is reachable only through motion. app.js pre-lights .hl,
     but the swipe is a CSS transform — without this, a reduced-motion reader
     with JS blocked loses the highlight the headline is written around. */
  .hl:before{ transform:scaleX(1) }
}
/* One public navigation shell, shared by the site and Gazette. */
header.public-header {
  position: relative;
  inset: auto;
  margin: 0;
  padding: 0;
  max-width: none;
  width: 100%;
  background: var(--maroon);
  color: var(--paper);
  border: 0;
  font-family: var(--sans);
  box-sizing: border-box;
}
header.public-header * { box-sizing: border-box; }
header.public-header .wrap {
  display: grid;
  grid-template-columns: auto minmax(180px, 1fr) auto;
  align-items: center;
  gap: 24px;
  width: calc(100% - 96px);
  max-width: 1360px;
  height: auto;
  margin: 0 auto;
  padding: 24px 0;
}
header.public-header .brand {
  color: var(--paper);
  font-family: var(--sans);
  font-weight: 750;
  line-height: 1;
  font-size: 39px;
  letter-spacing: -.045em;
  white-space: nowrap;
  text-decoration: none;
}
header.public-header .brand span { color: var(--gold); }
header.public-header .tag {
  order: initial;
  display: block;
  width: auto;
  max-width: none;
  margin: 0;
  padding: 0;
  border: 0;
  color: var(--paper);
  font: 400 12px/1.55 var(--sans);
  letter-spacing: normal;
}
header.public-header nav {
  position: static;
  display: flex;
  flex-flow: row nowrap;
  align-items: center;
  gap: 22px;
  width: auto;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
}
header.public-header nav a {
  display: flex;
  align-items: center;
  width: auto;
  min-height: 44px;
  margin: 0;
  padding: 0;
  border: 0;
  color: var(--paper);
  background: transparent;
  font: 400 15px/1.5 var(--sans);
  letter-spacing: normal;
  text-decoration: none;
  white-space: nowrap;
}
header.public-header nav a::after { display: none; }
header.public-header nav a[aria-current=page] {
  color: var(--gold);
  text-decoration: underline;
  text-underline-offset: 6px;
  text-decoration-thickness: 2px;
}
header.public-header a:hover { color: var(--gold); }
header.public-header :focus-visible {
  outline: 3px solid var(--gold);
  outline-offset: 4px;
}
header.public-header .menu-btn { display: none; }
.page-nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 24px;
  width: calc(100% - 96px);
  max-width: 1360px;
  margin: 0 auto;
  padding: 12px 0;
  border-bottom: 1px solid var(--line);
  font: 400 14px/1.5 var(--sans);
}
.page-nav > span { color: var(--muted); }
.page-nav a, .page-nav button {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--maroon);
}
.page-nav button { margin-left: auto; }
@media (max-width: 1150px) {
  header.public-header .wrap {
    width: calc(100% - 56px);
    grid-template-columns: auto 1fr;
    gap: 16px 24px;
  }
  header.public-header nav {
    grid-column: 1 / -1;
    justify-content: flex-end;
    padding-top: 10px;
    border-top: 1px solid var(--on-dark-rule);
  }
  .page-nav { width: calc(100% - 56px); }
}
@media (max-width: 700px) {
  header.public-header .wrap {
    width: calc(100% - 40px);
    grid-template-columns: 1fr auto;
    gap: 14px;
    padding: 20px 0;
  }
  header.public-header .brand { font-size: clamp(26px, 8.5vw, 33px); }
  header.public-header .tag { grid-column: 1 / -1; grid-row: 2; font-size: 11px; }
  header.public-header .menu-btn {
    grid-column: 2;
    grid-row: 1;
    display: block;
    min-width: 44px;
    min-height: 44px;
    margin: 0;
    padding: 8px 12px;
    border: 1px solid var(--on-dark-rule);
    border-radius: 3px;
    color: var(--paper);
    background: transparent;
    font: 400 13px/1.5 var(--sans);
    cursor: pointer;
  }
  header.public-header .menu-btn span { margin-left: 7px; }
  header.public-header nav {
    /* The wrap grid is `1fr auto` here; without spanning, the open nav sits in
       column 1 while column 2 stays reserved for .menu-btn, so its links wrap
       early. .tag above spans for the same reason. */
    grid-column: 1 / -1;
    grid-row: 3;
    display: none;
    justify-content: flex-start;
    flex-wrap: wrap;
    gap: 2px 25px;
  }
  header.public-header nav.open { display: flex; }
  html:not(.js-nav) header.public-header nav { display: flex; }
  html:not(.js-nav) header.public-header .menu-btn { display: none; }
  .page-nav { width: calc(100% - 40px); gap: 4px 18px; }
}
/* Motion. The shell shares one vocabulary with the pages it frames: a gold
   rule draws under the link you are about to take, the drawer settles in
   link by link, and same-origin navigation crossfades while the masthead
   holds still. Reduced motion collapses each to its final state. */
@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }
}
header.public-header { view-transition-name: masthead; }
header.public-header a { transition: color var(--d-fast) var(--ease-out); }
header.public-header nav a { position: relative; }
header.public-header nav a::after {
  content: "";
  display: block;
  position: absolute;
  left: 0;
  right: 0;
  bottom: 7px;
  height: 2px;
  background: var(--gold);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--d-state) var(--ease-out);
}
header.public-header nav a:hover::after,
header.public-header nav a:focus-visible::after { transform: scaleX(1); }
header.public-header nav a[aria-current=page]::after { display: none; }
@keyframes public-nav-in {
  from { opacity: 0; transform: translateY(-4px); }
}
@media (max-width: 700px) {
  header.public-header nav.open a {
    animation: public-nav-in .28s var(--ease-out) both;
    animation-delay: calc(var(--i, 0) * 35ms);
  }
  header.public-header nav.open a:nth-child(2) { --i: 1; }
  header.public-header nav.open a:nth-child(3) { --i: 2; }
  header.public-header nav.open a:nth-child(4) { --i: 3; }
  header.public-header nav.open a:nth-child(5) { --i: 4; }
  header.public-header nav.open a:nth-child(6) { --i: 5; }
}
@media (prefers-reduced-motion: reduce) {
  header.public-header * { transition: none; animation: none; }
}
@media print {
  header.public-header, .page-nav { display: none; }
}

/* High-zoom reflow: retain every control when even the compact row cannot fit. */
@media (max-width: 300px) {
  header.public-header .wrap {
    width: calc(100% - 32px);
    grid-template-columns: minmax(0, 1fr);
  }
  header.public-header .brand { font-size: 24px; }
  header.public-header .menu-btn {
    grid-column: 1;
    grid-row: 2;
    justify-self: start;
  }
  header.public-header .tag { grid-row: 3; }
  header.public-header nav { grid-row: 4; }
  .page-nav { width: calc(100% - 32px); }
}
/* ==========================================================================
   viz.css — figure styling for the shared server-rendered primitive:
   chart marks, map layers, the figure shell, and the disclosed data table.

   Markup contract (the ONLY emitter is LorainData.Viz.Figure.render/1):

     figure.viz[.viz--chart|.viz--map]
       > svg.viz__svg            (chart marks from LorainData.Viz.Chart,
                                    map layers from LorainData.Viz.Map)
       > figcaption.viz__figcaption
       > details.viz__table > summary + table

   Every colour below is a design-system token (design-system/tokens.css,
   design-system/field-guide-tokens.css) — no hex literals outside comments.
   No animation, no transition, no stylesheet import, no external asset
   reference: this figure must render the same offline, in print, or with
   CSS disabled.
   ========================================================================== */

/* ---- figure shell --------------------------------------------------------
   .viz--chart and .viz--map both resolve to the same shell; nothing here
   needs to differ between them, so no modifier rule is written for either. */
.viz{
  display:block;
  max-width:100%;
  margin:0 0 var(--sp-8);
}

.viz__svg{
  width:100%;
  height:auto;
  display:block;
  color:var(--ink); /* currentColor baseline for untoned marks and layers */
}

.viz__svg text{
  font-family:var(--sans);
  font-size:12px; /* viewBox user units; 12 reads as small caption type */
}

/* ---- caption --------------------------------------------------------------
   One line of `·`-separated spans (figure.ex omits absent optional ones, so
   ":not(:first-child)" always lands on whichever span renders first). */
.viz__figcaption{
  display:block;
  margin-top:var(--sp-3);
  font-family:var(--sans);
  font-size:var(--t-src);
  color:var(--ink-quiet);
}

.viz__figcaption > span:not(:first-child)::before{
  content:" · ";
  color:var(--rule);
}

.viz__caption{
  color:var(--ink);
}

.viz__receipt{
  color:var(--ink);
  text-decoration:underline;
  text-underline-offset:2px;
}

.viz__receipt:hover{
  color:var(--rule-strong);
}

/* ---- data table (details.viz__table) --------------------------------------
   No card wrapper (that needs --r-card, outside this file's token list) —
   just the site's rule/rule-soft border rhythm from .rt in app.css, and its
   own horizontal scroll so a wide matrix/small-multiples table never pushes
   the page sideways. */
details.viz__table{
  margin-top:var(--sp-3);
  overflow-x:auto;
  overflow-y:hidden;
}

details.viz__table summary{
  cursor:pointer;
  font-family:var(--sans);
  font-size:var(--t-src);
  color:var(--ink-quiet);
  padding:var(--sp-2) 0;
}

details.viz__table table{
  width:100%;
  border-collapse:collapse;
  margin-top:var(--sp-2);
}

details.viz__table[open] table{
  background:var(--evidence);
}

details.viz__table th,
details.viz__table td{
  padding:var(--sp-2) var(--sp-3);
  border-bottom:var(--bw) solid var(--rule-soft);
  font-size:var(--t-src);
  text-align:left;
  vertical-align:baseline;
  white-space:nowrap;
}

details.viz__table th{
  font-weight:600;
  color:var(--ink-quiet);
  border-bottom:var(--bw) solid var(--rule);
}

details.viz__table tbody tr:last-child td{
  border-bottom:0;
}

/* ---- chart vocabulary (LorainData.Viz.Chart) ------------------------------
   viz-mark--bar, --dot, --event, --segment take no modifier rule of their
   own: they read the shared .viz-mark fill (overridden per series by
   tone-1..8, same as --cell). */
.viz-axis{ color:var(--ink) }
.viz-axis line{ stroke:var(--rule); stroke-width:1px }
.viz-axis-label{ fill:var(--ink-quiet) }
.viz-grid line{ stroke:var(--rule-soft); stroke-width:1px }

/* Legacy vocabulary: Chart.line/2, .bars/2, and .heatmap/2 predate the
   viz-* rename and still emit chart-axis/axis-labels. The Gazette's own
   stylesheet (priv/gazette/templates/gazette.css) already carries these
   rules; the same primitives wrapped in Viz.Figure outside the Gazette
   need them here too, or their axis lines and labels render unstyled —
   no inline stroke on a bare <line>, default text fill instead of the
   theme-aware token. */
.chart-axis{ color:var(--ink) }
.chart-axis line{ stroke:var(--rule); stroke-width:1px }
.chart-axis text,
.axis-labels{ fill:var(--ink-quiet); font:12px var(--sans) }

.viz-mark{ fill:var(--ink) }
.viz-mark--line{ fill:none; stroke:var(--ink); stroke-width:2px }
.viz-mark--range{ fill:none; stroke:var(--ink-quiet); stroke-width:2px }
.viz-mark--tick{ stroke:var(--ink); stroke-width:2px }
.viz-mark--cell{ rx:var(--r-cell) }
.viz-mark--cell.is-empty{ fill:var(--evidence-inset) }
.viz-mark--step{ fill:var(--ink-quiet) }
.viz-mark--step.is-total{ fill:var(--ink) }

.viz-label{ fill:var(--ink) }
.viz-label--dim{ fill:var(--ink-quiet) }

.viz-legend{ font-family:var(--sans) }
.viz-legend__swatch{ rx:var(--r-cell) }
.viz-legend__label{ fill:var(--ink-quiet) }

/* tone-1..8 walk the field-guide register ramp (forest-deep -> mist);
   shared by stacked/share-bar segments, dot-matrix legends, matrix cells. */
.tone-1{ fill:var(--reg-1) }
.tone-2{ fill:var(--reg-2) }
.tone-3{ fill:var(--reg-3) }
.tone-4{ fill:var(--reg-4) }
.tone-5{ fill:var(--reg-5) }
.tone-6{ fill:var(--reg-6) }
.tone-7{ fill:var(--reg-7) }
.tone-8{ fill:var(--reg-8) }

/* State modifiers, generic across marks and map features alike. The map
   layer below overrides is-emphasized with a stroke change instead, since
   opacity there is fixed by the reference layer's own group (see
   .viz-layer--reference). */
.is-muted{ opacity:.55 }
.is-emphasized{ opacity:1 }
.is-positive{ fill:var(--reg-2) }
.is-negative{ fill:var(--rule-strong) }

/* A share-bar percentage is drawn right after its segment; on the four
   darkest register tones the default ink label would disappear. */
.viz-mark--segment.tone-1 + .viz-label,
.viz-mark--segment.tone-2 + .viz-label,
.viz-mark--segment.tone-3 + .viz-label,
.viz-mark--segment.tone-4 + .viz-label{ fill:var(--paper) }

/* ---- map vocabulary (LorainData.Viz.Map) ----------------------------------
   viz-ref--county takes no modifier rule: the base .viz-ref stroke, plus the
   reference layer's own currentColor, is enough. */
.viz-layer--reference{ color:var(--rule) }
.viz-ref{ stroke-width:1px }
.viz-ref--shoreline{ stroke:var(--ink-quiet) }
.viz-ref--municipality.is-emphasized{ stroke:var(--rule-strong); stroke-width:1.5px }

.viz-feature--polygon{ fill:var(--evidence-inset); stroke:var(--ink); stroke-width:1px }
.viz-feature--line{ fill:none; stroke:var(--ink); stroke-width:1.5px }
.viz-feature--point{ fill:var(--ink) }

.viz-scale,
.viz-north{ color:var(--ink-quiet) }
.viz-scale line,
.viz-north path{ stroke:var(--ink-quiet); fill:var(--ink-quiet) }
.viz-scale text,
.viz-north text{ fill:var(--ink-quiet) }
