/* =========================================================================
   NL Tools — Brand CSS
   File: /system/nl-brand.css
   Version: v2.27 (24/07/2026)

   v2.27 — Rich-text entry canon completed (paired with NL.richText /
           NL.sanitiseHtml in nl-utils v1.24, promoted from the newsletter
           tool — second consumer after article-composer). Two additive
           pieces on the .fmt-toolbar widget: .fmt-toolbar--compact (slim
           variant for inline card contexts) and .fmt-edit (the editable
           contenteditable area under the bar: border, focus ring,
           :empty placeholder, paragraph/list/link typography, and explicit
           b/strong/i/em rules — the inherited body-level
           font-variation-settings:'wght' 400 pins the variable font's
           weight, so <b> was invisibly bold without them).
           Cache-bust ?v=24 -> ?v=25 in lockstep.

   v2.26 — .nl-cover__meta restyled as a bottom imprint: small, italic,
           muted — a document states its edition once, quietly, on the
           title page. Consumers place it last in the cover (after the
           division crests). Cache-bust ?v=23 -> ?v=24 in lockstep.

   v2.25 — Document-presentation canon (promoted from the Handbook editor +
           public reader, its second consumer — the promotion trigger).
           Three new component blocks, all additive:
             - .nl-doc — legal/governing document reading presentation:
               number gutter (.nl-art / .nl-clause), continuation paragraphs,
               nested list styles, bullet + unnumbered variants, depth tints,
               document tables (.nl-tbl), and read-mode click-to-copy number
               affordance (scoped :not(.is-editing) so editors keep their
               own chrome local).
             - .nl-cover — document title page: brand lockup, giant title,
               season line, small meta line, rule, division-crest row.
             - .nl-crumb — "you are here" breadcrumb strip (area › n · title)
               used with a scroll-spy; tools/readers keep the spy JS local.
           Editing chrome (.nl-doc.is-editing …), formatting toolbar and
           table row/col controls stay tool-local in the handbook editor.
           Cache-bust ?v=22 -> ?v=23 across the template + every tool head.

   v2.24 — Modal helper support (paired with NL.modal/confirm/prompt/alert in
           nl-utils.js). Two additive rules on the .modal block: .modal--sm
           (440px, for confirm/prompt/alert) and .modal__input (the text field
           NL.prompt renders — there was no canon form-input class). No visual
           change to existing modals. Cache-bust ?v=21 -> ?v=22 in lockstep
           with nl-utils ?v=22 -> ?v=23.

   v2.23 — Club-picker component support (paired with NL.clubPicker in
           nl-utils.js). Three additive rules on the canonical .club-picker
           block: .club-picker__option--active (arrow-key highlight, kept
           separate from :hover); .club-picker__input::placeholder now solid
           var(--text-muted) (was a per-tool color-mix at ~2:1, fails AA);
           and .club-picker__clear (opt-in clear button, promoted from the
           travel-planner local pattern). No visual change to existing
           callers — the new rules only apply once a tool adopts
           NL.clubPicker. Cache-busted ?v=20 → ?v=21 in lockstep with
           nl-utils.js ?v=10 → ?v=11 across the template + every tool head.

   v2.22 — Sticky topbar fix. Moved position:sticky off .topbar onto the
           #nlTopbar wrapper. The bar never actually pinned: .topbar's
           containing block is the shrink-wrapped #nlTopbar wrapper (same
           height as the bar), so sticky had no travel and released
           immediately on scroll. The wrapper is a direct child of <body>
           (the scroll container), so it pins correctly. Affects all tools.

   v2.21 — Compliance pass. All tools are in dev so this is the moment
           to finalise the palette: backwards-compat aliases retired,
           every call site moved to canonical names. After this commit
           the retired token names no longer resolve.
             - --info / --info-light → migrated to --blue / --blue-light
               across 11 tool files (index, tasks, attendance, meeting-
               notes, team-of-the-week, vacancies/submit, website-
               insights, dazn-vip, website-analysis, programme-packs,
               portal). Aliases deleted from brand.
             - --primary-dim → migrated to --primary-600 across all
               call sites (15 tool files + the .btn--accent:hover
               internal). Alias deleted.
             - --navy-mid → migrated to --navy-600 across all call
               sites. Alias deleted.
             - --navy-light → migrated to --navy-300 across all call
               sites. Alias deleted.
           The shade-ladder vocabulary is now the only way to say
           "lighter / darker than primary or navy".

   v2.20 — Palette tightening (style-guide review). Two duplications
           removed; hue-naming convention enforced.
           1. --info collapsed into --blue. The two were near-duplicate
              blues with different naming conventions (--info was
              semantic, every other colour was hue-named). New canon:
              --blue (#1565c0), --blue-light (#eef2ff, was --info-light).
              Visible shift: info pills / toasts / admin role chips
              moved from #3b82f6 (brighter info blue) to #1565c0
              (deeper UI blue). Pastel surfaces unchanged.
           2. Project palette --proj-1 / -2 / -3 / -4 / -5 / -6 now
              alias var(--navy) / --primary / --green / --amber /
              --purple / --blue directly. They were near-duplicates of
              the semantic hues with slightly different shades — the
              "tasks PROJ_COLOURS was authored before brand semantics
              firmed up" lineage. --proj-7 (deep navy slate) and
              --proj-8 (cool slate) stay as distinct hexes because no
              semantic equivalent exists. Visible shift: existing
              project tags in tasks move ~5% in hue toward the brand
              canonical greens/ambers/purples/blues. NL.projColours
              in nl-utils.js bumped to match (?v=9).
           3. Toolbar fix — .toolbar__search was missing input
              padding/border/radius, rendering as a tiny browser-
              default text box next to the styled .toolbar__filter
              dropdowns. Now matches .toolbar__filter styling exactly.
           Cache-busted via ?v=18 across every tool head in lockstep.

   v2.19 — Brand-compliance sweep. The "documented widget-internal
           exception" doctrine is rolled back: identity palettes that a
           second tool would plausibly want are now canon, with rationale
           per palette. Specifically:
           1. Solid shade ladders for primary and navy — --primary-50/100/
              200/300/400/500/600/700/800/900 derived from #9e0000, and
              --navy-50/100/.../900 derived from #223b7c. Computed once in
              OKLab and committed as literal hex so they render
              identically in every browser and in canvas/image-generation
              contexts. Use these instead of inline rgba() overlays —
              semi-opaque "white at 18%" effects become solid --navy-300
              (or whichever stop matches). [Legacy --primary-dim /
              --navy-mid / --navy-light aliases retired in v2.21.]
           2. Promoted from holiday-lieu: --cal-bh / --cal-other-text /
              --cal-worked / --cal-worked-text / --cal-rejected. Calendar
              event-type identity; next-caller-likely (rota, fixture
              calendar, leave wall).
           3. Promoted from travel-planner: --road-sign-m / --road-sign-
              a-bg / --road-sign-a-fg. UK national road-sign spec; next-
              caller-likely (any travel/ground-finder tool).
           4. Promoted from graphics/league-tables: --pos-champ / --pos-
              sf / --pos-qf / --pos-releg + the play-off and relegated
              fg/bg variants. NL competition position-band palette; used
              by canvas exports, so also exposed as NL.positionBands in
              nl-utils.js.
           5. Promoted from tasks: --proj-1 … --proj-8. Project-identity
              colour wheel; meeting-notes uses a subset of the same
              hexes, so both tools now read from canon.
           6. Promoted from graphics/article-composer: .fmt-toolbar
              component — rich-text formatting toolbar wrapper plus the
              button/select/separator/icon/danger styling. Any tool that
              grows a longform input is a next-caller.
           Cache-busted via ?v=17 across every tool head in lockstep.

   v2.18 — New .club-picker--select modifier. Same visual shell as
           .club-picker, but the typeable input is replaced by a
           click-to-toggle button showing the current selection (crest +
           name + chevron). For places where typing makes no sense and
           the caller wants a sheer dropdown with all options scrollable.
           Both variants render options identically (crest, name,
           division). Attendance uses .club-picker for the cup-fixture
           pickers (freetext welcome) and .club-picker--select for the
           admin "Focus on a club" selector (NL-only, no typing).
           Cache-busted via ?v=16 across every tool head in lockstep.

   v2.17 — Two promotions from attendance, each with a live caller, both
           clean enough to belong in brand:
           1. New --text-display token (clamp 40-56px) for hero stat
              digits that overrun --text-xl's 40px ceiling. Attendance
              uses it once for the Largest crowd figure.
           2. New .club-picker__option--freetext modifier (dashed top
              border, italic, red __option-div for "non-NL" tag). Lets
              callers surface a freetext-commit row INSIDE the dropdown
              alongside curated options, rather than the standalone
              footer .club-picker__freetext. Attendance uses it for
              non-NL FA Cup / FA Trophy opponents.
           (Cache-busted via ?v=15 originally; bumped to ?v=16 with v2.18.)

   Single source of truth for NL brand styling. Every tool page and the
   portal dashboard loads this file.

   STRUCTURE
   ──────────────────────────────────────────────────────────────────────────
   FOUNDATION
     - @font-face (carbona-variable)
     - Reset
     - :root design tokens (colours, spacing, radius, font)
     - Body defaults
     - Layout: #pageWrap, .main (fluid padding, wide max-width)

   WIDGETS (alphabetical, each self-contained)
     - Admin banner   .admin-banner
     - Button         .btn + variants
     - Club picker    .club-picker
     - Empty state    .empty-state
     - Form           .form-group + .form-grid + inputs + checkbox
     - Form panel     .form-panel
     - Icon system    .icon + sprite usage
     - Modal          .modal-backdrop + .modal + .modal__*
     - Page header    .page-header
     - Pill           .pill + state variants
     - Role pills     .role-* (extends .pill)
     - Section head   .section-head (page title + primary action)
     - Spinner        .spinner + keyframe
     - Stat cards     .stats + .stat + .stat__*
     - Success screen .success-screen (end-of-flow)
     - Table          .table + .table-wrap + loading/empty
     - Tabs           .tabs + .tab
     - Toast          .toast + states (positioned fixed, body-level)
     - Toolbar        .toolbar (filters/actions strip)
     - Topbar         .topbar (full component incl. profile dropdown)

   ADDING A NEW WIDGET
     1. Create a new section with a clear comment header.
     2. Use only existing tokens (var(--primary), var(--border) etc.) — never
        hardcode colours or sizes unless they are genuinely widget-internal.
     3. If a widget needs to override base styles, prefer a modifier class
        (e.g. .btn--accent) over !important.
     4. Bump version + add changelog entry below.
     5. Bump ?v= query in each tool's <link> tag.

   WHY !important IS USED ON CERTAIN CLASSES
     The layout structure of .stats, .stat, .table, .table-wrap, and their
     internal cells is !important because they define the base visual identity
     of core components across every tool. Colour-related properties on these
     classes are left without !important so tools can apply state modifiers,
     for example:
       .stat--live .stat__num     { color: var(--green); }
       .stat--approved .stat__num { color: var(--green); }
       .stat--soon .stat__num     { color: var(--amber); }
       .stat--pending .stat__num  { color: var(--amber); }
       .stat--pending             { border-left: 4px solid var(--amber); }
       .stat--expired .stat__num  { color: var(--red); }
       .stat--overdue .stat__num  { color: var(--red); }
       .stat--overdue             { border-left: 4px solid var(--red); }
       .stat--open .stat__num     { color: var(--navy); }
       .stat--resolved .stat__num { color: var(--text-muted); }
       .stat--deleted .stat__num  { color: var(--text-muted); }
       .stat--info .stat__num     { color: var(--blue); }
     These modifiers are defined per-tool today; promote into this file if a
     pattern becomes universal.

   IDENTITY PALETTES (promoted to canon — see v2.19)
     Default flipped in v2.19: identity palettes that a second tool would
     plausibly want now live here, not in tool-local definitions. The
     "documented widget-internal exception" doctrine had become a place
     where re-usable patterns hid.

     Promoted to canon:
       - --proj-1 … --proj-8           project identity (tasks + meeting-notes)
       - --cal-bh / --cal-other-text /
         --cal-worked / --cal-worked-text /
         --cal-rejected                calendar event-type identity (holiday-lieu)
       - --road-sign-m / --road-sign-
         a-bg / --road-sign-a-fg       UK road-sign spec (travel-planner)
       - --pos-champ / --pos-sf /
         --pos-qf / --pos-releg + po
         and r fg/bg variants          NL position-band palette (graphics)
       - .fmt-toolbar component        rich-text formatting bar (article-composer)

     Stays tool-internal (genuine one-offs, meaningless outside their tool):
       - claudio                       persona character identity
       - attendance                    --tier-nln/-nls competition tier
       - meeting-notes                 scratchpad paper aesthetic
       - GA channel palette            Google-defined Material colours
       - club crest LUT                data, not styling

     New rule of thumb: if you find yourself defining N+1 hex values in a
     tool-local :root block, ask "would another tool plausibly want
     these?" If yes, promote to this file. If no (truly identity-only),
     keep local with a comment.

   Changelog
   v2.16 (03/05/2026)
     - Promoted three darker-shade tokens to brand level — they were
       defined locally in 3+ tools (programme-packs, club-directory,
       claudio): --primary-dim, --navy-mid, --navy-light. All three
       derive from --primary / --navy via color-mix() so brand changes
       flow through automatically.
     - Added --red-deep and --amber-deep (color-mix darkening of --red
       and --amber). Captures the "darker-on-hover" pattern that
       appeared 7-9 times across tools as inline color-mix() calls.
     - Added --accent-live (#4ade80) — vivid neon green for "live now"
       pulse dots, real-time freshness markers. Reads visibly on red /
       navy / dark backgrounds where --green (#1a7030, desaturated
       forest) is too low-contrast. Promoted from meeting-notes'
       --live-green local.
     - Added .indicator--live widget — small pulsing/static dot using
       --accent-live. With .indicator--pulse modifier for the keyframe
       animation.
     - Added Identity-Palette policy block above this changelog —
       documents when local hex palettes are acceptable and how to
       comment them.

   v2.15 (03/05/2026)
     - Repaired corrupted header comment block (the .stat--* examples had
       leaked into prose).
     - Added tokens: --radius-sm/-lg/-pill, --transition-fast, --focus-ring,
       --tracking-tight/-wide/-wider.
     - Replaced hardcoded hex values with color-mix() of semantic tokens in
       .btn--danger, .btn--restore, .admin-banner, .topbar__dd-role--staff,
       .topbar__dd-section, .topbar__dd-item--active::after,
       .club-picker__freetext:hover.
     - Replaced both literal rgba(158,0,0,0.10) focus rings with
       var(--focus-ring).
     - Added :focus-visible outlines to .btn, .tab, .topbar__btn,
       .topbar__avatar, .topbar__dd-item for keyboard a11y.
     - Bumped low-contrast white-on-red text: .topbar__kicker 0.6 → 0.85;
       .modal__close idle 0.6 → 0.8.
     - Scoped .toast pointer-events: none to .toast:not(.show) so future
       dismissable toasts work.
     - .btn--accent is now an alias of .btn--primary (was duplicated rule).
     - Removed redundant box-sizing on .topbar (covered by reset).
     - Updated icon-system docblock to reflect actual button icon size (16px).
     - TODO comment added on .section-head h2 (clamp ceiling 15px contradicts
       the documented heading scale; left unchanged to avoid regressions).

   Follow-ups (deliberately deferred — each risks visible regressions):
     - Migrate widget font-sizes from raw px to --text-* tokens.
     - Deprecate .page-body / .page / .container in favour of .main.
     - Reconcile .role-* naming with BEM .pill--role-* convention.
     - Unify .success-screen and .empty-state into one .placeholder widget.
     - Reconcile divergent superadmin/admin/staff/club palettes between
       .role-* and .topbar__dd-role--* (currently superadmin is purple in
       role pills, red in topbar dropdown).
     - Backfill changelog history v2.2–v2.14 (currently missing).

   v2.1 (17/04/2026)
     - Significantly expanded fluid scaling for wide viewports.
       Previously: optimised for 1280-1360px effective viewports, wide
       screens (1920+ @ 100% zoom) looked too small/narrow.
       Now: smoothly scales up to ~1920px where content is ~56px stat
       numbers, 19px body text, 1700px max-width container.
     - .main max-width: 1400 → 1700px
     - Body font ceiling: 17px → 19px
     - Stat number ceiling: 48px → 56px
     - Stat card padding: now fluid
     - Topbar title ceiling: 22px → 24px
     - Section head h2: now fluid
     - .main padding ceiling: 40/32 → 56/44
     - Smaller viewports (1280-1536) unchanged — clamp() floors preserve them.

   v2.0 (17/04/2026)
     - Restructured file into Foundation + Widgets. Each widget is now a
       self-contained section with clear comment headers.
     - Removed duplicate "Modal" section.
     - Consolidated "Buttons" and "Button variants" into single .btn section.
     - Added file structure + policy header.

   v1.5 (17/04/2026)
     - Centralised tabs, modal, form-grid, section-head, spinner, loading-row,
       confirm-text, success-screen, .btn--accent, .btn--restore.

   v1.4 (17/04/2026)
     - Removed !important from colour properties so tool modifiers can
       override (e.g. .stat--live .stat__num).
     - Added .pill--approved (green).

   v1.3 (17/04/2026)
     - Fluid typography via clamp(): body, stat__num, topbar__title.
     - .main max-width 1200px → 1400px with fluid padding.

   v1.2 (17/04/2026)
     - Added !important to layout-critical classes (.stats, .stat, .table)
       so they establish a consistent ceiling across all tools.

   v1.0 (17/04/2026)
     - Initial centralised brand file.
   ========================================================================= */


