/* ==========================================================================
   El Faro — SHARED DESIGN TOKENS. Canonical copy.
   --------------------------------------------------------------------------
   Served as /assets/faro-tokens.css on BOTH Pages projects: the main site
   (elfaro.network, project `elfaro`, this dir) and the regional instance
   (lagodechapala.elfaro.network, project `elfaro-lakechapala` — its build
   copies this file, same arrangement as nav.js). Link it BEFORE the app
   stylesheet on every page.

   DIRECTION (Jack, 2026-07-31): "Editorial Faro" — the system already live on
   the main site — extended across the whole network, keeping ONE move from the
   rejected "Faro Nocturno" proposal: the night band. The header and hero are
   dark in light mode AND dark mode, so the lighthouse is always burning at the
   top of the page. On the regional landing that band is a photograph of the
   lake behind a scrim; everywhere else it is flat --night-800.

   WHY THIS FILE EXISTS. Before it, "the theme" was four divergent copies:
   dir.css, cal.css (nominally a verbatim mirror of dir.css, actually already
   drifted), an inline palette on the regional landing, and another inline one
   in /sky/. An audit found 51 places where a color was written literally
   instead of read from a token — i.e. 51 places where swapping :root would NOT
   have reskinned the site. ~24 of those traced to a single missing idea: there
   was no token for "the ink that sits on a brand-colored fill", so every
   header, hero, footer, pill and filled chip hardcoded its own foreground.
   That family (--on-brand, --on-accent, --header-ink, --footer-ink) is the
   most important thing in this file.

   NAMING. Two schemes coexist on purpose. The main site's stylesheet and
   app.js read --paper/--hair/--muted/--accent-txt; the regional apps read
   --bg/--line/--ink-faint/--brand. Rather than rename tokens across seven live
   pages, the regional names are defined here as ALIASES of the canonical
   Editorial Faro ones. One set of values, two vocabularies, nothing to keep in
   sync by hand.

   RULES THAT CAME OUT OF THE ACCESSIBILITY AUDIT — do not quietly break them:
     - --line is DECORATIVE ONLY (~1.6:1). Any boundary a reader must perceive
       — a card edge, an input, a table rule — uses --line-strong, which clears
       3:1 on every surface. There is no 1.5:1 threshold in WCAG; an earlier
       draft invented one and passed itself against it.
     - Focus rings get outline-offset:2px, ALWAYS. A ring hugging a fill of the
       same hue computes to 1.00:1 — an invisible focus state on the primary
       button. The offset makes the ring's only neighbour the page.
     - --on-fill white is safe on --accent-txt, the --night- ramp and --brand
       ONLY. On --accent (the lighter beacon amber) it fails; that surface
       takes --on-accent, which is near-black.
     - Alpha washes derive from tokens via color-mix(), never by hand-decoding
       a token back into rgba() literals. Hand-decoded washes are how dir.css
       and cal.css drifted apart in the first place.
   No third-party fonts, no CDN, no cookies. Light + dark via
   prefers-color-scheme.
   ========================================================================== */

