/* ==========================================================================
   avonlake.city — Public Record Design System
   colors_and_type.css — color + typography foundations

   Source of truth: index.html (the redesigned home page), :root block lines 10–24
   and the inline register palette in the page script (REG[].c).
   Every hex below was READ from that file. OKLch values are computed
   equivalents, not re-picked colors.

   Spacing, radius, shadow, motion and layout live in tokens.css.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Charis SIL — the display face, self-hosted.
   SIL International, OFL 1.1 (fonts/OFL-CharisSIL.txt). A Bitstream Charter derivative,
   which is the face the source already named at fallback position 2.
   Two static weights, 28 KB total. Self-hosted, so the system still makes no
   third-party request. See preview/type-audit.html for why this is bound
   rather than left to the OS.
   -------------------------------------------------------------------------- */
@font-face{
  font-family:'Charis SIL';
  src:url('fonts/charis-sil-400.woff2') format('woff2');
  font-weight:400; font-style:normal; font-display:swap;
}
@font-face{
  font-family:'Charis SIL';
  src:url('fonts/charis-sil-700.woff2') format('woff2');
  font-weight:600 700; font-style:normal; font-display:swap;
}

/* --------------------------------------------------------------------------
   IBM Plex Sans — the interface face, self-hosted.
   IBM Corp., OFL 1.1 (fonts/OFL-IBMPlexSans.txt). One variable file covering
   400–600, 40 KB.

   Bound for the same reason the serif was: left to the OS, the sans resolved
   to SF Pro / Segoe UI / Roboto / Liberation-or-Arial depending on the reader,
   so the interface voice was whatever the machine happened to own — and the
   tail of that chain was Arial. Plex is humanist with engineered detailing
   (flared terminals, the tailed `l`, a distinctly drawn `a` and `g`), which
   gives the interface some grain without becoming decorative.

   It is also the body face the sibling product already declares (the Map
   Room's own design system), so the public site and the private operator
   surface now share an interface voice while keeping their own display faces.
   -------------------------------------------------------------------------- */
@font-face{
  font-family:'IBM Plex Sans';
  src:url('fonts/ibm-plex-sans-var.woff2') format('woff2');
  font-weight:400 600; font-style:normal; font-display:swap;
}