/* =========================================================================
   FOUNDATION
   ========================================================================= */

/* Fonts */
@font-face {
  font-family: "carbona-variable";
  src: url("https://use.typekit.net/af/184cf2/0000000000000000774c3175/31/l?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3") format("woff2"),
       url("https://use.typekit.net/af/184cf2/0000000000000000774c3175/31/d?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n4&v=3") format("woff");
  font-display: swap;
  font-style: normal;
  font-weight: 200 900;
  font-stretch: normal;
}

/* Reset */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

/* Design tokens */
:root {
  /* Brand colours */
  --primary:     #9e0000;
  --navy:        #223b7c;

  /* Semantic */
  --red:         #d4380d;   /* semantic error/danger — shifted from crimson to red-orange to distinguish from --primary brand red */
  --red-light:   #fff1ec;
  --green:       #1a7030;
  --green-light: #edf7ee;
  --amber:       #c96f15;
  --amber-light: #fef6ec;
  --blue:         #1565c0;
  --blue-light:   #eef2ff;
  --purple:       #6a1b9a;
  --purple-light: #f3e5f5;

  /* Solid shade ladders for primary and navy (v2.19). Computed in OKLab
     once and committed as literal hex so they render identically in
     every browser and in canvas/image-generation contexts (Maps style,
     league-tables exports, etc.). Use these instead of inline rgba()
     overlays — a "white-on-navy at 18% opacity" effect should be a
     solid --navy-300 (or whichever stop matches) on a navy background.
     500 is the brand colour itself. Reach for the ladder by stop:
       50/100   tinted backgrounds, surface fills
       200/300  light borders, idle hovers, subtle pill backgrounds
       400      mid-contrast accents
       500      brand colour
       600      hover state on solid brand button
       700/800  emphasis on light surfaces, deep accents
       900      near-black text/icons that retain brand tint */
  --primary-50:  #fcf4f2;
  --primary-100: #f7e4e0;
  --primary-200: #ecc4be;
  --primary-300: #dfa197;
  --primary-400: #c56659;
  --primary-500: #9e0000;
  --primary-600: #7e0000;
  --primary-700: #600000;
  --primary-800: #430000;
  --primary-900: #250000;

  --navy-50:  #f3f5f9;
  --navy-100: #e2e6f0;
  --navy-200: #c0cade;
  --navy-300: #9baac9;
  --navy-400: #6277a7;
  --navy-500: #223b7c;
  --navy-600: #192e63;
  --navy-700: #11214a;
  --navy-800: #091533;
  --navy-900: #03081b;

  --red-deep:    color-mix(in srgb, var(--red)     80%, black);
  --amber-deep:  color-mix(in srgb, var(--amber)   70%, black);

  /* Live indicator — vivid neon green for "live now" pulse dots and
     real-time freshness markers. Reads visibly on dark/red/navy
     backgrounds where var(--green) (#1a7030, desaturated forest) is
     too low-contrast. Used by .indicator--live below. */
  --accent-live: #4ade80;

  /* Promoted identity palettes (v2.19). See policy block at top of file. */

  /* Project identity — 8-colour wheel for tagging projects, meetings,
     ownership chips. Order is stable: project N always gets --proj-N.
     v2.20: --proj-1 … --proj-6 now alias the semantic hues directly
     (they were near-duplicates with slightly different shades from
     when tasks PROJ_COLOURS was authored before the brand semantics
     firmed up). --proj-7 / --proj-8 stay as distinct hexes — no
     semantic equivalent. JS callers needing the array form read
     NL.projColours from nl-utils.js, which mirrors these values. */
  --proj-1: var(--navy);     /* alias of --navy    */
  --proj-2: var(--primary);  /* alias of --primary */
  --proj-3: var(--green);    /* alias of --green   */
  --proj-4: var(--amber);    /* alias of --amber   */
  --proj-5: var(--purple);   /* alias of --purple  */
  --proj-6: var(--blue);     /* alias of --blue    */
  --proj-7: #1a2f63;         /* deep navy slate    */
  --proj-8: #374151;         /* cool slate         */

  /* Calendar event-type identity — promoted from holiday-lieu.
     Use these to type-colour calendar cells, leave-wall blocks, and
     rota markers. */
  --cal-bh:           #fffbf0;   /* bank holiday surface (warm cream)   */
  --cal-other-text:   #4a5568;   /* non-NL event label                   */
  --cal-worked:       #e3f2fd;   /* worked-on-leave surface (sky)        */
  --cal-worked-text:  #0d47a1;   /* worked-on-leave label                */
  --cal-rejected:     #c0392b;   /* rejected-request marker (distinct
                                    from --red so it reads as a state,
                                    not a generic error)                 */

  /* UK road-sign palette — promoted from travel-planner. Motorway is
     deep blue with white text (DfT spec); A-road is green ground with
     yellow numerals. Use --road-sign-m as a single-token background;
     A-road badges combine --road-sign-a-bg + --road-sign-a-fg. */
  --road-sign-m:      #2563ac;
  --road-sign-a-bg:   #007a33;
  --road-sign-a-fg:   #ffd900;

  /* NL competition position-band palette — promoted from graphics/
     league-tables. Used by canvas/image-generation exports for league
     tables and standings graphics. Mirror exposed as NL.positionBands
     in nl-utils.js for JS callers that need literal hex strings. */
  --pos-champ:        #7F99DC;   /* champion row background              */
  --pos-sf:           #3760C8;   /* play-off semi-final row              */
  --pos-qf:           #2D4FA4;   /* play-off quarter-final row           */
  --pos-releg:        #192C5C;   /* relegation row                       */
  --pos-c-fg:         #000000;   /* foreground on --pos-champ            */
  --pos-po-sf-bg:     #9aa3ad;   /* light play-off semi shade            */
  --pos-po-fg:        #000000;   /* foreground on play-off shades        */
  --pos-r-bg:         #000000;   /* relegated solid bg (when needed)     */
  --pos-r-fg:         #ffffff;   /* foreground on --pos-r-bg             */

  /* Surfaces */
  --white:       #ffffff;
  --off-white:   #f4f6f9;
  --text:        #1a2a44;
  --text-muted:  #5a6a82;
  --border:      #dde3ed;

  /* Layout */
  --radius:      6px;
  --radius-sm:   4px;
  --radius-lg:   10px;
  --radius-pill: 999px;
  --shadow:      0 2px 12px rgba(10, 22, 40, 0.10);

  /* Motion */
  --transition-fast: 0.15s;

  /* Focus ring — used by inputs and :focus-visible across widgets */
  --focus-ring: 0 0 0 3px color-mix(in srgb, var(--primary) 18%, transparent);

  /* Letter-spacing scale (for uppercase labels, kickers, buttons) */
  --tracking-tight: 0.04em;
  --tracking-wide:  0.08em;
  --tracking-wider: 0.12em;

  /* Typography scale — use these tokens for ALL font sizes in tool UI.
     Only exceptions: canvas/graphic output pixel values, editorial heading
     hierarchies inside composer tools, and monospace code blocks.

     --text-xs       10-13px  kickers, char counts, fine print
     --text-sm       12-15px  secondary text, hints, table cells, labels
     --text-base     14-17px  standard UI text, tile descriptions, body alt
     --text-md       16-20px  subheadings, card titles, prominent labels
     --text-lg       20-26px  section headings, page titles
     --text-xl       28-40px  display headings, stat numbers
     --text-display  40-56px  hero stat digits (attendance "Largest crowd"
                              etc.) — reach for this rarely; --text-xl
                              handles most "big number" needs.          */
  --text-xs:       clamp(10px, 0.6vw + 7px, 13px);
  --text-sm:       clamp(12px, 0.75vw + 8px, 15px);
  --text-base:     clamp(14px, 0.85vw + 10px, 17px);
  --text-md:       clamp(16px, 0.9vw + 12px, 20px);
  --text-lg:       clamp(20px, 1.2vw + 14px, 26px);
  --text-xl:       clamp(28px, 2vw + 16px, 40px);
  --text-display:  clamp(40px, 2.5vw + 18px, 56px);

  /* Typography */
  --font:        'carbona-variable', 'carbona', sans-serif;
}