:root {
  /* ---- Editorial Faro canonical palette (light) ------------------------ */
  --paper:       #EFF2F0;
  --paper-2:     #F9FBFA;
  --ink:         #101619;
  --ink-soft:    #38433F;
  --muted:       #616B66;
  --hair:        #CBD3CF;
  /* Darkened from the main site's #A9B3AE, which computes to 1.79–2.07:1 against
     the four light surfaces — below the 3:1 SC 1.4.11 wants for a boundary a
     reader must perceive. Same hue and saturation, lightness only. */
  --hair-strong: #7A8981;
  --accent:      #C67C12;   /* beacon amber — fills, rules */
  /* Darkened from the main site's #9A5F08, which was 4.34:1 on --bg-soft (the
     adverse light surface) — a marginal miss on the link color. */
  --accent-txt:  #955C08;   /* deeper ochre — legible as text/links on paper */
  --accent-tint: #F4E7CF;
  --beam:        #E8A33D;
  --emergency:   #B23217;
  --on-ink:      #F4F6F5;

  /* ---- The night band (the one idea kept from "Faro Nocturno") ---------
     Editorial Faro's own dark ground pushed toward the lake: the same cool
     near-black family, with enough teal in it to read as water rather than
     as a generic dark bar. Deliberately NOT overridden in the dark block —
     the band looks identical at noon and at midnight, which is the point. */
  --night-900:   #060E12;
  --night-800:   #0C1E26;
  --night-700:   #123240;

  /* ---- Ink that sits ON a filled surface -------------------------------
     The family whose absence caused ~24 of the 51 audit findings. */
  --on-brand:        #F4F6F5;   /* on --accent-txt / --brand fills */
  --on-accent:       #241202;   /* on --accent / --beam fills (white FAILS) */
  --header-ink:      #EDF3F4;
  --header-ink-soft: #A9C2CB;
  --footer-ink:      #C6D5DA;
  --footer-ink-soft: #90A7B0;
  --footer-link:     #E8B968;
  --scrim:           rgba(6, 14, 18, .58);

  /* ---- Fonts (self-hosted; faces declared in styles.css) --------------- */
  --font-serif: 'Fraunces', Georgia, 'Times New Roman', serif;
  --font-sans:  'Archivo', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --font-mono:  'Spline Sans Mono', ui-monospace, 'Cascadia Code', Consolas, monospace;
  --font: var(--font-sans);

  /* ---- Status semantics (kept separate from the accent) ----------------
     --ok and --warn are one step darker than the values the main site shipped
     (#2f7d43 / #9A6300): measured on their own -bg pills they were 4.21 and
     4.19, just under AA. --bad already cleared. */
  --ok:     #2D7740;  --ok-bg:   #E7F1E9;
  --warn:   #925E00;  --warn-bg: #F6ECD7;
  --bad:    #A6482F;  --bad-bg:  #F4E3DD;
  --info:   var(--accent-txt);  --info-bg: var(--paper-2);
  /* The emergency CTA's fill, deliberately NOT scheme-dependent. --emergency
     lightens in dark mode so it stays legible as text on a dark ground, but
     white on that lighter red is 3.80:1 — and the emergency card button is the
     last control on this network that should be hard to read. */
  --emergency-fill: #B23217;

  --primary:     #2F6E8A;
  --primary-600: #245A72;

  /* ---- Shape & depth (editorial = near-square, hairlines, flat) -------- */
  --radius:      3px;
  --radius-sm:   3px;
  --radius-pill: 999px;
  --shadow:      0 1px 0 rgba(16,22,25,.04);
  --shadow-sm:   0 1px 0 rgba(16,22,25,.04);
  --shadow-md:   0 2px 0 rgba(16,22,25,.06);
  --shadow-lg:   0 12px 34px rgba(16,22,25,.14);
  --shadow-hover:0 2px 0 rgba(16,22,25,.06);

  --maxw: 1160px;
  --gap: 22px;
  --header-h: 56px;

  /* ---- Legacy aliases the main site's styles.css/app.js already read --- */
  --dark:        var(--ink);
  --text:        var(--ink);
  --light:       #E6EBE8;
  --line:        var(--hair);
  --card:        var(--paper-2);
  --card-solid:  var(--paper-2);
  --accent-600:  var(--accent-txt);

  /* ---- Regional-app vocabulary (aliases — same values, other names) ----
     dir.css / cal.css / the regional landing / /sky/ speak this dialect. */
  --bg:          var(--paper);
  --bg-soft:     #E6EBE8;
  --surface:     var(--paper-2);
  --surface-2:   #F3F6F4;
  --ink-faint:   var(--muted);
  --line-strong: var(--hair-strong);
  --brand:       var(--accent-txt);
  --brand-ink:   var(--ink);
  /* Derived, not hand-decoded — an earlier draft wrote rgba(154,95,8), which
     is the PRE-migration accent this same file retires 70 lines above. */
  --ring:        color-mix(in srgb, var(--accent-txt) 85%, transparent);

  /* ---- Confidence / verification (directory + calendar + article) ------
     The -ink variants exist for ONE case: text sitting on a 12–15% wash of its
     own colour (the chip/badge pattern). A colour is not legible on a tint of
     itself — measured live, --accent-txt on its own 14% wash is 3.82:1 — so
     the wash comes from the base token and the text from the -ink token. */
  --conf-ok:      #1B6B4E;
  --conf-ok-ink:  #145440;
  --conf-mid:     var(--accent-txt);
  --conf-mid-ink: #845207;
  --conf-low:     #A6482F;
  --conf-low-ink: #98422B;
  --accent-ink:   #845207;   /* --accent-txt on its own wash */
  --primary-ink:  var(--primary-600);

  /* ---- Calendar event types -------------------------------------------
     Retuned into the Editorial Faro family: same hue relationships as the
     placeholder set, pulled toward the cooler ground and darkened enough to
     clear 4.5:1 as text on --bg-soft, the adverse surface the earlier audit
     never tested. */
  --t-fiesta_patronal: #955C08;
  --t-religiosa:       #63479B;
  --t-civica:          #185C77;
  --t-cultural:        #96306F;
  --t-tianguis:        #276B43;
  --t-comunitaria:     #414E97;
  --t-musica:          #A82C56;
  --t-fallback:        #55636A;

  /* ---- Directory group colors -----------------------------------------
     Twelve groups, twelve hues. An interim six-hue set had four groups
     sharing --g-servicios, which collapsed the map/tile encoding; Jack asked
     for the full twelve back.
     Every value is solved, not picked: each clears 4.5:1 against --on-brand
     (the tile letter sits on this as a fill), 3:1 as a dot against all four
     surfaces of its own scheme, and CIE76 ΔE ≥ 15 from every sibling so the
     twelve stay tellable apart. Hues are spaced ≥26° around the wheel.
     Colour is never the only channel here — the tile carries a letter and the
     chip a written label — so this is scannability, not sole-cue encoding. */
  --g-autos:     #C84414;
  --g-comida:    #8F6B08;
  --g-hogar:     #5B7B1B;
  --g-hospedaje: #33802B;
  --g-salud:     #1E804F;
  --g-prof:      #1A7D81;
  --g-tiendas:   #2272C2;
  --g-comunidad: #3F50AB;
  --g-educacion: #8144A7;
  --g-cultura:   #B734AA;
  --g-mascotas:  #B9315F;
  --g-otros:     #67727B;

  /* ---- Dietary tags (food layer) --------------------------------------- */
  --diet-veg:   #276B43;
  --diet-vegan: #1B6B4E;
  --diet-gf:    #955C08;
}

