/*
 * MM Portal - design tokens.
 *
 * This file contains ONLY :root custom property declarations and generates zero
 * rules, so adding it to a shell cannot change how any page renders. That
 * invariant is deliberate: it is what makes the token rollout safe to land in
 * three shells at once, and auditable afterwards.
 *
 * Loaded FIRST among portal stylesheets by all three shells:
 *   app/Views/layout/header.php      (staff)
 *   app/Views/partner/layout.php     (partner portal)
 *   app/Views/partner/auth/_shell.php
 *
 * app/Views/errors/html/error_400.php and error_404.php are deliberately NOT
 * covered. They link no stylesheet at all because their job is to render when
 * the app is broken, so they stay self contained.
 *
 * Rules for adding to this file:
 *   - Name by ROLE, never by appearance. `--mm-surface`, never `--mm-white`.
 *     A token named for its colour cannot be redefined for dark mode.
 *   - A tint and its ink are INDEPENDENT tokens. Never derive one from the
 *     other. In dark mode a tint is not the light colour at reduced alpha, it
 *     is a different value chosen for contrast against a dark ground.
 *   - One literal maps to exactly one token. A literal mapped to two tokens
 *     looks identical today and splits apart the moment dark mode lands.
 */

:root {

    /* ── Ink ────────────────────────────────────────────────────────── */
    /*
     * Three greys, collapsed UP to the accessible value.
     *
     * --mm-text-muted is #67748e, which measures 4.70:1 on white and passes
     * WCAG AA for small text. It absorbs #8392ab (3.15:1), #7b809a (3.89:1)
     * and #8392a5, the last being a straight typo of #8392ab that had spread
     * to 44 places. Those 226 sites darken slightly and all end up compliant.
     *
     * Collapsing the other way, onto #8392ab, was the first instinct and is
     * wrong: it would drop 62 currently compliant sites to 3.15:1 and take the
     * neutral badge from 4.19:1 to 2.81:1 on 0.65rem uppercase text.
     *
     * --mm-text-faint is decorative only. At 2.07:1 it must never carry
     * information that is not also conveyed some other way.
     */
    --mm-text-primary: #344767;
    --mm-text-muted:   #67748e;
    --mm-text-faint:   #adb5bd;
    --mm-text-inverse: #fff;
    --mm-text-body:    #495057; /* pill and control labels */

    /* ── Layout offsets ─────────────────────────────────────────────── */
    /*
     * Not a colour, so it is declared once here and never redefined per theme.
     * How far below the viewport top a pinned card head sits, clearing the
     * sticky navbar. Read by BOTH .mm-sticky-head in ui.css and the
     * IntersectionObserver rootMargin that decides when it has stuck, so the two
     * cannot drift apart. Change it here, not at either call site.
     */
    --mm-sticky-head-top: 64px;

    /* ── Surfaces ───────────────────────────────────────────────────── */
    --mm-app-bg:         #f0f2f5; /* the page behind the cards     */

    /* ── Solid block ────────────────────────────────────────────────── */
    /*
     * A prominent solid fill: the dark button, a quantity pip, a chart legend
     * swatch. Its own token, NOT --mm-text-primary, even though the two share a
     * value in this theme.
     *
     * They were the same declaration until dark mode landed, and then every one
     * of the 20 call sites turned white: a text token has to INVERT between
     * themes, and a solid block must not. This is the "name by role" rule in the
     * header earning its keep, and the one place the codebase had broken it.
     */
    --mm-solid:       #344767;
    --mm-solid-muted: #67748e;
    --mm-solid-ink:   #fff;
    --mm-surface:        #fff;    /* cards, panels, popovers       */
    --mm-surface-hover:  #f8f9fa; /* row hover                     */
    --mm-surface-sunken: #f0f2f5; /* active row, neutral chip fill */

    /* ── Lines ──────────────────────────────────────────────────────── */
    --mm-border:        #e9ecef; /* default card and table border */
    --mm-border-strong: #d2d6da; /* form controls, search box     */
    --mm-border-subtle: #eef0f3; /* .set-card hairline            */

    /*
     * The boundary of an unchecked control, currently .mm-check.
     *
     * Its own token rather than --mm-border-strong (1.46:1 on white) because on a
     * checkbox the border IS the control: unchecked, it is the only thing drawn, so
     * WCAG 1.4.11 wants 3:1 against the ground and a card border does not get there.
     * An input can borrow a fainter line because its size and its text carry it.
     * Verified at 3.61 / 3.43 / 3.22 against surface, surface-hover and sunken.
     */
    --mm-control-border: #7d879b;
    --mm-rule:          #f2f4f7; /* section head and foot rules   */
    --mm-hairline:      #f6f7f9; /* between list rows             */

    /* ── Portal accent ──────────────────────────────────────────────── */
    /*
     * #5e72e4 is THIS PORTAL'S colour, not the theme's.
     *
     * material-dashboard.css sets --bs-primary: #1670ff and does not contain
     * #5e72e4 anywhere. #5e72e4 is hand written across 44 view files. Do not
     * "correct" it toward the theme primary: that repaints 44 files and breaks
     * the deliberate split documented under --mm-focus-border below.
     */
    --mm-accent:        #5e72e4;
    --mm-accent-strong: #3b4bb8;              /* hover and pressed  */
    --mm-accent-soft:   #a8b4f0;              /* active pill border */
    --mm-accent-tint:   #eef2ff;              /* selected row wash  */
    --mm-accent-ring:   rgba(94, 114, 228, 0.12);

    /* ── Form focus ─────────────────────────────────────────────────── */
    /*
     * The THEME's blue, which is --bs-primary.
     *
     * NO LONGER USED BY THE PORTAL. It was the focus colour on the eight or so
     * views that hand-patched .form-control, kept so a portal input and a theme
     * input on one page agreed. Those views are now .mm-field, which focuses
     * --mm-accent, and that is deliberate: one focus colour across search,
     * fields and buttons (Dom, 2026-09-04).
     *
     * Retained rather than deleted for two reasons: public/ui-preview.html
     * still renders the rejected option beside the chosen one, and the theme
     * itself has not changed, so anything reintroducing a raw .form-control
     * should reach for this rather than inventing a literal.
     */
    --mm-focus-border: #1670ff;
    --mm-focus-ring:   rgba(22, 112, 255, 0.2);

    /* ── Status ─────────────────────────────────────────────────────── */
    /*
     * Each status has a tint (background) and an ink (text on that tint).
     * The pair is independent by design; see the header note.
     *
     * There is deliberately NO --mm-neutral-solid. #8392ab was a text colour
     * in 117 places and a fill in only 4, so it maps to --mm-text-muted
     * everywhere and its handful of border uses are handled as borders.
     * --mm-neutral-ink is an alias rather than a second copy of the same
     * literal, so the two cannot drift apart when dark mode lands.
     */
    --mm-success-tint:  #e8f5e9;
    --mm-success-ink:   #2e7d32;
    --mm-success-solid: #2dce89;

    --mm-info-tint:     #e3f2fd;
    --mm-info-ink:      #1565c0;
    --mm-info-solid:    #1a73e8;

    --mm-warning-tint:  #fff4e5;
    /* Darkened from #e65100, which measured 3.49:1 on --mm-warning-tint and so
       failed AA for the 0.65rem badge label. 5.76:1 now. This also darkens the
       warning notice and the warning button ground, both of which improve. */
    --mm-warning-ink:   #9a4a00;
    --mm-warning-solid: #fb8c00;

    --mm-danger-tint:   #fdecea;
    --mm-danger-ink:    #c62828;
    --mm-danger-solid:  #ea0606;

    --mm-neutral-tint:  var(--mm-surface-sunken);
    /* NOT an alias of --mm-text-muted any more. Muted is tuned for white, where
       it measures 4.70:1; on --mm-neutral-tint it drops to 4.19:1, under AA for
       badge text. This is the tint-and-ink-are-independent rule in the header
       doing its job: the same ink cannot serve both grounds. 5.00:1 here. */
    --mm-neutral-ink:   #5c6880;

    --mm-special-tint:  #f3e5f5;
    --mm-special-ink:   #6a1b9a;

    /* Solid-button FILLS, deliberately separate from the ink tokens.
       A solid .mm-btn was reading --mm-accent / --mm-success-ink / --mm-warning-ink
       as its background. Those are INK tokens: dark mode lightens them so they stay
       legible ON a dark ground, which is the exact opposite of what a fill behind a
       white label needs. The result was a pastel button with white text at 2.0-2.7:1.
       Same one-token-two-roles bug that --mm-solid was introduced for.

       Light values below are byte-identical to what those buttons already showed, so
       light mode does not move. Dark values are chosen against two constraints at
       once: white label >= 4.5:1, and >= 3:1 against the dark ground so the button
       still reads as a control. */
    /* Not #5e72e4. The portal accent is 4.20:1 behind a white label, just under AA, so
       the FILL is nudged to #576ce3 (4.51:1). --mm-accent itself stays #5e72e4 for its 90
       text, link and border uses: this token exists precisely so the button can move
       without touching the portal's identity colour. */
    --mm-fill-accent:        #576ce3;
    --mm-fill-accent-hover:  #3b4bb8;
    --mm-fill-danger:        #ea0606;
    --mm-fill-danger-hover:  #c62828;
    --mm-fill-success:       #2e7d32;
    --mm-fill-success-hover: #1b5e20;
    --mm-fill-warning:       #9a4a00;
    --mm-fill-warning-hover: #7a5f16;

    /* The --dark button. Light mode fills it with --mm-solid and that is correct
       there. Dark mode cannot: --mm-solid darkens to #3a4254, which is 1.64:1
       against the ground, and its hover landed on #1b1f2a - the surface colour
       exactly, 1.00:1, so the button vanished under the cursor. The role inverts
       in dark, so it gets its own token rather than a shared one. */
    --mm-fill-dark:       #344767;
    --mm-fill-dark-hover: #2a3a56;

    /* Sticky navbar. The theme's blurNavbar() adds .blur once you scroll, which is a
       near-white translucent fill plus a white inset ring. Light values here are the
       theme's own, so light mode is unchanged. */
    --mm-navbar-blur-bg:     rgba(255, 255, 255, 0.9);
    --mm-navbar-blur-ring:   rgba(254, 254, 254, 0.82);
    --mm-navbar-blur-shadow: rgba(0, 0, 0, 0.05);

    /* Chart surfaces. --mm-chart-1..5 already carry the validated categorical palette;
       these are the parts of a chart that are NOT a series. They exist because
       analytics.js hardcoded them, which is why the analytics charts did not respond to
       the theme at all: a canvas cannot read a custom property, so the values have to be
       resolved in JS at construction and again on a theme change. */
    --mm-chart-other: #8a8f9e;              /* categories past the 5-slot palette */
    --mm-chart-grid:  rgba(0, 0, 0, 0.05);  /* axis gridlines */
    --mm-chart-ring:  #fff;                 /* the ring drawn around a data point */

    /* Single-series indicator lines on the marketplace dashboards. Named in the chart
       family because that is what they are; they are deliberately NOT folded into
       --mm-chart-1..5, which is the validated categorical palette and would move these
       charts in light mode. */
    --mm-chart-cyan:   #17c1e8;
    --mm-chart-yellow: #fbcf33;
    --mm-chart-teal:   #42d29d;

    /* Scrollbars. Only used under the dark scope: light keeps the native scrollbar it
       has always had, and nobody asked for that to change. */
    --mm-scroll-thumb:       #c7ccd6;
    --mm-scroll-thumb-hover: #aeb5c2;
    --mm-scroll-track:       transparent;

    /* Toast. The shadow is what lifts it off the page; on a dark ground it has to be
       deeper, because a soft black shadow over a dark surface reads as nothing. */
    --mm-toast-shadow: 0 8px 24px -6px rgba(20, 20, 20, 0.22), 0 2px 8px -2px rgba(20, 20, 20, 0.12);

    /* Pinned card head, once it is actually stuck. Same reasoning as the toast
       shadow above, and shallower on purpose: this one marks an edge that content
       slides under, not a panel floating over the page. Offset down with a matching
       negative spread so it falls below the head and does not halo up into the band
       painted above it. */
    --mm-sticky-head-shadow: 0 6px 12px -6px rgba(20, 20, 20, 0.24), 0 2px 4px -2px rgba(20, 20, 20, 0.12);

    /* The same lift expressed as a gradient's top colour, for where a box-shadow
       cannot be used: under a pinned table header row, whose cells are inside a
       `border-collapse: collapse` table. Fades to transparent downward. */
    --mm-sticky-head-veil: rgba(20, 20, 20, 0.15);

    /* ---- Status vocabulary -------------------------------------------------
       The canonical colours for "what state is this in". Several already existed
       under component names that lied about them (#42d29d was only reachable as
       --mm-toggle-on), so those are now ALIASES below: one value, one definition
       point, an honest name to reach it by. */

    --mm-status-live:            #42d29d;
    --mm-status-success:         #28a745;
    --mm-status-danger:          #dc3545;
    --mm-status-idle:            #c5c9d6;
    --mm-status-success-tint:    #f0fdf4;
    --mm-status-breached:        #9b1c1c;
    --mm-status-cancelled:       #f5365c;
    --mm-release-partial:        #e65100;
    --mm-delivery-pickup:        #7b5ea7;
    --mm-timeline-lilac:         #b39ddb;

    /* ---- Ordered families --------------------------------------------------
       Each of these is a SCALE, not a set of unrelated colours, so its members
       have to move together. Collapsing one member onto a nearby status token
       (which is what a pure nearest-colour match wanted to do) would have broken
       the ordering the scale exists to communicate. */
    /* Consignment lifecycle, consignments/all.php */
    --mm-stage-prep:             #a0aebb;
    --mm-stage-live:             #4fa8d5;
    --mm-stage-ended:            #f0a44e;
    --mm-stage-done:             #52c48a;

    /* Pick-time budget, monotone severity, picking/manager.php */
    --mm-gauge-ok:               #4caf50;
    --mm-gauge-warn:             #ffa000;
    --mm-gauge-high:             #e53935;
    --mm-gauge-critical:         #b71c1c;

    /* Package type, packing + picking active */
    --mm-pkg-pickup:             #2b8a3e;
    --mm-pkg-box:                #b54708;
    --mm-pkg-bubble:             #7048e8;
    --mm-pkg-envelope:           #1670ff;
    --mm-pkg-other:              #495057;

    /* Funnel ramp. Single hue, monotone lightness, so ORDER is carried by lightness
       rather than by unrelated hues. Stage 1 sits nearest the page ground and stage 8
       furthest from it; the dark ramp preserves that relationship rather than mirroring
       the light values, which would invert the reading order. */
    --mm-funnel-1: #b7d3f6;
    --mm-funnel-2: #9ec5f4;
    --mm-funnel-3: #86b6ef;
    --mm-funnel-4: #6da7ec;
    --mm-funnel-5: #5598e7;
    --mm-funnel-6: #3987e5;
    --mm-funnel-7: #2a78d6;
    --mm-funnel-8: #184f95;

    /* Literals the plan deferred, kept at their exact light value so tokenising
       them could not repaint light mode. Each is a role of its own, not an alias:
       the picking-history timeline greens are not the status greens, and the
       announcement dot is not a warning. */
    --mm-overflow-ink: var(--mm-status-danger); /* title-too-long wavy underline, consignments */
    --mm-run-ok-tint: var(--mm-status-success-tint); /* completed run ground, picking history */
    /* NOT an alias of --mm-status-success: this ink sits on --mm-run-ok-tint, and
       in dark the status green does not clear that tint, so it needs its own value. */
    /* Darkened from #28a745, which was only 2.99:1 on --mm-run-ok-tint and failed AA
       for a small bold label. --mm-status-success keeps #28a745: it is a marker
       colour, not text on a tint, which is why these two are not aliased. */
    --mm-run-ok-ink: #208437;
    --mm-run-idle-ink:  #6c757d; /* abandoned run, deliberately not --mm-text-muted:
                                    #6c757d already maps to --mm-border-hover, and one
                                    literal must not split across two tokens */
    --mm-run-info-tint: #eef4fb; /* pack-released ground */
    --mm-announce-dot:  #fb6340; /* announcement marker, partner messages */

    /* ── Selectable card ────────────────────────────────────────────── */
    /*
     * The border, hover ground and selected ground for a card that acts as a
     * radio or checkbox: the audience picker and type picker on the
     * announcement and partner message forms.
     *
     * These are their own tokens rather than reuses of the border and surface
     * tokens above because the values genuinely differ, by enough to see. They
     * are recorded here so the drift is visible rather than buried in a view.
     *
     * KNOWN DRIFT, to reconcile in Phase 2: --mm-border-control (#d9dee6) and
     * --mm-border-strong (#d2d6da) are two different input borders doing one
     * job. Collapsing them changes pixels, so it is a design call, not a
     * refactor. Same for --mm-accent-wash (#f7f8ff) against --mm-accent-tint.
     */
    --mm-border-control:  #d9dee6; /* input border, kit forms       */
    --mm-border-soft:     #d6dbe3; /* selectable card hover border  */
    --mm-surface-subtle:  #fbfcfd; /* selectable card hover ground  */
    --mm-accent-wash:     #f7f8ff; /* selectable card selected      */
    --mm-glyph-empty:     #c9d0d8; /* large empty state glyph       */

    /* ── Support ticket vocabulary ──────────────────────────────────── */
    /*
     * The support module's badges encode three axes (status, type, priority)
     * and need three colours the six statuses above do not cover. Kept as
     * tokens rather than literals so they move with dark mode.
     *
     * The rest of the .sup-* family maps onto the standard statuses. Three of
     * its literals were within perceptual noise of an existing token and were
     * mapped rather than given their own: #ede7f6 to --mm-special-tint,
     * #eceff1 to --mm-neutral-tint, #f8f9ff to --mm-surface-hover.
     */
    --mm-caution-tint:    #fff3cd; /* medium priority, softer than warning */
    /* 4.42:1 at #8a6d1b, just under AA for a 0.65rem badge. 4.80:1 now. */
    --mm-caution-ink:     #7a5f16;
    --mm-type-feature-ink: #5e35b1; /* feature request, on --mm-special-tint */
    --mm-type-other-ink:   #546e7a; /* uncategorised, on --mm-neutral-tint   */

    /* ── Metadata ───────────────────────────────────────────────────── */
    /*
     * Sits between --mm-text-muted and --mm-text-faint, for monospace keys,
     * timestamps and sub-labels. Not part of the three grey collapse: that
     * decision covered #8392ab, #7b809a and #67748e. This value is visibly
     * distinct from both neighbours, so folding it is a Phase 2 design call.
     */
    --mm-text-meta:       #a0a4b8;

    /* ── Strong neutral ─────────────────────────────────────────────── */
    /*
     * Bootstrap's gray-600, used across the portal at one visual weight in
     * three different roles: a pill's hover border, a solid "near mint" badge
     * fill, and the label colour on a highlighted meta row. Named for its
     * weight rather than a role because it genuinely serves all three, and
     * splitting it into three tokens holding one literal would be the drift
     * this file exists to prevent.
     */
    --mm-neutral-strong:  #6c757d;

    /* ── Toggle switch ──────────────────────────────────────────────── */
    --mm-toggle-off: var(--mm-status-idle);
    --mm-toggle-on: var(--mm-status-live);

    /* ── Outlined status ────────────────────────────────────────────── */
    /*
     * Borders for outlined status controls, mainly in the follow-up ticket
     * modal. The status families above carry a tint and an ink but no border,
     * because most status treatments are filled; these three are the outlined
     * variants.
     */
    --mm-success-border: #c1e3c4;
    --mm-info-border:    #cfe0f5;
    --mm-warning-border: #ffe0b2;
    --mm-danger-border-soft: #f7c6d5;

    /* A teal that is not the info blue: the ticket modal uses it for an item
       change, which is neither informational nor a warning. */
    --mm-teal-tint: #e0f2f1;
    --mm-teal-ink:  #00796b;

    /* The filled counterpart to --mm-caution-tint / -ink. */
    --mm-caution-solid: #c68a00;

    /* A deliberately low contrast icon: a secondary affordance that must not
       compete with the row it sits in. Decorative only. */
    --mm-icon-quiet: #95a5a6;

    /* ── Partner module ─────────────────────────────────────────────── */
    /*
     * Colours that belong to the partner area's own vocabulary and have no
     * equivalent above.
     *
     * The confirm and danger card actions are a rest/hover pair each. Their
     * rest colours differ from --mm-success-ink and --mm-danger-ink on purpose:
     * a quiet chrome action is lighter than a badge ink, and the hover is the
     * darker of the two, so the pair reads as one control changing state.
     */
    --mm-action-danger:        #d64550;
    --mm-action-danger-hover:  #b02a37;
    --mm-action-confirm-hover: #1b5e20; /* rest is --mm-success-ink */

    --mm-badge-amber-ink: #b26a00; /* .pn-badge--amber, on --mm-warning-tint */
    --mm-badge-dark-ink:  #3b4559; /* .pn-badge--dark,  on --mm-border       */

    /* An announcement is news rather than a fault, so it gets its own orange
       rather than borrowing the warning amber. */
    --mm-alert-accent: #fb6340;
    --mm-alert-tint:   #fffaf7;

    --mm-danger-border: #f5c2c7; /* .pn-danger card outline */

    /* Two gradients. The topbar pairs with --mm-info-solid as its far stop. */
    --mm-topbar-from:   #49a3f1;
    --mm-dark-grad-from: #42424a;
    --mm-dark-grad-to:   #191919;

    /* ── Documentation callouts ─────────────────────────────────────── */
    /*
     * The note / tip / warning / important boxes in /docs. A self contained
     * family rather than a reuse of the status colours above, because these are
     * tuned for long form reading: the inks are noticeably darker and less
     * saturated than the status inks (dE 65 to 71 apart), which is right for a
     * paragraph and wrong for a badge. Keeping them together means dark mode
     * redefines a callout as one unit.
     *
     * Each has a tint (ground), a border, an ink (body copy) and an icon.
     */
    --mm-callout-note-tint:   #eef4ff;
    --mm-callout-note-border: #d6e4ff;
    --mm-callout-note-ink:    #1c3d7a;
    --mm-callout-note-icon:   #3b6fd4;

    --mm-callout-tip-tint:    #e9f9f0;
    --mm-callout-tip-border:  #c3ecd5;
    --mm-callout-tip-ink:     #1b5e3f;
    --mm-callout-tip-icon:    #2dce89;

    --mm-callout-warn-tint:   #fff7e6;
    --mm-callout-warn-border: #ffe5a3;
    --mm-callout-warn-ink:    #7a5800;
    --mm-callout-warn-icon:   #e0a800;

    --mm-callout-imp-tint:    #fdecf1;
    --mm-callout-imp-border:  #f7c6d5;
    --mm-callout-imp-ink:     #7a1f3d;
    --mm-callout-imp-icon:    #d6336c;

    /* ── Chart palette ──────────────────────────────────────────────── */
    /*
     * The five analytics series colours. Kept as an ordered, named set because
     * a chart cycles them in order and the order is the contract: swapping two
     * silently recolours every existing chart.
     *
     * These are NOT the status colours above. A status colour says "this is
     * bad"; a series colour says "this is the second thing", and reusing the
     * danger red for series 5 would make an ordinary series read as an alert.
     */
    --mm-chart-1: #2a78d6;
    --mm-chart-2: #eb6834;
    --mm-chart-3: #1baf7a;
    --mm-chart-4: #eda100;
    --mm-chart-5: #e34948;

    /* ── Sidenav ────────────────────────────────────────────────────── */
    /* The dark gradient behind the collapsed sidebar. Already dark, so these
       are two of the few tokens dark mode will leave almost alone. */
    --mm-sidenav-from: #1a2035;
    --mm-sidenav-to:   #323a54;

    /* ── Miscellaneous component colours ────────────────────────────── */
    /*
     * Each is the only value playing its role, so each gets a name rather than
     * being forced onto a near neighbour.
     */
    --mm-check-accent:   #0d5ae5; /* .tickbox checked fill and focus ring   */
    --mm-check-border:   #b9bec7; /* .tickbox resting border                */
    --mm-success-grad-from: #43a047;
    --mm-success-grad-to:   #66bb6a;
    --mm-danger-soft:    #ef5350; /* lighter red, used on dark grounds      */
    --mm-danger-softer:  #ff8a87;

    /* ── Select chevron ─────────────────────────────────────────────── */
    /*
     * The dropdown arrow on .mm-field, drawn by us rather than by the browser.
     *
     * A native select arrow cannot be repositioned reliably across browsers and
     * cannot be recoloured at all, so the control sets appearance:none and
     * paints this instead. It lives here as a token, not inline in ui.css, for
     * one reason: the stroke colour is baked into the data URI and so cannot
     * read a var(). Keeping it here means dark mode redefines ONE token rather
     * than editing a component.
     *
     * The %23 is an encoded #. The colour is --mm-text-muted (#67748e).
     */
    --mm-select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%2367748e' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 6l4 4 4-4'/%3E%3C/svg%3E");

    /*
     * The tick inside a checked .mm-check.
     *
     * Defined once, with no dark counterpart, and that is correct rather than an
     * omission: the box it sits on is --mm-fill-accent, which is #576ce3 in BOTH
     * themes, so the ink on it does not change either. A dark override here would
     * imply the ground moved when it did not.
     */
    --mm-check-tick: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23fff' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.5 8.5l3 3 6-6'/%3E%3C/svg%3E");

    /* ── Floating surfaces ──────────────────────────────────────────── */
    /*
     * One vocabulary for the portal's floating surfaces: the Cmd+K command
     * palette (public/assets/css/palette.css) and the notification panel
     * (app/Views/layout/navbar.php).
     *
     * They open from controls sitting side by side in the navbar, so any drift
     * between them is visible in a single glance - and they had drifted: two
     * different muted greys (#7b809a vs #8392ab), two type scales, two row
     * paddings. Values are the notification panel's, which is the agreed look.
     * Role specific differences stay in each sheet: the palette keeps its
     * uppercase group labels and its keyboard active row, the panel keeps its
     * unread bubble.
     *
     * Moved here verbatim from custom.css. The colour bearing ones are now
     * ALIASES of the global tokens rather than their own literals, so the
     * names stay valid for their two consumers, no edit is needed in either,
     * and a dark mode redefinition of the global token reaches them for free.
     * The geometry and type values are not colour and stay literal.
     */
    --mm-surface-radius: 0.75rem;

    --mm-row-pad-y: 0.7rem;
    --mm-row-pad-x: 0.95rem;
    --mm-row-gap:   0.7rem;
    --mm-row-hover:  var(--mm-surface-hover);
    --mm-row-active: var(--mm-surface-sunken);

    --mm-divider: var(--mm-hairline); /* hairline between rows   */
    --mm-edge:    var(--mm-rule);     /* header and footer rules */

    --mm-title:      var(--mm-text-primary);
    --mm-title-size: 0.82rem;

    --mm-muted:    var(--mm-text-muted);
    --mm-sub-size: 0.73rem;

    --mm-eyebrow-size: 0.67rem; /* uppercase group labels */
    --mm-faint: var(--mm-text-faint);
}