:root{
  /* ---- Canvas & ink ------------------------------------------------------
     A cool paper-green canvas, not white. White is reserved for evidence. */
  --bg:          #f5f7f1;  /* oklch(0.973 0.008 121.6)  page canvas          */
  --surface:     #ffffff;  /* oklch(1.000 0.000 89.9)   cards, panels, rows  */
  --surface-2:   #eaeee3;  /* oklch(0.943 0.015 123.0)  inset / footnote fill*/
  --ink-band:    #0f2a1a;  /* oklch(0.258 0.045 155.4)  footer slab          */

  --fg:          #12241a;  /* oklch(0.241 0.031 158.6)  primary ink  15.05:1 */
  --fg-2:        #3d5044;  /* oklch(0.411 0.031 157.0)  body prose    8.01:1 */
  --muted:       #5a6d61;  /* oklch(0.515 0.030 157.5)  captions      5.13:1 */
  --meta:        #596d62;  /* oklch(0.515 0.029 161.2)  margin notes  5.14:1
                              Darkened from #5f7368 in the readiness audit: the old
                              value was 4.31:1 on --evidence-inset, so a margin
                              note failed AA on one of the three surfaces it can
                              legally sit on. Now clears 4.5 on all three.        */

  --border:      #d5ddcd;  /* oklch(0.887 0.023 128.8)  1px structural rule  */
  --border-soft: #e4eadd;  /* oklch(0.929 0.018 127.2)  intra-card divider   */

  /* ---- The green ramp ----------------------------------------------------
     One hue family (~150° green) carries structure, action and data.
     Ordered dark→light; the record field uses it as a sequential scale. */
  --forest-deep: #14572f;  /* oklch(0.405 0.094 152.5)  dark bands, panel top*/
  --forest:      #166534;  /* oklch(0.448 0.108 151.3)  ACTION: links, CTA   */
  --leaf:        #3f8f52;  /* oklch(0.584 0.121 149.1)  live dot, 3rd series */
  --moss:        #6aa876;  /* oklch(0.676 0.098 149.4)  4th series           */
  --sage:        #8fb597;  /* oklch(0.737 0.059 151.1)  hover border, 5th    */
  --pale:        #b3cdb8;  /* oklch(0.823 0.040 151.0)  6th series           */
  --mist:        #cfd8c9;  /* oklch(0.871 0.023 132.6)  residual / "other"   */

  /* ---- Signal colors -----------------------------------------------------
     Volt is the highlighter. It marks ONE thing per screen: the number that
     is the story ($0), the marker-swipe on the headline, the primary CTA on
     a dark band. Amber is the only non-green: "not yet public" status. */
  --volt:        #faff69;  /* oklch(0.969 0.170 111.0)  highlighter          */
  --volt-hover:  #eaf04f;  /* pressed/hover state of a volt button           */
  --volt-ink:    #1a2410;  /* ink on volt              15.01:1               */
  --amber:       #a8781f;  /* oklch(0.606 0.116 77.7)   auditor register swatch */
  --amber-ink:   #8a5f12;  /* oklch(0.519 0.102 75.8)   "records requested"  */

  /* ---- Status chip fills (stamps) --------------------------------------- */
  --stamp-live-bg: #e9f2e8;  /* forest on this: 6.22:1 */
  --stamp-prep-bg: #f8f2e4;  /* amber-ink on this: 5.05:1 */

  /* ---- On-dark text ramp -------------------------------------------------
     Used inside .feat (forest-deep) and the footer (ink-band). */
  --on-dark:        #ffffff;
  --on-dark-1:      #e7efe4;  /* 7.34:1 on forest-deep  */
  --on-dark-2:      #b9cfb8;  /* 5.21:1 on forest-deep  */
  --on-dark-3:      #b6cbb6;  /* 5.02:1 on forest-deep  */
  --on-ink-1:       #e4efe1;  /* emphasis in footer prose */
  --on-ink-2:       #cddcc8;  /* 10.73:1 on ink-band    */
  --on-ink-3:       #9db19a;  /* 6.72:1 on ink-band     */
  --on-ink-4:       #8ba489;  /* 5.69:1 on ink-band, colophon only */
  --panel-top-ink:  #eaf1e8;

  /* ---- Register scale (data encoding) ------------------------------------
     The 197-match prototype field maps source-group volume to the green ramp, largest
     register darkest. --reg-7 (amber) is the one deliberate hue break:
     county auditor property records. Fills only — never bare outlines. */
  --reg-1: var(--forest-deep);  /* Council agendas & minutes   n=70 */
  --reg-2: var(--forest);       /* Boards & hearings           n=44 */
  --reg-3: var(--leaf);         /* Council legislation         n=39 */
  --reg-4: var(--moss);         /* City press releases         n=13 */
  --reg-5: var(--sage);         /* SEC EDGAR (local)           n=6  */
  --reg-6: var(--pale);         /* Schools board               n=5  */
  --reg-7: var(--amber);        /* County auditor property     n=4  */
  --reg-8: var(--mist);         /* 7 other source groups       n=16 */

  /* ---- Type stacks -------------------------------------------------------
     Three roles, three faces, never blurred:
       serif  = the voice (headlines, wordmark, every headline FIGURE)
       sans   = the interface (body, labels, nav, card prose)
       mono   = the apparatus (eyebrows, sources, counts, stamps, buttons)

     The serif is SELF-HOSTED (see @font-face above) because it is the brand's
     voice and because the fallbacks disagree about numerals: classic Georgia
     defaults to old-style figures, which silently breaks this system's rule
     that every headline figure is serif + tabular. Charis SIL is a Bitstream
     Charter derivative — the face already named at fallback position 3 — so
     binding it guarantees a face the system always intended, rather than
     introducing a new one. Cambria sits ahead of Georgia in the chain because
     it ships with Windows/Office and, unlike Georgia, has lining tabular
     figures by default: if the webfont ever fails to load, the figure rule
     still holds for most readers.

     The SANS is bound too (see the second @font-face). It was the last role
     still resolving to whatever the OS owned — SF Pro, Segoe UI, Roboto, or a
     Liberation/Arial metric clone at the tail — which made the interface voice
     unpredictable in exactly the way the display face had been. Plex is
     humanist rather than neutral-grotesque: it gives the interface grain
     without asking to be looked at.

     The MONO stays a system face on purpose: it carries short apparatus
     strings (eyebrows, counts, stamps), every candidate resolves to something
     competent, and it costs zero bytes. Its tracking tolerance is documented
     below because that is the variance which actually matters. */
  --serif: 'Charis SIL','Iowan Old Style','Charter',Cambria,'Georgia','Times New Roman',serif;
  --sans:  'IBM Plex Sans',system-ui,-apple-system,'Segoe UI','Helvetica Neue',sans-serif;
  --mono:  ui-monospace,'SF Mono','SFMono-Regular',Menlo,Consolas,monospace;

  /* ---- Type scale (observed) -------------------------------------------- */
  --t-h1:        clamp(28px,3.5vw,44px); /* serif 600 / 1.14 / -.019em       */
  --t-h2:        clamp(23px,2.5vw,31px); /* serif 600 / 1.18 / -.012em       */
  --t-h2-dark:   clamp(24px,2.9vw,36px); /* the one h2 on a dark band        */
  --t-figure-xl: 27px;   /* serif ledger value on dark                       */
  --t-figure:    21px;   /* serif panel-row value                            */
  --t-h3:        20px;   /* serif card title                                 */
  --t-h3-sm:     18px;   /* serif standards title                            */
  --t-lede:      17px;   /* sans, --fg-2, max 52ch                           */
  --t-body:      16px;   /* sans / 1.6                                       */
  --t-body-sm:   15px;   /* sans section sub-copy, callout rule              */
  --t-ui:        13.5px; /* sans nav, card prose, ledger label               */
  --t-ui-sm:     12.5px; /* sans legend chip, footer disclaimer              */
  --t-src:       11.5px; /* mono source line / counts                        */
  --t-eyebrow:   11px;   /* mono uppercase .16em                             */
  --t-stamp:     10px;   /* mono uppercase .11em — 10px is the SIZE FLOOR.
                            Was 9px in the source; raised because the stamp
                            carries status ("we hold this" vs "not yet
                            obtainable"), which is the last thing a reader
                            should have to squint at. Nothing goes below 10px. */

  --lh-tight: 1.14;   /* h1                     */
  --lh-head:  1.18;   /* h2, h3                 */
  --lh-body:  1.6;    /* body                   */
  --lh-prose: 1.5;    /* card prose             */
  --lh-mono:  1.7;    /* margin notes           */

  --ls-h1:      -.019em;
  --ls-head:    -.012em;
  --ls-brand:   -.025em;
  /* Mono tracking is tuned on SF Mono. On a wider mono (Cascadia Mono on
     Windows, Roboto Mono on Android) these read loose; on a narrower one they
     tighten. Treat each as a MAXIMUM with a documented tolerance — reduce
     toward the low end for a wide face, never increase past the value here. */
  --ls-eyebrow:  .16em;  /* eyebrow  · tolerance .12em–.16em */
  --ls-label:    .12em;  /* stamps, standards numbers   */
  --ls-btn:      .07em;  /* buttons                     */

  /* ---- Measure ---------------------------------------------------------- */
  --m-h1: 19ch;  --m-h2: 24ch;  --m-h2-dark: 22ch;
  --m-lede: 52ch; --m-prose: 58ch; --m-src: 72ch;

  /* ======================================================================
     SEMANTIC ROLE LAYER
     ----------------------------------------------------------------------
     Everything above is a PRIMITIVE — a named color with no opinion about
     where it goes. Everything below is a ROLE. Build with roles; reach for a
     primitive only when defining a new role.

     Why this layer exists: `--forest` was doing three unrelated jobs at once
     (the action color, register step 2, and structural dark) with no name for
     any of them. That is fine until you need a dark theme or a second status,
     at which point "make the links lighter" also silently moves a data
     series. Roles decouple the two.
     ====================================================================== */

  /* -- surfaces: the four-step evidence ladder -------------------------- */
  --canvas:        var(--bg);          /* the page. Paper, not screen.      */
  --evidence:      var(--surface);     /* white = "this is a record"        */
  --evidence-inset:var(--surface-2);   /* footnote strips, callouts         */
  --slab:          var(--ink-band);    /* footer / utility dark             */
  --slab-feature:  var(--forest-deep); /* the one lead-story dark band      */
  --rule:          var(--border);      /* structural 1px                    */
  --rule-soft:     var(--border-soft); /* divider INSIDE a container        */

  /* -- text ------------------------------------------------------------- */
  --ink:           var(--fg);          /* 15.05:1 on canvas                 */
  --ink-prose:     var(--fg-2);        /*  8.01:1                           */
  --ink-quiet:     var(--muted);       /*  5.13:1 captions, .src            */
  --ink-margin:    var(--meta);        /*  5.14:1 margin notes only         */

  /* -- action ----------------------------------------------------------- */
  --action:        var(--forest);      /* links, primary fill, eyebrow      */
  --action-strong: var(--forest-deep); /* pressed / hovered solid button    */
  --action-on:     #ffffff;            /* text on an action fill  7.13:1    */
  --action-edge:   var(--sage);        /* hover borders                     */
  --focus:         var(--forest);      /* 2px ring, 3px offset              */
  --focus-on-dark: var(--volt);        /* the ring inside any dark region   */

  /* -- emphasis: volt, and its four permitted roles ---------------------- */
  --mark:          var(--volt);        /* 1 · highlighter behind a word     */
  --figure-lead:   var(--volt);        /* 2 · ONE figure per data block     */
  --cta-dark:      var(--volt);        /* 3 · ONE primary CTA per dark band */
  --wordmark-tld:  var(--volt);        /* 4 · the footer TLD                */
  --mark-ink:      var(--volt-ink);    /* 15.01:1 on volt                   */

  /* -- evidence status --------------------------------------------------
     The product defines a SEVEN-state claim lifecycle (draft · open ·
     contested · corroborated · disproven · withdrawn · ready) on a single
     axis. The palette still carries only the green/amber pair — so status is
     encoded by ROLE, not by inventing five more hues. Anything not settled
     and not held reads amber; anything inert reads quiet.
     Full mapping table: IMPLEMENTATION.md § Status vocabulary.            */
  --status-held:      var(--forest);       /* corroborated · ready · active */
  --status-held-bg:   var(--stamp-live-bg);
  --status-pending:   var(--amber-ink);    /* contested · disproven · open-with-conflict */
  --status-pending-bg:var(--stamp-prep-bg);
  --status-quiet:     var(--muted);        /* draft · open · withdrawn      */
  --status-quiet-bg:  var(--surface-2);

  /* -- a rule that carries meaning ---------------------------------------
     --rule is a 1.29:1 hairline: it organises the page and must never be the
     only thing distinguishing two states. When a border IS the signal — a
     selected cell, a focused row, a form control's edge — use this instead.
     --sage was the obvious pick and was only 2.11:1 on the canvas, so it was
     rejected. --leaf is the lightest ramp step that clears the 3:1 WCAG 2.2
     non-text minimum on BOTH light surfaces: --leaf is 3.70:1 on --canvas and
     3.99:1 on --evidence.                                                  */
  --rule-strong:   var(--leaf);

  /* -- cartographic fills --------------------------------------------------
     The dashboard carries a Lake Erie map. Its previous fills were #d7e2ea
     (water) and #e6e6da (land) — the first of which is a BLUE, and a second
     hue is this system's first anti-pattern. Both are re-derived from steps
     the ramp already owns, so the map stays inside the one-hue rule and needs
     no new colour. Separation is 1.39:1 — enough to read as two regions
     without either competing with the data drawn on top.                   */
  --map-water:     var(--pale);
  --map-land:      var(--border-soft);

  /* -- ordinal confidence ramp -----------------------------------------
     `identity grade` (attested → identified → keyed → ambiguous) and the
     register scale are the same SHAPE of data: an ordinal series where
     darkest = strongest. They share the ramp on purpose — one hue, ordered
     by weight, never a traffic-light.                                     */
  --grade-1: var(--forest-deep);  /* attested   — reviewer-bound           */
  --grade-2: var(--forest);       /* identified — source-native identifier */
  --grade-3: var(--moss);         /* keyed      — name-key match only      */
  --grade-4: var(--mist);         /* ambiguous  — do not assert            */
}