/* Body defaults */
html, body {
  height: 100%;
}
body {
  font-family: var(--font);
  font-size: clamp(16px, 0.9vw + 12px, 21px);
  line-height: 1.5;
  font-variation-settings: 'wght' 400;
  color: var(--text);
  background: var(--off-white);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* Layout: #pageWrap is hidden by default; auth-guard reveals it after auth. */
#pageWrap { display: none; }
/* Universal content container — fluid max-width 1700px on wide screens, scaling
   padding. Four aliases supported so any tool gets this for free:
     .main          — canonical name (newer tools)
     .page-body     — portal, login
     .page          — shared files, holiday-lieu, submit-style tools
     .container     — chase hq, legacy tools
   Tools can still override per-tool if they need a different width
   (e.g. submit page uses max-width: 720px for narrow single-column form). */
.main,
.page-body,
.page,
.container {
  max-width: 1700px;
  margin: 0 auto;
  padding: clamp(24px, 3vw, 56px) clamp(16px, 2.5vw, 44px) 70px;
}
@media (max-width: 700px) {
  .main,
  .page-body,
  .page,
  .container {
    padding: 20px 14px 60px;
  }
}


/* =========================================================================
   TYPOGRAPHY UTILITY CLASSES
   Use these on any element to apply the correct size + weight + colour.
   Tokens (--text-xs through --text-xl) remain in :root for direct CSS use.
   ========================================================================= */

/* Display — page heroes, stat numbers */
.text-display {
  font-size: var(--text-xl);
  font-weight: 900;
  font-variation-settings: 'wght' 900;
  color: var(--navy);
  line-height: 1.1;
  letter-spacing: -0.01em;
}

/* Heading — section and page titles */
.text-heading {
  font-size: var(--text-lg);
  font-weight: 900;
  font-variation-settings: 'wght' 900;
  color: var(--navy);
  line-height: 1.2;
}

/* Subhead — card titles, prominent labels */
.text-subhead {
  font-size: var(--text-md);
  font-weight: 700;
  font-variation-settings: 'wght' 700;
  color: var(--text);
  line-height: 1.3;
}

/* Body — standard prose and UI copy */
.text-body {
  font-size: var(--text-base);
  font-weight: 400;
  font-variation-settings: 'wght' 400;
  color: var(--text);
  line-height: 1.6;
}

/* Secondary — hints, descriptions, supporting copy */
.text-secondary {
  font-size: var(--text-sm);
  font-weight: 400;
  font-variation-settings: 'wght' 400;
  color: var(--text-muted);
  line-height: 1.5;
}

/* Label — kickers, uppercase tags, fine print */
.text-label {
  font-size: var(--text-xs);
  font-weight: 700;
  font-variation-settings: 'wght' 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  line-height: 1.4;
}

/* =========================================================================
   WIDGET: Button
   ========================================================================= */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 11px 20px;
  border-radius: var(--radius);
  font-size: 13px;
  font-weight: 900;
  font-variation-settings: 'wght' 900;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  cursor: pointer;
  border: none;
  font-family: var(--font);
  transition: all 0.15s;
  white-space: nowrap;
  text-decoration: none;
}
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
.btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }

