/* ============================================================
   OLL — Design tokens ("daylight instrument panel", Phase 25)
   ============================================================
   Single source of truth for every colour/type/geometry value used by
   the app's CHROME (panels, borders, controls, typography) — nothing in
   this file encodes what a LAYER's data means (except the dedicated
   Area Finder score palette shared between map and chrome). Crime's yellow-to-red
   scale, flood risk's two blues, the noise yellow/amber/red ramp, council
   tax's purple scale, every supermarket brand colour, every category
   marker colour in icon-config.js all stay exactly as they are, defined
   where they already live. Every future control/panel should read from
   these custom properties rather than introduce a new one-off value —
   see CLAUDE.md's own "Design tokens" decision record for the full
   rationale and where each token is actually consumed.

   Direction: Ordnance-Survey-draughting-meets-control-room-instrument —
   precise and restrained, not sci-fi/cyberpunk. The feeling comes from
   clarity (crisp hairlines, real telemetry, monospace numerals), not
   glow/gradients/decoration.

   Phase 25 recoloured the base palette: the chrome moved from the
   original teal-and-black night console to a daylit drafting table —
   cool-paper surfaces, ink-slate text, sharp corners and the blueprint
   grid kept. The one accent moved OFF teal (see --color-accent). The
   geometry, typography and every semantic/data colour are unchanged. --- */

/* --- Fonts: self-hosted, not a Google Fonts CDN link ---
   This project vendors every other JS/CSS dependency (Leaflet,
   Leaflet.markercluster) specifically so the map works "with no
   internet dependency beyond the tile images themselves" (CLAUDE.md) —
   a live CDN font load would quietly reintroduce exactly the kind of
   third-party runtime dependency that rule exists to avoid, just for
   page chrome. These six files (Latin subset only — this app's UI is
   English-only, London-scoped) were fetched once from Google Fonts'
   own CDN and committed here, same one-time-fetch-then-vendor pattern
   as every other vendored asset. SIL Open Font License 1.1 — see
   app/static/vendor/fonts/OFL.txt for the full licence text and each
   family's copyright notice. */