/* ==========================================================================
   DARK THEME
   --------------------------------------------------------------------------
   Opt-in via `<html data-theme="dark">`. NOT a full inversion and not a new
   palette: the canvas is `--ink-band`, the slab the source already owns, and
   every text value is a ramp the source already measured. The three additions
   are a lifted surface ladder (same hue and chroma as --ink-band, stepped in
   OKLch), a lighter action color, and a lifted amber — because `--forest` is
   `--forest` 2.16:1 on this canvas, and `--amber` likewise too dark to read.

   Every pair below is measured, not estimated. Body text ≥ 4.5:1 and UI
   ≥ 3:1 against BOTH the canvas and the raised surface (WCAG 2.2 AA).
   ========================================================================== */
[data-theme="dark"]{
  color-scheme: dark;

  /* surfaces — oklch(L 0.045 155.4), L stepped from the source's own slab */
  --canvas:         #0f2a1a;  /* L .258 — this is --ink-band, unchanged     */
  --evidence:       #1d3828;  /* L .315 — 1.21:1 lift, reads as a card      */
  --evidence-inset: #2a4534;  /* L .363 — 1.46:1                            */
  --rule:           #3c5745;  /* L .430 — 1.93:1, visible as a structure    */
  --rule-soft:      #304b39;  /* L .385 — 1.60:1, divider inside a card     */
  --slab:           #0b2015;  /* one step BELOW canvas, so the footer still
                                 reads as a distinct slab in dark           */
  --slab-feature:   var(--forest-deep); /* unchanged — already a dark band  */

  /* text — the source's own on-ink ramp, all re-measured on this canvas    */
  --ink:        #e4efe1;  /* 12.98:1 canvas · 10.76:1 surface               */
  --ink-prose:  #cddcc8;  /* 10.73:1 · 8.90:1                               */
  --ink-quiet:  #9db19a;  /*  6.72:1 · 5.57:1                               */
  --ink-margin: #9fb2a3;  /*  6.86:1 canvas · 5.68:1 evidence · 4.69:1 inset  */

  /* action — --forest is 2.16:1 here and fails outright. Lifted past --moss
     until it clears AA on ALL THREE dark surfaces: the record table's header
     text is --action on --evidence-inset, where --moss managed only 3.74:1. */
  --action:        #7fbc8a;  /* 6.93:1 canvas · 5.74:1 evidence · 4.73:1 inset.
                                Lifted from --moss #6aa876 in the readiness audit:
                                moss measured 3.74:1 on --evidence-inset, and the
                                record table's header text is --action ON that inset,
                                so it was a live failure, not a theoretical one.  */
  --action-strong: #a1cea9;  /* 8.72:1 · hover goes LIGHTER on dark, so it had to
                                move up too when --action was lifted.           */
  --action-on:     #0f2a1a;  /* dark ink on a light-green fill             */
  --action-edge:   #6aa876;
  --focus:         var(--volt);  /* the ring the source already used on dark */

  /* status — same two meanings, lifted to clear AA on the dark surface    */
  --status-held:      #6aa876;  /* 4.53:1 on --evidence                     */
  --status-held-bg:   #0e2b18;  /* 5.43:1 with --status-held   */
  --status-pending:   #e0ae5d;  /* oklch(.78 .115 77.7) — --amber, lifted.
                                   7.60:1 canvas · 6.48:1 on its own chip    */
  --status-pending-bg:#3a2f1b;  /* 6.48:1 with --status-pending */
  --status-quiet:     #9db19a;
  --status-quiet-bg:  #2a4534;  /* 4.60:1 with --status-quiet   */

  /* grade ramp inverts: on dark, LIGHTEST = strongest, so weight still
     reads as confidence rather than flipping meaning                      */
  --grade-1: #cfd8c9;
  --grade-2: #8fb597;
  --grade-3: #3f8f52;
  --grade-4: #2a4534;

  /* a load-bearing rule and the map, lifted for the dark canvas */
  --rule-strong: #6aa876;   /* 5.47:1 on the dark canvas */
  --map-water:   #2f5a44;
  --map-land:    #26402f;

  /* volt is unchanged — it was always a dark-only color. 14.32:1 on the
     canvas, 15.89:1 on the slab.                                         */

  /* elevation: shadows do almost nothing on a dark canvas. Depth comes
     from the surface ladder plus a hairline, not from a drop shadow.      */
  --shadow-sm: 0 0 0 1px rgba(255,255,255,.04);
  --shadow:    0 0 0 1px rgba(255,255,255,.06), 0 8px 24px rgba(0,0,0,.35);
  --shadow-lg: 0 0 0 1px rgba(255,255,255,.08), 0 18px 44px rgba(0,0,0,.45);
}