/* Colour variants */
.btn--primary,
.btn--accent { background: var(--primary); color: var(--white); }
.btn--primary:hover:not(:disabled),
.btn--accent:hover:not(:disabled) { background: var(--primary-600); }

.btn--navy { background: var(--navy); color: var(--white); }
.btn--navy:hover:not(:disabled) { background: var(--navy-600); }

.btn--ghost {
  background: var(--white);
  color: var(--text);
  border: 1px solid var(--border);
}
.btn--ghost:hover:not(:disabled) { background: var(--off-white); }

.btn--danger {
  background: var(--red-light);
  color: var(--red);
  border: 1px solid color-mix(in srgb, var(--red) 30%, white);
}
.btn--danger:hover:not(:disabled) { background: color-mix(in srgb, var(--red) 12%, white); }

.btn--restore {
  background: var(--green-light);
  color: var(--green);
  border: 1px solid color-mix(in srgb, var(--green) 30%, white);
}
.btn--restore:hover:not(:disabled) { background: color-mix(in srgb, var(--green) 12%, white); }

/* Size variants */
.btn--sm { font-size: 12px; padding: 8px 14px; letter-spacing: 0.07em; }


/* =========================================================================
   WIDGET: Form
   ========================================================================= */
.form-group label {
  display: block;
  font-size: 11px;
  font-weight: 800;
  font-variation-settings: 'wght' 800;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-muted);
  margin-bottom: 6px;
}
.form-group label .req { color: var(--primary); margin-left: 2px; }

.form-group input,
.form-group select,
.form-group textarea {
  width: 100%;
  padding: 10px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-size: 15px;
  font-family: var(--font);
  font-variation-settings: 'wght' 400;
  color: var(--text);
  background: var(--white);
  transition: border-color 0.15s, box-shadow 0.15s;
}
.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: var(--focus-ring);
}
.form-group textarea { resize: vertical; min-height: 100px; }

/* Layout: two-column grid */
.form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}
.form-group.span2 { grid-column: 1 / -1; }
@media (max-width: 500px) {
  .form-grid { grid-template-columns: 1fr; }
}

/* Extras */
.form-hint { font-size: 11px; color: var(--text-muted); }
.char-count {
  font-size: 11px;
  color: var(--text-muted);
  text-align: right;
}
.datetime-row { display: flex; gap: 8px; }
.datetime-row input[type="date"] { flex: 1; }
.datetime-row input[type="time"] { flex: 0 0 120px; }

/* Native checkbox override (browsers hate being styled consistently) */
input[type="checkbox"] {
  width: 16px !important;
  height: 16px !important;
  padding: 0 !important;
  border: 1px solid var(--border) !important;
  border-radius: 3px !important;
  box-shadow: none !important;
  cursor: pointer;
  flex-shrink: 0;
  accent-color: var(--primary);
  -webkit-appearance: checkbox;
  appearance: checkbox;
}


/* =========================================================================
   WIDGET: Modal
   ========================================================================= */
.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(10, 22, 40, 0.65);
  z-index: 200;
  align-items: flex-start;
  justify-content: center;
  padding: 40px 16px;
  overflow-y: auto;
  display: none;
}
.modal-backdrop.open { display: flex; }

.modal {
  background: var(--white);
  border-radius: 10px;
  width: 100%;
  max-width: 640px;
  box-shadow: 0 16px 60px rgba(0, 0, 0, 0.3);
  overflow: hidden;
  margin: auto;
}
.modal--wide { max-width: 740px; }
.modal--sm   { max-width: 440px; }   /* NL.confirm / NL.prompt / NL.alert */

.modal__head {
  background: var(--primary);
  color: var(--white);
  padding: 16px 20px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-bottom: 7px solid var(--navy);
}
.modal__head h3 {
  color: var(--white);
  font-size: 14px;
  font-weight: 900;
  font-variation-settings: 'wght' 900;
  text-transform: uppercase;
  letter-spacing: 0.1em;
}
.modal__close {
  background: none;
  border: none;
  color: rgba(255, 255, 255, 0.8);
  font-size: 26px;
  cursor: pointer;
  line-height: 1;
  padding: 2px 6px;
  font-family: var(--font);
}
.modal__close:hover { color: var(--white); }
.modal__body { padding: 24px; }
.modal__footer {
  padding: 16px 24px;
  border-top: 1px solid var(--border);
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  background: var(--off-white);
}
.modal__footer--split { justify-content: space-between; }

/* Confirm modal helpers */
.confirm-text {
  font-size: 14px;
  line-height: 1.6;
  color: var(--text);
}
.confirm-job {
  font-weight: 800;
  font-variation-settings: 'wght' 800;
  color: var(--navy);
  margin-top: 8px;
}
/* Text field inside NL.prompt */
.modal__input {
  width: 100%;
  margin-top: 12px;
  padding: 9px 11px;
  font: inherit;
  font-size: 14px;
  color: var(--text);
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.modal__input:focus-visible { outline: none; box-shadow: var(--focus-ring); border-color: var(--primary); }


/* =========================================================================
   WIDGET: Pill
   ========================================================================= */
.pill {
  display: inline-block;
  padding: 4px 12px;
  border-radius: 20px;
  font-size: 11px;
  font-weight: 800;
  font-variation-settings: 'wght' 800;
  white-space: nowrap;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.pill--live     { background: var(--green-light); color: var(--green); }
.pill--approved { background: var(--green-light); color: var(--green); }
.pill--expired  { background: var(--red-light);   color: var(--red); }
.pill--rejected { background: var(--red-light);   color: var(--red); }
.pill--soon     { background: var(--amber-light); color: var(--amber); }
.pill--pending  { background: var(--amber-light); color: var(--amber); }
.pill--info     { background: var(--blue-light);  color: var(--navy); }


/* =========================================================================
   WIDGET: Section head (page title + primary action row)
   ========================================================================= */
.section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
  gap: 12px;
  flex-wrap: wrap;
}
/* TODO(brand-v3): clamp ceiling 15px contradicts the documented heading scale
   (--text-lg is 20–26px). Bumping it would visibly change every tool, so
   left as-is for now — resolve as part of the wholesale scale pass, NOT on its
   own. See system/brand-v3-scale-plan.md (the tools read small/narrow at a real
   1920×1200 @ 100% because the whole scale was tuned for a ~1280–1440 viewport). */
.section-head h2 {
  font-size: clamp(13px, 0.3125vw + 9px, 15px);
  font-weight: 900;
  font-variation-settings: 'wght' 900;
  color: var(--navy);
  text-transform: uppercase;
  letter-spacing: 0.1em;
}


/* =========================================================================
   WIDGET: Spinner
   ========================================================================= */
.spinner {
  display: inline-block;
  width: 16px;
  height: 16px;
  border: 2px solid rgba(255, 255, 255, 0.3);
  border-top-color: var(--white);
  border-radius: 50%;
  animation: nl-spin 0.7s linear infinite;
  vertical-align: middle;
  margin-right: 4px;
}
@keyframes nl-spin { to { transform: rotate(360deg); } }


/* =========================================================================
   WIDGET: Live indicator (vivid pulsing dot for "live now" / real-time)
   Use on red/navy/dark backgrounds where var(--green) reads too dark.
   Structure:
     <span class="indicator--live"></span>           — bare dot, no pulse
     <span class="indicator--live indicator--pulse"></span>  — pulsing
   Sizes default to 8px. Override with width/height inline if needed.
   ========================================================================= */
.indicator--live {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent-live);
  flex-shrink: 0;
  vertical-align: middle;
}
.indicator--live.indicator--pulse {
  animation: nl-live-pulse 1.4s ease-in-out infinite;
}
@keyframes nl-live-pulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent-live) 70%, transparent); }
  50%      { box-shadow: 0 0 0 5px color-mix(in srgb, var(--accent-live) 0%,  transparent); }
}