@font-face {
  font-family: "Space Grotesk";
  src: url("../vendor/fonts/SpaceGrotesk-Medium.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Space Grotesk";
  src: url("../vendor/fonts/SpaceGrotesk-Bold.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Inter";
  src: url("../vendor/fonts/Inter-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Inter";
  src: url("../vendor/fonts/Inter-SemiBold.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("../vendor/fonts/IBMPlexMono-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("../vendor/fonts/IBMPlexMono-Medium.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

:root {
  /* --- Colour — Phase 25 "daylight" recolour ---
     The chrome palette moved from the original teal-and-black night
     console to a daylit drafting table. If a new chrome colour is ever
     needed it belongs here as a new named token, not a hardcoded hex
     elsewhere. Semantic map colours retain their separate data meanings. */
  --color-base: #EDF1F7;   /* page/app background — cool paper, a hair blue so it
                              never reads warm next to the Esri "Light" basemap
                              or the Guided-Discovery teal overlay */
  --color-panel: #FFFFFF;  /* every panel/popup/module surface — one step lighter
                              than --color-base, same relationship as before */
  --color-accent: #4C5BD4; /* the ONE interactive accent — active states, focus,
                              hover, checked controls, the primary "+ Add pin"
                              action. Periwinkle-indigo, deliberately NOT teal:
                              the old #4FD1C5 accent was the same value the
                              Guided-Discovery matching overlay uses semantically
                              (discovery-matches.js), so chrome and overlay were
                              indistinguishable. 5.6:1 on white. */
  --color-accent-2: #8E96D9; /* secondary accent — a quieter, lighter sibling of
                                --color-accent: hover fills and secondary chrome.
                                Same hue family
                                so it cannot clash with any data colour; distinct
                                enough to read as "secondary, not active". NEW in
                                Phase 25 — the app was single-accent before. */
  --color-warning: #B26B00; /* warning/error — amber family, the "needs attention"
                               hue. Darkened from the original dark-theme #FFB454
                               (only ~1.7:1 on the new white panels) as a scoped
                               Phase 25 exception; same semantic role. */
  --color-border: #D2DAE8;  /* every hairline */

  /* --- Sidebar depth rails (Phase 26) ---
     Four steps of ONE hue — the --color-accent periwinkle-indigo — drawn
     as left-edge rails (plus each group's own top hairline) down the
     layer menu, so a glance tells you how deep a row sits: lighter and
     cooler on the outer sections where a rail spans a big block, deeper
     and more saturated on the row you actually click. Rails only — no
     group-body fills: the map is the content, and a body wash would
     compete with the semantic layer colours doing real work on it.
     These encode ROLE in the menu (section / sub-section / layer row /
     dependent sub-layer), NOT raw DOM-nesting depth — a group nested
     twice (Eating & drinking inside Food & Drink) keeps the sub-section
     rail and the extra indent carries the nesting. An active group's top
     border still switches to the full --color-accent (style.css's
     .layer-group-active), which stays louder than any rail so "a layer
     is on in here" never reads as "I'm N levels deep". Consumed only by
     the Phase 26 block in style.css. */
  --color-sidebar-depth-1: #B7C0E8; /* the six top-level sections -
                                       soft periwinkle mist, ~1.6:1 on white, a
                                       faint presence by design */
  --color-sidebar-depth-2: #909CDB; /* sub-section groups (Schools, Green spaces,
                                       Noise, Crime) - light periwinkle,
                                       sibling of --color-accent-2 #8E96D9 */
  --color-sidebar-depth-3: #6373C6; /* individual layer rows — mid periwinkle, sits
                                       lighter than the #4C5BD4 checked-box fill and
                                       is a thin rail, not a solid square */
  --color-sidebar-depth-4: #43508F; /* dependent sub-layers (Serious cycling
                                       injuries) — deep muted indigo, darker and
                                       lower-chroma than --color-accent so it reads
                                       as structure, not an active control */

  /* Derived text colours — three steps of emphasis, picked for contrast
     against BOTH --color-base and --color-panel and verified with a real
     contrast-ratio check (see CHANGELOG.md), not eyeballed. Same idea as
     the "muted subtitle" convention this project used pre-redesign
     (e.g. .tier-brand-subtitle), just tokenised. */
  --color-text: #1C2333;       /* primary body/prose text — ink-slate, 15.7:1 on white */
  --color-text-muted: #54607A; /* secondary text — subtitles, hints, meta — 6.3:1 on white */
  --color-text-dim: #8B95AA;   /* least prominent — placeholders, disabled, non-text
                                  borders ONLY; ~3.0:1, intentionally below AA for
                                  body text, same convention as the pre-Phase-25 token */

  /* Every dropdown/text/number/date input in the app shares one
     "recessed control" background — a touch darker than the white panel
     it sits on, aliased to --color-base rather than a new hex so a
     control always reads correctly relative to whichever panel/popup
     it's currently inside. */
  --color-input-bg: var(--color-base);

  /* --- Typography: three genuinely different faces, one job each ---
     Display: section/group headers + sidebar category labels ONLY —
     never body prose, never numerals.
     Body: everything else that isn't a numeral — popup prose, info-icon
     copy, general UI text. Deliberately unremarkable.
     Mono: EVERY numeral, anywhere in the UI — prices, coordinates,
     percentages, dates, council tax figures, crime rates, radius/
     duration/opacity values, sidebar "N active" counts. The single most
     important typographic rule in this pass (see the .oll-num utility
     class below) — applied at the point each value is rendered, not
     detected after the fact (CSS/regex can't reliably tell a numeral
     from surrounding prose). */
  --font-display: "Space Grotesk", "Arial Narrow", sans-serif;
  --font-body: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: "IBM Plex Mono", "Consolas", monospace;

  /* --- Chrome geometry: sharp, hairline, restrained --- */
  --border-width: 1px;
  --workspace-right-panel-width: 360px;
  /* Area Finder preference-match presentation, shared by map and chrome.
     Saturated rather than pastel: these fills sit over a detailed street
     basemap, and the former pastels were not separable from each other or
     from the map beneath them. Hue AND lightness both move across the
     scale, so the five bands stay ordered under red-green colour-vision
     deficiency, where hue alone would not. */
  --color-score-very-low: #C24149;
  --color-score-low: #D2732F;
  --color-score-moderate: #B08C1E;
  --color-score-good: #5A9670;
  --color-score-very-good: #26704B;
  /* Over budget: NOT a match band. Deeper, darker and more purple-red
     than "very low match", and carries a hatch as a second, non-colour
     cue so the two are told apart without opening a popup. */
  --color-score-over-budget: #8E1B2D;
  --color-discovery-unscored: #4fd1c5;
  /* Ordinary hex fill opacity. Chosen by screenshot comparison at 0.60 /
     0.65 / 0.70 over the real basemap: the lowest value at which all five
     bands separate while road and place names stay readable beneath. */
  --discovery-fill-opacity: 0.65;
  --discovery-over-budget-fill-opacity: 0.72;
  --radius: 0px;    /* panels/buttons/inputs: zero radius throughout */
  --radius-sm: 2px; /* the one deliberate exception — very small elements
                        (checkboxes, badge chips) keep a barely-there
                        radius so they read as "sharp" rather than
                        "broken", not a softening of the rule above */
  --radius-card: 6px; /* Phase 29A — a second, scoped exception for the
                        report view's collapsible cards ONLY. Proposed at
                        8px, shipped at 6px per review: still reads as a
                        rounded card, distinct from the zero-radius
                        instrument-panel chrome around it, without
                        "shouting" a second visual language the way 8px
                        did. Used nowhere outside .rcard/.rpill. */

  /* Faint blueprint-paper grid texture for panel backgrounds — a single
     definition here so every panel uses the exact same spacing/opacity
     rather than each hand-tuning its own. 24px spacing, 1px hairlines in
     a faint periwinkle (the --color-accent hue) at 6% over the white
     --color-panel. The pre-Phase-25 dark theme used 16% of the old slate
     --color-border; on white a much lower alpha is needed to keep the
     grid "barely visible, texture reference, not a visible pattern at
     normal viewing distance" as the original brief asked. Applied as
     `background-image` layered under `background-color: var(--color-panel)`. */
  --panel-grid-bg:
    repeating-linear-gradient(
      0deg,
      rgba(76, 91, 212, 0.06) 0px,
      rgba(76, 91, 212, 0.06) 1px,
      transparent 1px,
      transparent 24px
    ),
    repeating-linear-gradient(
      90deg,
      rgba(76, 91, 212, 0.06) 0px,
      rgba(76, 91, 212, 0.06) 1px,
      transparent 1px,
      transparent 24px
    );
}

/* --- Shared utility classes (consumed everywhere in checkpoints 2-7) ---
   Defined once here so a display label or a numeral looks IDENTICAL
   regardless of which file/component renders it. */

/* Section/group headers, sidebar category labels. Condensed, wide-
   tracked, uppercase — the brief's "small-caps or uppercase" choice
   picked here is uppercase + letter-spacing (Space Grotesk's own small-
   caps glyph coverage is unreliable across browsers for a self-hosted
   subset; uppercase + tracking reads the same "instrument label" way
   without depending on font-feature-settings support). */
.oll-label {
  font-family: var(--font-display);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

/* EVERY numeral in the UI — see the typography rule above. Tabular
   figures so a column of numbers (e.g. a council-tax A-H table) lines
   up, not just a font swap. */
.oll-num {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}
