/* ─────────────────────────────────────────────────────────────
   LAYER 2 — SEMANTIC TOKENS
   Roles and intent. The only layer components may reference.

   Two layers, not three: a component layer would be pure indirection
   until a real divergence appears (Review-Questions Q3).
   Names describe role, never appearance (§2 T4).

   Source of truth: DESIGN.md. Where a role name here differs from the
   spelling in DESIGN.md §2, the mapping is stated inline. The pack's
   --color-<group>-<role> convention is kept because base.css,
   ledger.css and tools/lint-tokens.php already speak it; renaming
   eleven files to match a spelling buys nothing.

   THEMING. Light is the default. Dark is opt-in via
   :root[data-theme="dark"] and overrides THIS layer only — layer 1
   never changes. prefers-color-scheme is deliberately NOT wired up
   yet: only [data-rl] subtrees are restyled today, so a system-dark
   user would get a dark ledger inside a white Bootstrap page. The
   media query lands with the shell.
   ───────────────────────────────────────────────────────────── */

:root {
  /* ── Colour: background ──
        page = DESIGN.md --background · surface/raised = --card
        sunken = --muted (row stripe, wells, disabled fill) ── */
  --color-bg-page:    var(--stone-25);
  --color-bg-surface: var(--stone-0);
  --color-bg-raised:  var(--stone-0);
  --color-bg-sunken:  var(--stone-50);
  /* color-mix() needs Chrome 111+ / Safari 16.2+. The first declaration is
     the fallback; browsers that understand the second take it, the rest keep
     an opaque backdrop — uglier, but it still hides what it must. */
  --color-bg-overlay: rgba(23, 26, 24, 0.55);
  --color-bg-overlay: color-mix(in srgb, var(--stone-950) 55%, transparent);

  /* ── Colour: foreground ── */
  --color-fg-default:   var(--stone-950);
  --color-fg-muted:     var(--stone-600);
  --color-fg-inverse:   var(--stone-0);
  --color-fg-on-action: var(--stone-0);

  /* ── Colour: action — the accent, and NOTHING else (DESIGN.md §7).
        Not status, not emphasis, not decoration. ── */
  --color-action-default:  var(--azure-600);
  --color-action-hover:    rgb(29, 76, 169);
  --color-action-hover:    color-mix(in srgb, var(--azure-600) 92%, black);
  --color-action-subtle:   color-mix(in srgb, var(--azure-600) 12%, transparent);
  --color-action-disabled: var(--stone-50);

  /* ── Colour: border — two tokens, on purpose (DESIGN.md §2).
        -subtle is decorative and may be faint.
        -default is a MEANINGFUL boundary and clears 3:1 against page,
        surface and stripe alike. Never put -subtle on an input,
        checkbox, radio or segmented control.
        (-default is DESIGN.md's --input; -subtle is its --border.) ── */
  --color-border-subtle:  var(--stone-150);
  --color-border-default: var(--stone-500);
  --color-border-focus:   var(--azure-600);

  /* ── Colour: status — the memorable element (DESIGN.md §1).
        Five states, no sixth. Colour never travels alone: every chip
        carries text, and most carry an icon (§2). ── */
  --color-status-paid-fg:    var(--moss-700);
  --color-status-paid-bg:    var(--moss-50);
  --color-status-due-fg:     var(--amber-800);
  --color-status-due-bg:     var(--amber-50);
  --color-status-overdue-fg: var(--clay-700);
  --color-status-overdue-bg: var(--clay-50);
  /* Ended / vacant and in-progress / notice-given are OUTLINED chips:
     no tint, so they take a foreground and the subtle border. */
  --color-status-ended-fg:    var(--color-fg-muted);
  --color-status-progress-fg: var(--color-fg-default);

  /* Money reads through the status system rather than owning colours of
     its own — arrears are tiered by age (§7), not painted red wholesale. */
  --color-money-owed:    var(--color-status-overdue-fg);
  --color-money-cleared: var(--color-status-paid-fg);
  --color-feedback-danger-fg:  var(--color-status-overdue-fg);
  --color-feedback-success-fg: var(--color-status-paid-fg);
  --color-feedback-warning-fg: var(--color-status-due-fg);


  /* ── Role triplets, for Bootstrap's !important colour utilities only.
        Same roles as above, expressed as R, G, B because that is the only
        shape .text-* / .bg-* can consume. Nothing else should use these:
        if you are writing a rule yourself, use the colour token. ── */
  --color-action-default-rgb:    var(--azure-600-rgb);
  --color-fg-default-rgb:        var(--stone-950-rgb);
  --color-fg-muted-rgb:          var(--stone-600-rgb);
  --color-fg-on-action-rgb:      var(--stone-0-rgb);
  --color-bg-sunken-rgb:         var(--stone-50-rgb);
  --color-status-paid-fg-rgb:    var(--moss-700-rgb);
  --color-status-due-fg-rgb:     var(--amber-800-rgb);
  --color-status-overdue-fg-rgb: var(--clay-700-rgb);


  /* ── Colour: domain — WHERE you are, never WHAT STATE something is in.
        Four areas of the product, each with one colour that follows it
        everywhere: sidebar glyph, section heading, stat tile, page header.
        Used as a tinted well plus its own foreground, NEVER as a chip —
        a chip always means state (DESIGN.md §2), and keeping the two in
        different shapes is what stops them competing.
        Recorded as an override of §7 in the reconciliation doc §8. ── */
  --color-domain-estate-fg: var(--estate-600);
  --color-domain-estate-bg: var(--estate-50);
  --color-domain-people-fg: var(--people-600);
  --color-domain-people-bg: var(--people-50);
  --color-domain-ledger-fg: var(--ledger-600);
  --color-domain-ledger-bg: var(--ledger-50);
  --color-domain-upkeep-fg: var(--upkeep-600);
  --color-domain-upkeep-bg: var(--upkeep-50);


  /* ── Chart series. Three jobs, three rules (dataviz skill):
        CATEGORICAL identity  -> a fixed order, never cycled
        STATUS                -> the five states, re-stepped for fills
        SINGLE SERIES         -> one hue, no legend needed
        Every value here was passed through the palette validator for
        colourblind separation and surface contrast, in both themes. ── */
  --chart-1: var(--estate-600);   /* fixed order: never reassigned by rank */
  --chart-2: var(--upkeep-600);
  --chart-3: var(--ledger-600);
  --chart-other: var(--color-fg-muted);   /* the catch-all, deliberately grey */

  /* Status fills. NOT the chip colours — see tokens.primitive.css. */
  --chart-status-paid:     var(--moss-400);
  --chart-status-due:      var(--gold-600);
  --chart-status-overdue:  var(--clay-700);
  --chart-status-ended:    var(--color-fg-muted);
  --chart-status-progress: var(--estate-600);

  /* One series needs no palette; the title names it. */
  --chart-series: var(--ledger-600);

  /* Chrome stays recessive so the data is the loudest thing. */
  --chart-grid:  var(--color-border-subtle);
  --chart-axis:  var(--color-fg-muted);
  --chart-label: var(--color-fg-default);

  /* ── Space — base 4 (DESIGN.md §5) ── */
  --space-2: 0.125rem;  --space-4: 0.25rem;  --space-8: 0.5rem;
  --space-12: 0.75rem;  --space-16: 1rem;    --space-24: 1.5rem;
  --space-32: 2rem;     --space-48: 3rem;    --space-64: 4rem;
  --space-96: 6rem;

  --space-section:       var(--space-48);
  --space-section-tight: var(--space-24);

  /* ── Type — one family (DESIGN.md §3). A second would have to earn
        its place, and in a table-led product it does not.

        Shipped state: the native system stack. Inter / Public Sans is
        not self-hosted yet, a font CDN contradicts the performance
        budget, and there is no build step here. Swapping is a one-line
        change once public/fonts/*.woff2 exist. Every member of the
        stack below has genuine tabular figures. ── */
  --font-body: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
               "Helvetica Neue", Arial, sans-serif;
  /* Reference codes, IDs and ledger lines only — never prose. */
  --font-ledger: ui-monospace, "Cascadia Mono", "Segoe UI Mono", "Roboto Mono",
                 Menlo, Consolas, monospace;

  /* No display size. This product has no hero (DESIGN.md §3). */
  --text-h1:    1.75rem;   /* 28 */
  --text-h2:    1.25rem;   /* 20 */
  --text-h3:    1rem;      /* 16 */
  --text-body:  1rem;      /* 16 — both densities, never smaller */
  --text-table: 0.875rem;  /* 14 — table cells, compact only. The floor. */
  --text-small: 0.8125rem; /* 13 — captions, metadata, timestamps */
  --text-mono:  0.875rem;  /* 14 */

  --weight-regular: 400;
  --weight-medium:  500;   /* the only two weights loaded */

  --leading-heading: 1.25;
  --leading-h2:      1.3;
  --leading-h3:      1.35;
  --leading-body:    1.55;
  --leading-table:   1.45;
  --tracking-h1:     -0.01em;
  --measure:         65ch;  /* prose only; not applicable to tables */

  /* ── Radius ladder (DESIGN.md §6) ── */
  --radius-none: 0;         /* tables, full-bleed */
  --radius-sm:   0.25rem;   /* inputs, small controls */
  --radius-md:   0.5rem;    /* cards, menus, dialogs */
  --radius-full: 9999px;    /* chips, avatars */

  /* ── Elevation — almost flat. Separation comes from spacing and
        alignment first, background shift second, border third, shadow
        last. Never a border and a shadow on the same edge. ── */
  --shadow-raised:   0 1px 2px rgba(0, 0, 0, 0.06);
  --shadow-floating: 0 4px 12px rgba(0, 0, 0, 0.10);
  --shadow-overlay:  0 16px 40px rgba(0, 0, 0, 0.18);

  /* ── Motion — functional only (DESIGN.md §9) ── */
  --duration-press: 140ms;
  --duration-fast:  160ms;  /* tooltip */
  --duration-base:  200ms;  /* dropdown, date picker, toast */
  --duration-slow:  260ms;  /* dialog, drawer — in */
  --duration-exit:  180ms;  /* dialog, drawer — out */
  --ease-out:    cubic-bezier(0.23, 1, 0.32, 1);
  --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);

  /* ── Z-index — named scale. A raw value anywhere is a defect ── */
  --z-base: 0;      --z-sticky: 100;  --z-dropdown: 200;
  --z-overlay: 300; --z-modal: 400;   --z-toast: 500;

  /* ── Breakpoints (reference only; queries live with components) ── */
  --bp-sm: 480px; --bp-md: 768px; --bp-lg: 1024px; --bp-xl: 1280px;

  /* ── Density (DESIGN.md §1). Compact tightens spacing and control
        height, NEVER type. Comfortable is the default so the tenant
        portal and any un-migrated surface get the roomier value. ── */
  --control-height: 2.75rem;  /* 44 — thumb-reachable */
  --row-padding-y:  var(--space-12);
  --cell-padding-x: var(--space-16);
  --field-gap:      var(--space-16);
  --text-cell:      var(--text-body);
  --tap-target:     2.75rem;
}