/* =========================================================================
   WIDGET: Stat cards
   ========================================================================= */
.stats {
  display: grid !important;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)) !important;
  gap: 12px !important;
  margin-bottom: 28px !important;
}
.stat {
  background: var(--white) !important;
  border: 1px solid var(--border);
  border-radius: var(--radius) !important;
  padding: clamp(18px, 1.5vw + 2px, 28px) clamp(16px, 1.25vw, 24px) !important;
  text-align: center !important;
  box-shadow: var(--shadow) !important;
}
.stat__num {
  font-size: clamp(36px, 2.5vw + 8px, 56px) !important;
  font-weight: 900 !important;
  font-variation-settings: 'wght' 900 !important;
  line-height: 1 !important;
  margin-bottom: 6px !important;
  color: var(--text);
}
.stat__label {
  font-size: var(--text-xs) !important;
  color: var(--text-muted);
  font-weight: 800 !important;
  font-variation-settings: 'wght' 800 !important;
  text-transform: uppercase !important;
  letter-spacing: 0.1em !important;
}


/* =========================================================================
   WIDGET: Success screen (end-of-flow)
   ========================================================================= */
.success-screen {
  text-align: center;
  padding: 48px 24px;
}
.success-screen__icon {
  font-size: 48px;
  margin-bottom: 16px;
}
.success-screen h2 {
  font-size: 22px;
  font-weight: 900;
  font-variation-settings: 'wght' 900;
  color: var(--navy);
  text-transform: uppercase;
  margin-bottom: 10px;
}
.success-screen p {
  font-size: 14px;
  color: var(--text-muted);
  max-width: 420px;
  margin: 0 auto;
  line-height: 1.7;
}
.success-screen .btn {
  margin-top: 28px;
}


/* =========================================================================
   WIDGET: Table (incl. loading + empty states)
   ========================================================================= */
.table-wrap { overflow-x: auto !important; }
.table {
  width: 100% !important;
  border-collapse: collapse !important;
  background: var(--white) !important;
  border-radius: var(--radius) !important;
  overflow: hidden !important;
  box-shadow: var(--shadow) !important;
  border: 1px solid var(--border) !important;
  font-size: 15px !important;
}
.table th {
  background: var(--navy) !important;
  color: var(--white) !important;
  font-weight: 800 !important;
  font-variation-settings: 'wght' 800 !important;
  font-size: 10px !important;
  text-transform: uppercase !important;
  letter-spacing: 0.1em !important;
  padding: 12px 16px !important;
  text-align: left !important;
  white-space: nowrap !important;
}
.table td {
  padding: 12px 16px !important;
  border-bottom: 1px solid var(--border) !important;
  vertical-align: middle !important;
}
.table tr:last-child td { border-bottom: none !important; }
.table tr:hover td { background: var(--off-white) !important; }

/* Loading/empty rows */
.loading-row td, .empty-row td {
  text-align: center;
  padding: 40px;
  color: var(--text-muted);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-weight: 700;
}


/* =========================================================================
   WIDGET: Tabs
   ========================================================================= */
.tabs {
  display: flex;
  gap: 4px;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 3px;
  margin-bottom: 16px;
}
.tab {
  flex: 1;
  text-align: center;
  padding: 8px 12px;
  border-radius: 4px;
  font-size: 11px;
  font-weight: 800;
  font-variation-settings: 'wght' 800;
  cursor: pointer;
  color: var(--text-muted);
  border: none;
  background: none;
  transition: all 0.15s;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-family: var(--font);
}
.tab.active { background: var(--primary); color: var(--white); }
.tab:hover:not(.active) { color: var(--text); }
.tab:focus-visible { outline: none; box-shadow: var(--focus-ring); }


/* =========================================================================
   WIDGET: Toast (body-level positioned, managed by NL.toast)
   ========================================================================= */
.toast {
  position: fixed;
  bottom: 24px;
  right: 24px;
  background: var(--navy);
  color: var(--white);
  padding: 12px 18px;
  border-radius: var(--radius);
  font-size: 11px;
  font-weight: 800;
  font-variation-settings: 'wght' 800;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
  z-index: 999;
  transform: translateY(80px);
  opacity: 0;
  transition: all 0.25s ease;
  max-width: 300px;
}
.toast:not(.show) { pointer-events: none; }
.toast.show { transform: translateY(0); opacity: 1; }
.toast--success { border-left: 4px solid var(--green); }
.toast--error   { border-left: 4px solid var(--red); }
.toast--info    { border-left: 4px solid var(--blue); }


/* =========================================================================
   WIDGET: Topbar (rendered into #nlTopbar by /system/nl-topbar.js)
   Includes: logo, title+kicker, profile avatar, profile dropdown
   ========================================================================= */
/* The wrapper (#nlTopbar, a direct child of <body>) carries the sticky so the
   bar pins to the viewport on scroll. Sticking .topbar itself failed because
   its containing block is this shrink-wrapped wrapper — same height as the bar,
   so it has no room to stay pinned. */
#nlTopbar {
  position: sticky;
  top: 0;
  z-index: 100;
}
.topbar {
  background: var(--primary);
  color: var(--white);
  padding: 0 20px;
  height: 72px;
  display: flex;
  align-items: center;
  gap: 14px;
  z-index: 100;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
  border-bottom: 7px solid var(--navy);
  width: 100%;
}
.topbar__logo {
  height: 42px;
  flex-shrink: 0;
}
.topbar__title-wrap {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  line-height: 1;
  gap: 3px;
}
.topbar__title {
  font-weight: 900;
  font-variation-settings: 'wght' 900;
  font-size: clamp(18px, 0.625vw + 12px, 24px);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--white);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.topbar__kicker {
  font-size: 9px;
  font-weight: 700;
  font-variation-settings: 'wght' 700;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: rgba(255, 255, 255, 0.85);
  white-space: nowrap;
}
.topbar__btn {
  background: none;
  border: 1px solid rgba(255, 255, 255, 0.3);
  color: var(--white);
  padding: 7px 14px;
  border-radius: var(--radius);
  font-size: 11px;
  font-weight: 700;
  font-variation-settings: 'wght' 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  cursor: pointer;
  transition: all 0.15s;
  font-family: var(--font);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
  flex-shrink: 0;
}
.topbar__btn:hover { background: rgba(255, 255, 255, 0.12); }
.topbar__btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.topbar__btn--icon { padding: 7px 10px; font-size: 14px; }

/* Profile avatar */
.topbar__profile { position: relative; flex-shrink: 0; }
.topbar__avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.5);
  color: var(--white);
  font-family: var(--font);
  font-weight: 800;
  font-variation-settings: 'wght' 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
  transition: all 0.15s;
}
.topbar__avatar:hover { border-color: rgba(255, 255, 255, 0.8); }
.topbar__avatar:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.topbar__avatar--staff { background: var(--navy); }
.topbar__avatar--staff-2 { font-size: 13px; }
.topbar__avatar--staff-3 { font-size: 11px; letter-spacing: 0; }
.topbar__avatar--staff-4 { font-size: 9px; letter-spacing: 0; }
.topbar__avatar--club {
  background: var(--white);
  padding: 3px;
}
.topbar__avatar--club img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  border-radius: 50%;
}