/* --------------------------------------------------------------------------
   Base type — apply by pasting this file, then these three rules.
   -------------------------------------------------------------------------- */
body{
  background:var(--canvas); color:var(--ink);
  font-family:var(--sans); font-size:var(--t-body); line-height:var(--lh-body);
  -webkit-font-smoothing:antialiased;
}
h1,h2,h3{
  font-family:var(--serif); font-weight:600;
  line-height:var(--lh-head); letter-spacing:var(--ls-head); margin:0;
}
h1{ font-size:var(--t-h1); line-height:var(--lh-tight); letter-spacing:var(--ls-h1); max-width:var(--m-h1); }
h2{ font-size:var(--t-h2); max-width:var(--m-h2); }
h3{ font-size:var(--t-h3); }
a{ color:var(--action); text-decoration:none }
a:hover{ text-decoration:underline }

/* The apparatus: three mono utilities that carry the system's credibility. */
.eyebrow{ font-family:var(--mono); font-size:var(--t-eyebrow); letter-spacing:var(--ls-eyebrow);
          text-transform:uppercase; color:var(--action) }
.mono{ font-family:var(--mono); font-variant-numeric:tabular-nums }
.src{ font-family:var(--mono); font-size:var(--t-src); color:var(--ink-quiet);
      letter-spacing:.02em; line-height:var(--lh-body); max-width:var(--m-src) }

/* Every headline figure is serif + tabular. Never sans. */
.figure{ font-family:var(--serif); font-variant-numeric:tabular-nums }