/* Manager console. Set data-density="compact" on the root of that surface. */
[data-density="compact"] {
  --control-height: 2rem;      /* 32 */
  --row-padding-y:  var(--space-8);
  --cell-padding-x: var(--space-12);
  --field-gap:      var(--space-12);
  --text-cell:      var(--text-table);
  --tap-target:     1.5rem;    /* 24 — the floor on a pointer surface */
}

/* ─────────────────────────────────────────────────────────────
   DARK THEME — overrides layer 2 only.
   Derived independently from light, not inverted: #1F53B8 fails on a
   dark surface, so the accent is a different value rather than the
   same one flipped. Each theme is checked independently by
   tools/check-contrast.php; a palette that passes light and fails
   dark is one theme.
   ───────────────────────────────────────────────────────────── */
:root[data-theme="dark"] {
  --color-bg-page:    var(--stone-940);
  --color-bg-surface: var(--stone-880);
  --color-bg-raised:  var(--stone-880);
  --color-bg-sunken:  var(--stone-920);
  --color-bg-overlay: rgba(0, 0, 0, 0.62);

  --color-fg-default:   var(--stone-75);
  --color-fg-muted:     var(--stone-400);
  --color-fg-inverse:   var(--stone-950);
  --color-fg-on-action: var(--azure-980);

  --color-action-default:  var(--azure-300);
  --color-action-hover:    rgb(167, 194, 247);
  --color-action-hover:    color-mix(in srgb, var(--azure-300) 88%, white);
  --color-action-subtle:   color-mix(in srgb, var(--azure-300) 16%, transparent);
  --color-action-disabled: var(--stone-800);

  --color-border-subtle:  var(--stone-800);
  --color-border-default: var(--stone-550);
  --color-border-focus:   var(--azure-300);

  /* Status text is lifted, not reused. The light text values sit at
     ~2.4:1 on the dark tints — unreadable. These keep the hue and clear
     4.5:1 on both the tint and the surface. DESIGN.md §2 gives the tints
     per theme but only one text value per status; this is that gap
     closed. Recorded in docs/design-plans/00-design-md-reconciliation.md. */
  --color-status-paid-fg:    var(--moss-400);
  --color-status-paid-bg:    var(--moss-960);
  --color-status-due-fg:     var(--amber-500);
  --color-status-due-bg:     var(--amber-960);
  --color-status-overdue-fg: var(--clay-400);
  --color-status-overdue-bg: var(--clay-960);


  --color-action-default-rgb:    var(--azure-300-rgb);
  --color-fg-default-rgb:        var(--stone-75-rgb);
  --color-fg-muted-rgb:          var(--stone-400-rgb);
  --color-bg-sunken-rgb:         var(--stone-950-rgb);
  --color-status-paid-fg-rgb:    var(--moss-400-rgb);
  --color-status-due-fg-rgb:     var(--amber-500-rgb);
  --color-status-overdue-fg-rgb: var(--clay-400-rgb);


  --color-domain-estate-fg: var(--estate-300);
  --color-domain-estate-bg: var(--estate-960);
  --color-domain-people-fg: var(--people-300);
  --color-domain-people-bg: var(--people-960);
  --color-domain-ledger-fg: var(--ledger-300);
  --color-domain-ledger-bg: var(--ledger-960);
  --color-domain-upkeep-fg: var(--upkeep-300);
  --color-domain-upkeep-bg: var(--upkeep-960);


  /* Chart steps for dark are SELECTED, not flipped — each was validated
     against the dark surface on its own. */
  --chart-1: var(--estate-300);
  --chart-2: var(--upkeep-400);
  --chart-3: var(--ledger-300);
  --chart-status-paid:    var(--moss-400);
  --chart-status-due:     var(--gold-400);
  --chart-status-overdue: var(--clay-450);
  --chart-status-progress: var(--estate-300);
  --chart-series: var(--ledger-300);

  /* A lighter surface does most of the work; the shadow is halved (§6). */
  --shadow-raised:   0 1px 2px rgba(0, 0, 0, 0.03);
  --shadow-floating: 0 4px 12px rgba(0, 0, 0, 0.05);
  --shadow-overlay:  0 16px 40px rgba(0, 0, 0, 0.09);
}

/* Reduced motion removes movement but preserves the state change.
   Opacity and colour transitions are kept; nothing is lost (§9). */
@media (prefers-reduced-motion: reduce) {
  :root {
    --duration-press: 1ms;
    --duration-fast:  1ms;
    --duration-base:  1ms;
    --duration-slow:  1ms;
    --duration-exit:  1ms;
  }
}