/* Profile dropdown */
.topbar__dropdown {
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  min-width: 280px;
  background: var(--white);
  color: var(--text);
  border-radius: 10px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.22);
  overflow: hidden;
  z-index: 200;
  border: 1px solid var(--border);
  font-family: var(--font);
  display: none;
}
.topbar__dropdown.is-open { display: block; }
.topbar__dd-head {
  padding: 14px 16px;
  border-bottom: 1px solid var(--border);
}
.topbar__dd-name {
  font-size: 14px;
  font-weight: 800;
  font-variation-settings: 'wght' 800;
  color: var(--text);
  margin-bottom: 2px;
}
.topbar__dd-email {
  font-size: 11px;
  color: var(--text-muted);
  font-weight: 400;
  margin-bottom: 8px;
  word-break: break-all;
}
.topbar__dd-role {
  display: inline-block;
  font-size: 8px;
  font-weight: 900;
  font-variation-settings: 'wght' 900;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  padding: 3px 8px;
  border-radius: 10px;
  background: var(--blue-light);
  color: var(--navy);
}
.topbar__dd-role--superadmin { background: var(--red-light); color: var(--primary); }
.topbar__dd-role--admin { background: var(--blue-light); color: var(--navy); }
.topbar__dd-role--staff { background: color-mix(in srgb, var(--text-muted) 12%, white); color: var(--text-muted); }
.topbar__dd-role--club {
  background: var(--white);
  border: 1px solid var(--border);
  color: var(--text);
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding-left: 4px;
}
.topbar__dd-role--club img { width: 14px; height: 14px; object-fit: contain; }
.topbar__dd-section {
  font-size: 9px;
  font-weight: 900;
  font-variation-settings: 'wght' 900;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--text-muted);
  padding: 10px 16px 6px;
}
.topbar__dd-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 16px;
  cursor: pointer;
  font-size: 13px;
  color: var(--text);
  font-weight: 600;
  font-variation-settings: 'wght' 600;
  border: none;
  background: none;
  width: 100%;
  text-align: left;
  font-family: var(--font);
  line-height: 1.2;
  text-decoration: none;
}
.topbar__dd-item:hover:not(:disabled) { background: var(--off-white); }
.topbar__dd-item:focus-visible { outline: none; box-shadow: inset var(--focus-ring); }
.topbar__dd-item-icon { font-size: 15px; width: 18px; text-align: center; flex-shrink: 0; }
.topbar__dd-item-label { flex: 1; }
.topbar__dd-item-badge {
  font-size: 8px;
  font-weight: 900;
  font-variation-settings: 'wght' 900;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  padding: 2px 6px;
  border-radius: 8px;
  background: var(--blue-light);
  color: var(--navy);
}
.topbar__dd-item--active {
  background: var(--off-white);
  cursor: default;
  color: var(--text-muted);
}
.topbar__dd-item--active::after {
  content: '• current';
  font-size: 10px;
  font-weight: 700;
  color: var(--text-muted);
  margin-left: auto;
}
.topbar__dd-divider { height: 1px; background: var(--border); }
.topbar__dd-item--danger { color: var(--primary); }

/* Mobile: Portal button becomes icon-only, title shrinks */
@media (max-width: 700px) {
  .topbar { padding: 0 14px; gap: 10px; }
  .topbar__btn-text-portal { display: none; }
  .topbar__btn--portal { padding: 7px 10px; }
  .topbar__title { font-size: 17px; }
  .topbar__dropdown { min-width: 260px; right: -8px; }
}

/* WIDGET: Empty state ─────────────────────────────────────────────────────
   Used when a list/table has no content to show.
   Structure:
     <div class="empty-state">
       <div class="empty-state__icon">📭</div>
       <div class="empty-state__title">No vacancies found</div>
       <div class="empty-state__text">Try adjusting your filters.</div>
     </div>
   __title and __text are optional. __icon can be an emoji or SVG.
*/
.empty-state {
  text-align: center;
  padding: 60px 20px;
  color: var(--text-muted);
}
.empty-state__icon {
  font-size: 48px;
  margin-bottom: 16px;
  line-height: 1;
}
.empty-state__title {
  font-size: 15px;
  font-weight: 700;
  font-variation-settings: 'wght' 700;
  color: var(--text);
  margin-bottom: 6px;
}
.empty-state__text {
  font-size: 13px;
  line-height: 1.6;
  max-width: 320px;
  margin: 0 auto;
}
/* Legacy alias — some tools use __msg instead of __text */
.empty-state__msg {
  font-size: 14px;
  font-weight: 600;
  font-variation-settings: 'wght' 600;
}

/* WIDGET: Admin banner ─────────────────────────────────────────────────────
   Shown at top of a tool when staff/admin is viewing in admin context.
   Blue-tinted background, navy text, optional action link.
   Structure:
     <div class="admin-banner">
       <span class="admin-banner__icon">🔧</span>
       <span class="admin-banner__text">You are viewing in admin mode.</span>
       <a class="admin-banner__link" href="#">Manage</a>
     </div>
*/
.admin-banner {
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--blue-light);
  border: 1px solid color-mix(in srgb, var(--blue) 30%, white);
  border-radius: var(--radius);
  padding: 12px 16px;
  margin-bottom: 20px;
  font-size: 13px;
  color: var(--navy);
  line-height: 1.4;
}
.admin-banner__icon { font-size: 18px; flex-shrink: 0; }
.admin-banner__text { flex: 1; line-height: 1.4; }
.admin-banner__link {
  font-size: 11px;
  font-weight: 800;
  font-variation-settings: 'wght' 800;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--white);
  background: var(--navy);
  padding: 6px 12px;
  border-radius: 5px;
  text-decoration: none;
  white-space: nowrap;
  flex-shrink: 0;
  transition: background 0.15s;
}
.admin-banner__link:hover { background: var(--navy-600); }

/* WIDGET: Role pills ────────────────────────────────────────────────────────
   Used to display user role. Apply to a <span class="pill role-{role}">.
   Extends the base .pill class — always use both classes together:
     <span class="pill role-staff">STAFF</span>
*/
.role-superadmin { background: var(--purple-light); color: var(--purple); }
.role-admin      { background: var(--blue-light); color: var(--navy); }
.role-staff      { background: var(--green-light); color: var(--green); }
.role-club       { background: var(--amber-light); color: var(--amber); }
.role-pending    { background: var(--off-white); color: var(--text-muted); border: 1px solid var(--border); }

/* WIDGET: Toolbar ─────────────────────────────────────────────────────────
   Horizontal strip above content. Left side: filters/search. Right side: actions.
   Structure:
     <div class="toolbar">
       <div class="toolbar__left">
         <input class="toolbar__search" type="text" placeholder="Search…">
         <select class="toolbar__filter">…</select>
       </div>
       <div class="toolbar__right">
         <button class="btn btn--primary btn--sm">+ Add</button>
       </div>
     </div>
*/
.toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 20px;
  flex-wrap: wrap;
}
.toolbar__left {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 1;
  flex-wrap: wrap;
  min-width: 0;
}
.toolbar__right {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}
.toolbar__search {
  flex: 1;
  min-width: 200px;
  max-width: 320px;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--white);
  font-family: var(--font);
  font-size: var(--text-sm);
  font-variation-settings: 'wght' 400;
  color: var(--text);
  outline: none;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.toolbar__search:focus {
  border-color: var(--primary);
  box-shadow: var(--focus-ring);
}
.toolbar__search::placeholder {
  color: var(--text-muted);
  font-variation-settings: 'wght' 400;
  opacity: 1;
}
.toolbar__filter {
  font-family: var(--font);
  font-size: var(--text-sm);
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--white);
  color: var(--text);
  cursor: pointer;
  outline: none;
  transition: border-color 0.15s;
}
.toolbar__filter:focus { border-color: var(--primary); }
@media (max-width: 600px) {
  .toolbar { flex-direction: column; align-items: stretch; }
  .toolbar__right { justify-content: flex-end; }
  .toolbar__search { max-width: 100%; }
}

/* WIDGET: Formatting toolbar (rich-text editor controls) ───────────────────
   Distinct from .toolbar (which is a filter/search/action strip above
   content). .fmt-toolbar is the row of formatting buttons that lives
   above a contenteditable area: bold/italic/underline, lists,
   undo/redo, clear formatting, plus a style/heading select. Promoted
   from graphics/article-composer in v2.19 — any tool with longform
   user input (tasks descriptions, meeting-notes, claudio prompts) can
   reuse this verbatim.
   Structure:
     <div class="fmt-toolbar">
       <button class="fmt-icon" data-cmd="bold">…</button>
       <button class="fmt-icon" data-cmd="italic">…</button>
       <span class="sep"></span>
       <select id="styleSelect">…</select>
       <span class="sep"></span>
       <button class="danger">Clear formatting</button>
     </div>
*/
.fmt-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 0 14px;
  align-items: center;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px;
}
.fmt-toolbar button,
.fmt-toolbar select {
  padding: 8px 14px;
  border: 1px solid var(--border);
  background: var(--white);
  border-radius: var(--radius);
  cursor: pointer;
  font-family: var(--font);
  font-size: var(--text-sm);
  font-weight: 900;
  font-variation-settings: 'wght' 900;
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
  color: var(--text);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  transition: background var(--transition-fast) ease,
              border-color var(--transition-fast) ease,
              color var(--transition-fast) ease;
  line-height: 1;
}
.fmt-toolbar button:hover,
.fmt-toolbar select:hover {
  background: var(--off-white);
  border-color: var(--navy-300);
  color: var(--navy);
}
.fmt-toolbar button:active,
.fmt-toolbar button.is-active {
  background: var(--navy);
  color: var(--white);
  border-color: var(--navy);
}
.fmt-toolbar select {
  padding: 7px 8px;
  font-weight: 700;
  font-variation-settings: 'wght' 700;
}
.fmt-toolbar .sep {
  width: 1px;
  height: 22px;
  background: var(--border);
  margin: 0 4px;
}
.fmt-toolbar .fmt-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
}
.fmt-toolbar .fmt-icon svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}
.fmt-toolbar .danger {
  color: var(--red);
  border-color: var(--border);
}
.fmt-toolbar .danger:hover {
  background: var(--red-light);
  border-color: var(--red);
  color: var(--red-deep);
}
/* Compact variant — inline card contexts (per-article editors etc.) where
   the full-size bar is too heavy */