@media (prefers-color-scheme: dark) {
  :root {
    --paper:       #0C1214;
    --paper-2:     #131B1E;
    --ink:         #EEF2F0;
    --ink-soft:    #C3CCC8;
    --muted:       #8B968F;
    --hair:        #222D30;
    /* Lightened from the main site's #38454A (1.58–1.90:1 on the dark
       surfaces) for the same SC 1.4.11 reason as the light value. */
    --hair-strong: #5B7078;
    --accent:      #E8A33D;
    --accent-txt:  #F0B45E;
    --accent-tint: #241C10;
    --beam:        #F2B65B;
    --emergency:   #E1543A;
    --on-ink:      #0C1214;

    /* --night-* is intentionally NOT overridden. The band is the same at
       noon and at midnight — that is the whole idea. */

    --on-brand:        #0C1214;
    --on-accent:       #241202;
    --header-ink:      #EDF3F4;
    --header-ink-soft: #A9C2CB;
    --footer-ink:      #C6D5DA;
    --footer-ink-soft: #90A7B0;
    --footer-link:     #E8B968;
    --scrim:           rgba(4, 9, 12, .62);

    --ok:   #6FBF73;  --ok-bg:   #12331C;
    --warn: #E0A33D;  --warn-bg: #33260F;
    --bad:  #D98A72;  --bad-bg:  #3A1F16;
    --info: var(--accent-txt);  --info-bg: var(--paper-2);

    --primary:     #6FB2CF;
    --primary-600: #9CCBE0;

    --light: #1B2529;

    --shadow:       none;
    --shadow-sm:    none;
    --shadow-md:    none;
    --shadow-hover: none;
    --shadow-lg:    0 16px 44px rgba(0,0,0,.6);

    --bg-soft:     #1B2529;
    --surface-2:   #1B2529;
    --ring:        color-mix(in srgb, var(--accent-txt) 75%, transparent);

    /* Dark mode: a tint of a light colour over a dark ground stays dark, so
       the base colour is already legible on it and -ink just lifts it. */
    --conf-ok:      #63C79E;
    --conf-ok-ink:  #8FDCBB;
    --conf-mid-ink: var(--accent-txt);
    --conf-low:     #E58C74;
    --conf-low-ink: #F0A894;
    --accent-ink:   var(--accent-txt);
    --primary-ink:  var(--primary-600);

    --t-fiesta_patronal: #F0B45E;
    --t-religiosa:       #B9A2EC;
    --t-civica:          #6FB2CF;
    --t-cultural:        #E88BC9;
    --t-tianguis:        #7FC98E;
    --t-comunitaria:     #939CEE;
    --t-musica:          #F0879F;
    --t-fallback:        #9BA9AF;

    --g-autos:     #EC6B3C;
    --g-comida:    #F4C134;
    --g-hogar:     #ABD84F;
    --g-hospedaje: #69C95E;
    --g-salud:     #51D694;
    --g-prof:      #4DD6DB;
    --g-tiendas:   #4994DF;
    --g-comunidad: #6977C7;
    --g-educacion: #9E67C1;
    --g-cultura:   #D058C4;
    --g-mascotas:  #D2567F;
    --g-otros:     #8A969E;

    --diet-veg:   #7FC98E;
    --diet-vegan: #63C79E;
    --diet-gf:    #F0B45E;
  }
}