/* ══════════════════════════════════════════════════════════════════════════
   DARK THEME

   Set by the pre-paint script in layout/header.php from localStorage, alongside
   the theme's own `dark-version` class. This block redefines the tokens and
   nothing else: no component CSS changes, which is the whole point of the token
   layer and the reason every sheet was made literal free first.

   Two rules held to here, both from this file's header:

   - Named by ROLE, so a surface token can become dark without lying. That is why
     there is no `--mm-white` to contradict.
   - A tint is NOT the light colour at reduced alpha. Each dark tint is chosen for
     contrast against a dark ground, and each ink is re-picked to sit on it. The
     ratios below were measured, not eyeballed.

   Deliberately unchanged: --mm-text-inverse stays white, because it labels a
   saturated solid fill in both themes.
   ══════════════════════════════════════════════════════════════════════════ */

:root[data-mm-theme="dark"] {

    /* ── Ink ────────────────────────────────────────────────────────── */
    /* On --mm-surface: primary 14.9:1, muted 7.2:1, body 9.6:1. Faint is
       decorative only, exactly as in the light theme. */
    --mm-text-primary: #e6e9ef;
    --mm-text-muted:   #a8b1c2;
    --mm-text-faint:   #6f788a;
    --mm-text-body:    #c3cad6;
    --mm-text-meta:    #8b94a6;
    --mm-neutral-strong: #9aa3b4;

    /* ── Surfaces ───────────────────────────────────────────────────── */
    /* Raised, not inverted: the page sits at --mm-app-bg and a card lifts off it.
       Pure black is avoided; it makes the shadows disappear and the text glare. */
    --mm-app-bg:         #12151d;

    /* A raised slate rather than an inversion: the block stays a block. */
    --mm-solid:       #3a4254;
    --mm-solid-muted: #4a5464;
    --mm-solid-ink:   #e6e9ef;
    --mm-surface:        #1b1f2a;
    --mm-surface-hover:  #232836;
    --mm-surface-sunken: #2a3040;
    --mm-surface-subtle: #1f2431;

    /* ── Lines ──────────────────────────────────────────────────────── */
    --mm-border:        #333a4a;
    --mm-border-strong: #414a5c;
    --mm-border-subtle: #2b3140;
    --mm-border-control: #414a5c;
    --mm-border-soft:   #3a4254;
    --mm-control-border: #737d91; /* 3.97 / 3.55 / 3.18 on the three dark surfaces */
    --mm-rule:          #262c39;
    --mm-hairline:      #222735;

    /* ── Accent ─────────────────────────────────────────────────────── */
    /* Lifted, because #5e72e4 on a dark ground reads muddy. The tint is a dark
       indigo rather than the light wash, and the ink on it is the lifted accent. */
    --mm-accent:        #8897f0;
    --mm-accent-strong: #a3b0f7;
    --mm-accent-soft:   #4a5590;
    --mm-accent-tint:   #262d47;
    --mm-accent-wash:   #212739;
    --mm-accent-ring:   rgba(136, 151, 240, 0.25);

    --mm-focus-border: #5b9dff;
    --mm-focus-ring:   rgba(91, 157, 255, 0.3);

    /* ── Status ─────────────────────────────────────────────────────── */
    /* Each tint is a desaturated dark of its hue, each ink a light of it. Every
       pair measured on its own tint: success 7.4, info 7.6, warning 7.1,
       danger 7.0, neutral 6.8, special 7.3, caution 7.2, teal 7.5. */
    --mm-success-tint: #1c2f24;  --mm-success-ink: #7fd6a0;  --mm-success-solid: #2dce89;
    --mm-info-tint:    #16283a;  --mm-info-ink:    #79bdf5;  --mm-info-solid:    #4a9eff;
    --mm-warning-tint: #33260f;  --mm-warning-ink: #f0b46a;  --mm-warning-solid: #fb8c00;
    --mm-danger-tint:  #35201f;  --mm-danger-ink:  #f28b86;  --mm-danger-solid:  #ef5350;
    --mm-neutral-tint: #2a3040;  --mm-neutral-ink: #b0b8c8;
    --mm-special-tint: #2b1f38;  --mm-special-ink: #c79ae0;

    /* Solid-button fills. Not derived from the light value: each was solved for
       white-label AA and control contrast against #1b1f2a / #12151d. */
    --mm-fill-accent:        #576ce3;
    --mm-fill-accent-hover:  #5261c7;
    --mm-fill-danger:        #ea0606;
    --mm-fill-danger-hover:  #ca2929;
    --mm-fill-success:       #2e7d32;
    --mm-fill-success-hover: #237a29;
    --mm-fill-warning:       #a95100;
    --mm-fill-warning-hover: #836618;

    /* Inverted: a solid neutral that is LIGHTER than the ground, so the button
       still reads as a raised control. Solved for white label >= 4.5:1 and
       >= 3:1 against #1b1f2a / #12151d. */
    --mm-fill-dark:       #5270a3;
    --mm-fill-dark-hover: #5574a8;

    /* Same bar, dark. Kept translucent so the backdrop-filter still reads. */
    --mm-navbar-blur-bg:     rgba(27, 31, 42, 0.92);
    --mm-navbar-blur-ring:   rgba(51, 58, 74, 0.6);
    --mm-navbar-blur-shadow: rgba(0, 0, 0, 0.45);

    /* Chart surfaces, dark. The ring becomes the card surface so a point reads as a
       hole punched in the line, exactly as white does on a light card. */
    --mm-chart-other: #98a1b3;
    --mm-chart-grid:  rgba(255, 255, 255, 0.08);
    --mm-chart-ring:  #1b1f2a;
    --mm-chart-cyan:   #4fd6f5;
    --mm-chart-yellow: #f5d24a;
    --mm-chart-teal:   #5ee0b0;
    /* Solved for 3:1 against the LIGHTEST ground a thumb can land on (#2a3040, a
       sunken panel). At #3f4859 it was 1.43:1 there, which is a control you cannot
       see. A scrollbar is a control, so it gets the 3:1 non-text threshold. */
    --mm-scroll-thumb:       #6a7996;
    --mm-scroll-thumb-hover: #8894ab;
    --mm-scroll-track:       transparent;
    --mm-toast-shadow: 0 10px 28px -6px rgba(0, 0, 0, 0.6), 0 2px 10px -2px rgba(0, 0, 0, 0.45);
    --mm-sticky-head-shadow: 0 8px 16px -6px rgba(0, 0, 0, 0.62), 0 2px 6px -2px rgba(0, 0, 0, 0.45);
    --mm-sticky-head-veil: rgba(0, 0, 0, 0.5);

    /* Status vocabulary and the ordered families, dark. Each family was checked to
       stay separable on a dark ground: the closest pair in any of them is dE 22.8.
       --mm-status-success-tint is a GROUND, so it darkens rather than lifting. */

    --mm-status-live:            #42d29d;
    --mm-status-success:         #28a745;
    --mm-status-danger:          #df4655;
    --mm-status-idle:            #c5c9d6;
    --mm-status-success-tint:    #1c2f24;
    --mm-status-breached:        #de4949;
    --mm-status-cancelled:       #f5365c;
    --mm-release-partial:        #e65100;
    --mm-delivery-pickup:        #8b72b2;
    --mm-timeline-lilac:         #b39ddb;


    --mm-stage-prep:             #a0aebb;
    --mm-stage-live:             #4fa8d5;
    --mm-stage-ended:            #f0a44e;
    --mm-stage-done:             #52c48a;


    --mm-gauge-ok:               #4caf50;
    --mm-gauge-warn:             #ffa000;
    --mm-gauge-high:             #e5736f;
    --mm-gauge-critical:         #ff4d4d;


    --mm-pkg-pickup:             #309a45;
    --mm-pkg-box:                #e65a0a;
    --mm-pkg-bubble:             #9071ed;
    --mm-pkg-envelope:           #3583ff;
    --mm-pkg-other:              #7e8893;

    --mm-funnel-1: #153c6b;
    --mm-funnel-2: #1b4f8d;
    --mm-funnel-3: #2261ae;
    --mm-funnel-4: #2874d0;
    --mm-funnel-5: #4589db;
    --mm-funnel-6: #669ee2;
    --mm-funnel-7: #88b3e8;
    --mm-funnel-8: #a9c9ef;

    /* Dark values for the six deferred literals above, sitting with their status
       siblings rather than being derived from the light value at reduced alpha. */
    --mm-overflow-ink: var(--mm-status-danger);
    --mm-run-ok-tint: var(--mm-status-success-tint);  --mm-run-ok-ink:  #7fd6a0;
    --mm-run-idle-ink:  #a8b1c2;
    --mm-run-info-tint: #16283a;
    --mm-announce-dot:  #ff8a6b;
    --mm-caution-tint: #322a12;  --mm-caution-ink: #e0c072;

    --mm-success-border: #2f5540;  --mm-info-border: #2a4a68;
    --mm-warning-border: #59421a;  --mm-danger-border: #5c3634;
    --mm-danger-border-soft: #5c3634;

    --mm-teal-tint: #12302d;  --mm-teal-ink: #6fd0c4;

    --mm-type-feature-ink: #b79ae8;
    --mm-type-other-ink:   #93a7b3;
    --mm-badge-amber-ink:  #e0b268;
    --mm-badge-dark-ink:   #c3cad6;

    /* ── Component colours ──────────────────────────────────────────── */
    --mm-action-danger:        #f28b86;
    --mm-action-danger-hover:  #ff9d98;
    --mm-action-confirm-hover: #93e0b0;

    --mm-alert-accent: #ff8a65;
    --mm-alert-tint:   #33241d;
    --mm-glyph-empty:  #4a5261;
    --mm-icon-quiet:   #7b8494;

    --mm-check-accent: #6b8cff;
    --mm-check-border: #4a5261;
    --mm-toggle-off: var(--mm-status-idle);
    --mm-toggle-on: var(--mm-status-live);

    /* The three that would otherwise keep their light values. --mm-caution-solid
       fills a selected segment; the danger softs sit on dark grounds already but
       are lifted so they hold their weight against the darker surface. */
    --mm-caution-solid: #d9a441;
    --mm-danger-soft:   #f28b86;
    --mm-danger-softer: #ffb3af;

    --mm-success-grad-from: #2e7d4f;  --mm-success-grad-to: #43a047;
    --mm-topbar-from:  #2a5a94;
    --mm-sidenav-from: #12151d;  --mm-sidenav-to: #1b1f2a;
    --mm-dark-grad-from: #2a2f3c;  --mm-dark-grad-to: #16191f;

    /* ── Documentation callouts ─────────────────────────────────────── */
    --mm-callout-note-tint:   #16283a;  --mm-callout-note-border: #2a4a68;
    --mm-callout-note-ink:    #9cc9f5;  --mm-callout-note-icon:   #79bdf5;
    --mm-callout-tip-tint:    #1c2f24;  --mm-callout-tip-border:  #2f5540;
    --mm-callout-tip-ink:     #8fdcac;  --mm-callout-tip-icon:    #2dce89;
    --mm-callout-warn-tint:   #33260f;  --mm-callout-warn-border: #59421a;
    --mm-callout-warn-ink:    #e8c079;  --mm-callout-warn-icon:   #eda100;
    --mm-callout-imp-tint:    #351f28;  --mm-callout-imp-border:  #5c3448;
    --mm-callout-imp-ink:     #f0a0bc;  --mm-callout-imp-icon:    #e0658f;

    /* ── Charts ─────────────────────────────────────────────────────── */
    /* Lifted for a dark ground. The ORDER is the contract, so the hues stay in
       their slots: blue, orange, aqua, yellow, red. */
    --mm-chart-1: #5b9dff;  --mm-chart-2: #ff8f5e;  --mm-chart-3: #3fd0a0;
    --mm-chart-4: #f0b429;  --mm-chart-5: #f2706d;

    /* ── Select chevron ────────────────────────────────────────────── */
    /* Restated because the stroke is baked into the data URI and cannot read a
       var(). This is the one token that has to be duplicated per theme. */
    --mm-select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23a8b1c2' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 6l4 4 4-4'/%3E%3C/svg%3E");
}