.fmt-toolbar--compact {
  padding: 6px;
  gap: 6px;
  margin: 0 0 8px;
}
.fmt-toolbar--compact button {
  padding: 5px 10px;
}
/* The editable area under the bar — paired with NL.richText(mount, opts)
   in nl-utils.js v1.24+ (bold/italic/bullets/link, forced plain-text
   paste, NL.sanitiseHtml whitelist on every change). */
.fmt-edit {
  min-height: 110px;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px 12px;
  font-family: var(--font);
  font-size: var(--text-sm);
  line-height: 1.55;
  color: var(--text);
}
.fmt-edit:focus {
  outline: 2px solid var(--navy-300);
  outline-offset: -1px;
}
.fmt-edit:empty::before {
  content: attr(data-placeholder);
  color: var(--text-muted);
}
.fmt-edit p { margin: 0 0 0.6em; }
.fmt-edit p:last-child { margin-bottom: 0; }
.fmt-edit ul { margin: 0 0 0.6em; padding-left: 1.3em; }
.fmt-edit a { color: var(--blue); }
/* The body-level font-variation-settings:'wght' 400 inherits in and PINS
   the variable font's weight — <b>'s font-weight alone is silently
   defeated. Explicit variation settings make bold/italic actually show. */
.fmt-edit b, .fmt-edit strong { font-weight: 700; font-variation-settings: 'wght' 700; }
.fmt-edit i, .fmt-edit em { font-style: italic; }

/* WIDGET: Page header ──────────────────────────────────────────────────────
   Title + optional subtitle at top of a tool page, above the main content.
   Distinct from .section-head which is a section divider within a page.
   Structure:
     <div class="page-header">
       <div class="page-header__titles">
         <h1 class="page-header__title">Judgements & Decisions</h1>
         <p class="page-header__sub">Season 2025/26 disciplinary records</p>
       </div>
       <div class="page-header__actions">
         <button class="btn btn--primary">+ Add record</button>
       </div>
     </div>
*/
.page-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 28px;
  flex-wrap: wrap;
}
.page-header__titles { flex: 1; min-width: 0; }
.page-header__title {
  font-size: clamp(22px, 2vw, 30px);
  font-weight: 900;
  font-variation-settings: 'wght' 900;
  color: var(--navy);
  line-height: 1.1;
  margin-bottom: 4px;
}
.page-header__sub {
  font-size: var(--text-sm);
  color: var(--text-muted);
  line-height: 1.4;
}
.page-header__actions {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-shrink: 0;
  padding-top: 4px;
}
@media (max-width: 600px) {
  .page-header { flex-direction: column; }
  .page-header__actions { width: 100%; }
  .page-header__actions .btn { flex: 1; justify-content: center; }
}

/* WIDGET: Form panel ───────────────────────────────────────────────────────
   White card wrapping a form section. Typically inside a two-column layout
   or as a standalone panel on a narrower page.
   Structure:
     <div class="form-panel">
       <div class="form-panel__head">Add new record</div>
       <div class="form-panel__body">
         <div class="form-grid">…</div>
       </div>
       <div class="form-panel__foot">
         <button class="btn btn--primary">Save</button>
       </div>
     </div>
*/
.form-panel {
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;
}
.form-panel__head {
  padding: 16px 20px;
  font-size: 11px;
  font-weight: 900;
  font-variation-settings: 'wght' 900;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--white);
  background: var(--navy);
}
.form-panel__body {
  padding: 20px;
}
.form-panel__foot {
  padding: 14px 20px;
  border-top: 1px solid var(--border);
  background: var(--off-white);
  display: flex;
  gap: 8px;
  justify-content: flex-end;
}

/* WIDGET: Club picker ──────────────────────────────────────────────────────
   Typeahead input with crest preview and club dropdown. Used wherever a user
   needs to select a club from the full NL clubs list.
   Requires clubs-meta.json (loaded in JS) and crest images.
   Structure:
     <div class="club-picker">
       <div class="club-picker__wrap">
         <img class="club-picker__crest" src="…" alt="">
         <input class="club-picker__input" type="text" placeholder="Search club…">
       </div>
       <div class="club-picker__dropdown">
         <div class="club-picker__option">
           <img src="…" alt="">
           <span class="club-picker__option-name">Aldershot Town</span>
           <span class="club-picker__option-div">PREMIER</span>
         </div>
         <div class="club-picker__freetext">Enter manually</div>
       </div>
     </div>
   See Vacancies or Judgements for full JS implementation.
*/
.club-picker { position: relative; }
.club-picker__wrap {
  display: flex;
  align-items: center;
  gap: 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 7px 12px;
  background: var(--white);
  transition: border-color 0.15s;
}
.club-picker__wrap:focus-within {
  border-color: var(--primary);
  box-shadow: var(--focus-ring);
}
.club-picker__crest { width: 28px; height: 28px; object-fit: contain; flex-shrink: 0; }
.club-picker__input {
  flex: 1;
  border: none !important;
  padding: 0 !important;
  font-size: var(--text-sm);
  outline: none;
  background: transparent;
  font-family: var(--font);
  font-variation-settings: 'wght' 400;
}
.club-picker__dropdown {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 50;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  max-height: 220px;
  overflow-y: auto;
  display: none;
  margin-top: 2px;
}
.club-picker__dropdown.open { display: block; }
.club-picker__option {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  cursor: pointer;
  font-size: var(--text-sm);
  border-bottom: 1px solid var(--border);
}
.club-picker__option:last-child { border-bottom: none; }
.club-picker__option:hover { background: var(--off-white); }
.club-picker__option img { width: 24px; height: 24px; object-fit: contain; }
.club-picker__option-name { flex: 1; font-weight: 600; font-variation-settings: 'wght' 600; }
.club-picker__option-div { font-size: var(--text-xs); color: var(--text-muted); text-transform: uppercase; }
.club-picker__freetext {
  padding: 9px 12px;
  font-size: var(--text-xs);
  color: var(--text-muted);
  font-style: italic;
  cursor: pointer;
  border-top: 1px solid var(--border);
  background: var(--off-white);
}
.club-picker__freetext:hover { background: color-mix(in srgb, var(--off-white) 70%, var(--border)); }

/* "Use as entered" option — modifier on .club-picker__option for callers
   that surface freetext-commit as a styled row INSIDE the dropdown rather
   than as the simpler standalone .club-picker__freetext footer above.
   Visually distinct (dashed top border, off-white fill, italic name + red
   tag) so users know they're stepping outside the curated NL club list.
   Used by attendance/index.html for non-NL FA Cup / FA Trophy opponents. */
.club-picker__option--freetext {
  border-top: 2px dashed var(--border);
  background: var(--off-white);
  font-style: italic;
  color: var(--text-muted);
}
.club-picker__option--freetext:hover { background: var(--off-white); }
.club-picker__option--freetext .club-picker__option-name {
  color: var(--text);
  font-style: normal;
}
.club-picker__option--freetext .club-picker__option-div {
  color: var(--primary);
  font-style: italic;
}

/* MODIFIER: .club-picker--select — click-to-toggle variant ─────────────────
   Same shell + dropdown styling as .club-picker, but the typeable input is
   replaced by a <button> trigger that shows the current selection (or a
   placeholder when nothing is picked). For callers where typing makes no
   sense and the right UX is "scroll through all options".

   Markup:
     <div class="club-picker club-picker--select">
       <button class="club-picker__wrap" type="button">
         <img class="club-picker__crest" src="…" alt="">
         <span class="club-picker__value">Aldershot Town</span>
         <svg class="club-picker__chevron" viewBox="0 0 12 12">
           <path d="M2 4l4 4 4-4" stroke="currentColor" fill="none"
                 stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
         </svg>
       </button>
       <div class="club-picker__dropdown">…</div>
     </div>

   Use .club-picker__value--placeholder on the value span when nothing is
   selected (mutes the colour). Toggle .open on the dropdown to show it,
   exactly like the typeable variant. */