/* ==========================================================================
   Shared primitives every app repeats. Defined once here so the chrome stops
   being re-hardcoded per app.
   ========================================================================== */

/* The night band. Flat by default; the regional landing layers a photograph
   underneath by setting --band-image on the element. */
.faro-band {
  background: var(--night-800);
  color: var(--header-ink);
}
.faro-band a { color: var(--footer-link); }

/* Focus. One rule, every app, offset always — see the header note. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 3px solid var(--ring);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Skip link — the first thing a keyboard user meets. */
.skip {
  position: absolute; left: -9999px; top: 0; z-index: 1000;
  background: var(--accent-txt); color: var(--on-brand);
  padding: 10px 14px; border-radius: 0 0 var(--radius) 0;
}
.skip:focus { left: 0; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}


/* ==========================================================================
   Explicit theme override hooks. No toggle ships today, but if one ever does
   it must win over the media query in BOTH directions. Generated from the two
   blocks above — an earlier hand-maintained copy of these in styles.css had
   silently drifted back to the pre-audit --hair-strong and --accent-txt.
   ========================================================================== */
:root[data-theme="light"] {
  --paper: #EFF2F0;
  --paper-2: #F9FBFA;
  --ink: #101619;
  --ink-soft: #38433F;
  --muted: #616B66;
  --hair: #CBD3CF;
  --hair-strong: #7A8981;
  --accent: #C67C12;
  --accent-txt: #955C08;
  --accent-tint: #F4E7CF;
  --beam: #E8A33D;
  --emergency: #B23217;
  --on-ink: #F4F6F5;
  --night-900: #060E12;
  --night-800: #0C1E26;
  --night-700: #123240;
  --on-brand: #F4F6F5;
  --on-accent: #241202;
  --header-ink: #EDF3F4;
  --header-ink-soft: #A9C2CB;
  --footer-ink: #C6D5DA;
  --footer-ink-soft: #90A7B0;
  --footer-link: #E8B968;
  --scrim: rgba(6, 14, 18, .58);
  --font-serif: 'Fraunces', Georgia, 'Times New Roman', serif;
  --font-sans: 'Archivo', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --font-mono: 'Spline Sans Mono', ui-monospace, 'Cascadia Code', Consolas, monospace;
  --font: var(--font-sans);
  --ok: #2D7740;
  --ok-bg: #E7F1E9;
  --warn: #925E00;
  --warn-bg: #F6ECD7;
  --bad: #A6482F;
  --bad-bg: #F4E3DD;
  --info: var(--accent-txt);
  --info-bg: var(--paper-2);
  --emergency-fill: #B23217;
  --primary: #2F6E8A;
  --primary-600: #245A72;
  --radius: 3px;
  --radius-sm: 3px;
  --radius-pill: 999px;
  --shadow: 0 1px 0 rgba(16,22,25,.04);
  --shadow-sm: 0 1px 0 rgba(16,22,25,.04);
  --shadow-md: 0 2px 0 rgba(16,22,25,.06);
  --shadow-lg: 0 12px 34px rgba(16,22,25,.14);
  --shadow-hover: 0 2px 0 rgba(16,22,25,.06);
  --maxw: 1160px;
  --gap: 22px;
  --header-h: 56px;
  --dark: var(--ink);
  --text: var(--ink);
  --light: #E6EBE8;
  --line: var(--hair);
  --card: var(--paper-2);
  --card-solid: var(--paper-2);
  --accent-600: var(--accent-txt);
  --bg: var(--paper);
  --bg-soft: #E6EBE8;
  --surface: var(--paper-2);
  --surface-2: #F3F6F4;
  --ink-faint: var(--muted);
  --line-strong: var(--hair-strong);
  --brand: var(--accent-txt);
  --brand-ink: var(--ink);
  --ring: color-mix(in srgb, var(--accent-txt) 85%, transparent);
  --conf-ok: #1B6B4E;
  --conf-ok-ink: #145440;
  --conf-mid: var(--accent-txt);
  --conf-mid-ink: #845207;
  --conf-low: #A6482F;
  --conf-low-ink: #98422B;
  --accent-ink: #845207;
  --primary-ink: var(--primary-600);
  --t-fiesta_patronal: #955C08;
  --t-religiosa: #63479B;
  --t-civica: #185C77;
  --t-cultural: #96306F;
  --t-tianguis: #276B43;
  --t-comunitaria: #414E97;
  --t-musica: #A82C56;
  --t-fallback: #55636A;
  --g-autos: #C84414;
  --g-comida: #8F6B08;
  --g-hogar: #5B7B1B;
  --g-hospedaje: #33802B;
  --g-salud: #1E804F;
  --g-prof: #1A7D81;
  --g-tiendas: #2272C2;
  --g-comunidad: #3F50AB;
  --g-educacion: #8144A7;
  --g-cultura: #B734AA;
  --g-mascotas: #B9315F;
  --g-otros: #67727B;
  --diet-veg: #276B43;
  --diet-vegan: #1B6B4E;
  --diet-gf: #955C08;
}
:root[data-theme="dark"] {
  --paper: #0C1214;
  --paper-2: #131B1E;
  --ink: #EEF2F0;
  --ink-soft: #C3CCC8;
  --muted: #8B968F;
  --hair: #222D30;
  --hair-strong: #5B7078;
  --accent: #E8A33D;
  --accent-txt: #F0B45E;
  --accent-tint: #241C10;
  --beam: #F2B65B;
  --emergency: #E1543A;
  --on-ink: #0C1214;
  --on-brand: #0C1214;
  --on-accent: #241202;
  --header-ink: #EDF3F4;
  --header-ink-soft: #A9C2CB;
  --footer-ink: #C6D5DA;
  --footer-ink-soft: #90A7B0;
  --footer-link: #E8B968;
  --scrim: rgba(4, 9, 12, .62);
  --ok: #6FBF73;
  --ok-bg: #12331C;
  --warn: #E0A33D;
  --warn-bg: #33260F;
  --bad: #D98A72;
  --bad-bg: #3A1F16;
  --info: var(--accent-txt);
  --info-bg: var(--paper-2);
  --primary: #6FB2CF;
  --primary-600: #9CCBE0;
  --light: #1B2529;
  --shadow: none;
  --shadow-sm: none;
  --shadow-md: none;
  --shadow-hover: none;
  --shadow-lg: 0 16px 44px rgba(0,0,0,.6);
  --bg-soft: #1B2529;
  --surface-2: #1B2529;
  --ring: color-mix(in srgb, var(--accent-txt) 75%, transparent);
  --conf-ok: #63C79E;
  --conf-ok-ink: #8FDCBB;
  --conf-mid-ink: var(--accent-txt);
  --conf-low: #E58C74;
  --conf-low-ink: #F0A894;
  --accent-ink: var(--accent-txt);
  --primary-ink: var(--primary-600);
  --t-fiesta_patronal: #F0B45E;
  --t-religiosa: #B9A2EC;
  --t-civica: #6FB2CF;
  --t-cultural: #E88BC9;
  --t-tianguis: #7FC98E;
  --t-comunitaria: #939CEE;
  --t-musica: #F0879F;
  --t-fallback: #9BA9AF;
  --g-autos: #EC6B3C;
  --g-comida: #F4C134;
  --g-hogar: #ABD84F;
  --g-hospedaje: #69C95E;
  --g-salud: #51D694;
  --g-prof: #4DD6DB;
  --g-tiendas: #4994DF;
  --g-comunidad: #6977C7;
  --g-educacion: #9E67C1;
  --g-cultura: #D058C4;
  --g-mascotas: #D2567F;
  --g-otros: #8A969E;
  --diet-veg: #7FC98E;
  --diet-vegan: #63C79E;
  --diet-gf: #F0B45E;
}