.club-picker--select .club-picker__wrap {
  cursor: pointer;
  width: 100%;
  font-family: var(--font);
  font-size: var(--text-sm);
  color: var(--text);
  text-align: left;
}
.club-picker--select .club-picker__wrap:focus-visible {
  outline: none;
  border-color: var(--primary);
  box-shadow: var(--focus-ring);
}
.club-picker__value {
  flex: 1;
  font-variation-settings: 'wght' 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.club-picker__value--placeholder { color: var(--text-muted); font-variation-settings: 'wght' 400; }
.club-picker__chevron {
  width: 12px; height: 12px;
  flex-shrink: 0;
  color: var(--text-muted);
  transition: transform 0.15s;
}
.club-picker--select.is-open .club-picker__chevron { transform: rotate(180deg); }

/* Keyboard-navigation highlight (arrow keys) — kept distinct from :hover so
   mouse and keyboard don't fight over the highlighted row. Used by
   NL.clubPicker's arrow-key / type-ahead navigation. */
.club-picker__option--active { background: var(--off-white); }

/* Placeholder contrast — solid --text-muted (5.5:1). Was a local
   color-mix(--text-muted 50% white) (~2:1, fails AA) in per-tool copies;
   promoted to canon so every caller of NL.clubPicker inherits the fix. */
.club-picker__input::placeholder { color: var(--text-muted); }

/* Optional clear button (NL.clubPicker clearable:true) — promoted from the
   travel-planner local pattern. Pair with .has-crest on the picker root. */
.club-picker__clear {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--text-muted);
  font-size: 18px;
  line-height: 1;
  padding: 0 2px;
  flex-shrink: 0;
  font-family: var(--font);
}
.club-picker__clear:hover { color: var(--text); }
.club-picker__clear:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: var(--radius-sm); }

/* WIDGET: Icon system ──────────────────────────────────────────────────────
   SVG sprite sheet at /assets/icons/sprites.svg

   Usage:
     <svg class="icon icon--md">
       <use href="/assets/icons/sprites.svg#icon-add"></use>
     </svg>

   Available icons (24):
   add, close, back, forward, up, down, download, upload, tick,
   refresh, settings, edit, search, eye, filter, calendar, user,
   warning, info, link, star, star-filled, send, delete

   Sizes: .icon--sm (16px)  .icon--md (20px)  .icon--lg (24px)
   Inside .btn the icon is forced to 16px (14px in .btn--sm) regardless of
   modifier — see the `.btn .icon` rule below.
   Colour: inherits currentColor from parent — set color on the svg or parent element

   CONVENTION:
   - Navigation icons: BEFORE the text  (<svg>back</svg> Back)
   - Completion icons: AFTER the text   (Submit <svg>send</svg>)
   - No icon on neutral actions (Save, Cancel)
*/

/* Icon helper classes — for SVG sprite icons
   Usage: <svg class="icon icon--md"><use href="/assets/icons/sprites.svg#icon-add"></use></svg>
   Colour inherits from parent via currentColor.
   Sprite sheet: /assets/icons/sprites.svg
*/
.icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.icon--sm { width: 16px; height: 16px; }
.icon--md { width: 20px; height: 20px; }  /* default for most button/inline use */
.icon--lg { width: 24px; height: 24px; }

/* Icon inside a button — consistent alignment */
.btn .icon { width: 16px; height: 16px; }
.btn--sm .icon { width: 14px; height: 14px; }

/* =========================================================================
   DOCUMENT PRESENTATION — .nl-doc / .nl-cover / .nl-crumb  (v2.25)
   Legal/governing document rendering, promoted from the Handbook editor and
   its public reader (the second consumer). One presentation, every context:
   editor read mode, draft preview, published edition, embeds.
   - The clause number lives in a GUTTER, never in the text.
   - Editing chrome (.nl-doc.is-editing …), formatting toolbars and table
     row/col controls are tool-local — this block is the reading surface.
   ========================================================================= */

.nl-doc { max-width: 820px; margin: 0 auto; padding: 30px 28px 100px; color: var(--text); font-size: 15px; line-height: 1.62; }
@media (max-width: 860px) { .nl-doc { padding: 22px 16px 70px; } }
.nl-doc__head { margin-bottom: 26px; padding-bottom: 18px; border-bottom: 2px solid var(--navy); }
.nl-doc__title { font-size: 27px; font-variation-settings: 'wght' 900; color: var(--navy); line-height: 1.15; }
.nl-doc__sub { font-size: 14px; color: var(--text-muted); margin-top: 4px; }
.nl-doc__season { display: inline-block; margin-top: 10px; font-size: 12px; padding: 3px 10px; border-radius: 999px; background: var(--navy-50); color: var(--navy); font-variation-settings: 'wght' 700; }

/* Article (top-level node) */
.nl-art { margin: 30px 0 6px; scroll-margin-top: 14px; }
.nl-art__head { display: flex; gap: 12px; align-items: baseline; }
.nl-art__num { font-size: 18px; font-variation-settings: 'wght' 900; color: var(--primary); flex-shrink: 0; min-width: 30px; }
.nl-art__title { font-size: 18px; font-variation-settings: 'wght' 800; color: var(--navy); letter-spacing: 0.01em; }

/* Clause row: number gutter + body; children nest inside body → auto-indent */
.nl-clause { display: flex; gap: 12px; margin: 9px 0; scroll-margin-top: 14px; }
.nl-clause__num { flex-shrink: 0; min-width: 46px; text-align: left; color: var(--primary); font-variation-settings: 'wght' 800; font-size: 13px; padding-top: 1px; font-variant-numeric: tabular-nums; }
.nl-clause__body { flex: 1; min-width: 0; }
.nl-clause__title { font-variation-settings: 'wght' 800; color: var(--navy); margin-bottom: 2px; }
.nl-clause__text > p { margin: 0 0 8px; }
.nl-clause__text > p:last-child { margin-bottom: 0; }
/* Lists inside a clause body (imported, or made with a formatting toolbar) */
.nl-clause__text ul, .nl-clause__text ol { margin: 6px 0 8px; padding-left: 26px; }
.nl-clause__text ul { list-style: disc; }
.nl-clause__text ol { list-style: decimal; }
.nl-clause__text ol ol { list-style: lower-alpha; }
.nl-clause__text ol ol ol { list-style: lower-roman; }
.nl-clause__text li { margin: 2px 0; }
.nl-clause--bullet .nl-clause__num { color: var(--text-muted); min-width: 20px; }
/* Unnumbered nodes: collapse the empty gutter so content sits flush. */
.nl-clause--nonum > .nl-clause__num { display: none; }
.nl-art--nonum .nl-art__num { display: none; }
.nl-clause__text a { color: var(--navy); }

/* Document tables */
.nl-tbl-wrap { overflow-x: auto; margin: 6px 0 10px; }
.nl-tbl { border-collapse: collapse; width: 100%; font-size: 14px; }
.nl-tbl th, .nl-tbl td { border: 1px solid var(--border); padding: 7px 10px; text-align: left; vertical-align: top; }
.nl-tbl th { background: var(--navy-50); font-variation-settings: 'wght' 800; color: var(--navy); }

/* Depth tints for the gutter number (subtle legal hierarchy cue) */
.nl-clause[data-depth="2"] .nl-clause__num { color: var(--navy); }
.nl-clause[data-depth="3"] .nl-clause__num,
.nl-clause[data-depth="4"] .nl-clause__num { color: var(--navy-600); font-variation-settings: 'wght' 700; }

/* Read mode: numbers are click-to-copy deep links (editors add .is-editing) */
.nl-doc:not(.is-editing) .nl-clause__num,
.nl-doc:not(.is-editing) .nl-art__num { cursor: pointer; }
.nl-doc:not(.is-editing) .nl-clause__num:hover,
.nl-doc:not(.is-editing) .nl-art__num:hover { text-decoration: underline; text-underline-offset: 3px; }

/* ---- .nl-cover — document title page ---- */
.nl-cover { max-width: 760px; margin: 0 auto; padding: 44px 24px 90px; text-align: center; }
.nl-cover__lockup { display: block; width: min(430px, 82%); height: auto; margin: 18px auto 34px; }
.nl-cover__title { margin: 0; font-size: clamp(46px, 9vw, 74px); letter-spacing: .05em; color: var(--navy); font-variation-settings: 'wght' 900; line-height: 1.02; text-transform: uppercase; }
.nl-cover__season { font-size: clamp(24px, 5vw, 36px); color: var(--primary); font-variation-settings: 'wght' 800; margin-top: 8px; }
/* Bottom imprint — the document's single, quiet edition statement. Place last in the cover. */
.nl-cover__meta { margin-top: 40px; color: var(--text-muted); font-size: 12.5px; font-style: italic; }
.nl-cover__rule { width: 76px; height: 3px; background: var(--navy); margin: 44px auto 30px; border-radius: 2px; }
.nl-cover__divs { display: flex; justify-content: center; gap: 16px; flex-wrap: wrap; }
.nl-cover__divs img { width: 150px; max-width: 28%; height: auto; }

/* ---- .nl-crumb — "you are here" breadcrumb strip (pairs with a scroll-spy) ---- */
.nl-crumb {
  flex: 0 0 auto; display: flex; align-items: center; gap: 8px;
  padding: 8px 28px; border-bottom: 1px solid var(--border); background: var(--off-white);
  font-size: 13px; color: var(--text-muted); min-height: 18px;
}
.nl-crumb:empty { display: none; }
.nl-crumb__area { font-variation-settings: 'wght' 700; color: var(--navy); flex: 0 0 auto; }
.nl-crumb__sep { color: var(--text-muted); flex: 0 0 auto; }
.nl-crumb__sec { font-variation-settings: 'wght' 700; color: var(--primary); flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@media (max-width: 860px) { .nl-crumb { padding: 8px 14px; cursor: pointer; } }
