/* ==========================================================================
   MAHAPARV THEME — design tokens
   ==========================================================================
   ONE :root block holding the 201 tokens the app actually resolves.

   This file used to hold 23 :root blocks — one per candidate palette (Aurora,
   and 22 alternatives) — all of them live and uncommented. CSS cascades, so
   they did not "switch": every token resolved to its LAST definition and the
   rest were overridden. The file read like a theme picker but behaved like a
   single theme assembled accidentally out of 23 layers.

   Note the trap that made this worth doing carefully: the effective palette was
   NOT simply the last block. That block defines only 96 tokens, while 105 more
   were still resolving from earlier blocks that later ones never redefined.
   Deleting all but the last would have silently dropped 105 tokens. What
   follows is the merged result — byte-for-byte the same computed values the
   browser was already using.

   To change a value, edit it here. To trial a palette, edit these tokens on a
   branch rather than appending another :root block.
   ========================================================================== */

/* --- Import Fonts ---------------------------------------------------------
   ONE URL, three families, three weights — everything the app chrome renders:
     Roboto + Noto Sans Devanagari   --font-primary   since 2026-11-14 (owner, P1 of
                                      design_concepts/app_fonts_preview.html): English
                                      in Roboto, Marathi and Hindi in Noto Sans
                                      Devanagari, which draws the Marathi shapes of
                                      ल and श on a lang="mr" page (Hind drew the Hindi
                                      ones). Android's own pair.
     Mukta   --font-brand     the business-name wordmark only
     Hind, Inter              fallbacks (Hind was the app face until 2026-11-14)

   Weights stop at 600 on purpose: MATERIAL_DESIGN §3 bans 700/800/900, so
   loading them only paid for bytes no rule may use (and let a stray <b> paint
   a real 700 instead of a synthesised one — the base rule in style.css now
   pins b/strong/th/h1–h6 to --md-weight-semibold).

   Self-hosted since 2026-11-02 (shared/assets/fonts/ui/, latin, latin-ext and
   devanagari subsets only): the Google sheet was a render-blocking request to
   a second server, plus a third for the files. The browser still downloads a
   file only when a glyph in its unicode-range is drawn. The display faces
   live in marketing.css (artwork fonts, marketing pages only).
   -------------------------------------------------------------------------- */
/* Roboto (English) + Noto Sans Devanagari (Marathi, Hindi), the owner's P1 of
   design_concepts/app_fonts_preview.html, 2026-11-14: Android's own pair. Both
   are variable fonts, one file per script for every weight. */
@font-face { font-family: 'Roboto'; font-style: normal; font-weight: 100 900; font-display: swap; src: url('../fonts/ui/roboto-latin-ext-b052d8.woff2') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Roboto'; font-style: normal; font-weight: 100 900; font-display: swap; src: url('../fonts/ui/roboto-latin-75be45.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Noto Sans Devanagari'; font-style: normal; font-weight: 100 900; font-display: swap; src: url('../fonts/ui/noto-sans-devanagari-049373.woff2') format('woff2'); unicode-range: U+0900-097F, U+1CD0-1CF4, U+1CF7-1CF9, U+200C-200D, U+20A8, U+20B9, U+20F0, U+25CC, U+A830-A839, U+A8E0-A8FF, U+11B00-11B0A; }
@font-face { font-family: 'Hind'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/ui/hind-devanagari-6a0ff0.woff2') format('woff2'); unicode-range: U+0900-097F, U+1CD0-1CF4, U+1CF7-1CF9, U+200C-200D, U+20A8, U+20B9, U+20F0, U+25CC, U+A830-A839, U+A8E0-A8FF, U+11B00-11B0A; }
@font-face { font-family: 'Hind'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/ui/hind-latin-ext-883939.woff2') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Hind'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/ui/hind-latin-335c83.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Hind'; font-style: normal; font-weight: 500; font-display: swap; src: url('../fonts/ui/hind-devanagari-385b76.woff2') format('woff2'); unicode-range: U+0900-097F, U+1CD0-1CF4, U+1CF7-1CF9, U+200C-200D, U+20A8, U+20B9, U+20F0, U+25CC, U+A830-A839, U+A8E0-A8FF, U+11B00-11B0A; }
@font-face { font-family: 'Hind'; font-style: normal; font-weight: 500; font-display: swap; src: url('../fonts/ui/hind-latin-ext-93dbb1.woff2') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Hind'; font-style: normal; font-weight: 500; font-display: swap; src: url('../fonts/ui/hind-latin-e4ba92.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Hind'; font-style: normal; font-weight: 600; font-display: swap; src: url('../fonts/ui/hind-devanagari-0575d3.woff2') format('woff2'); unicode-range: U+0900-097F, U+1CD0-1CF4, U+1CF7-1CF9, U+200C-200D, U+20A8, U+20B9, U+20F0, U+25CC, U+A830-A839, U+A8E0-A8FF, U+11B00-11B0A; }
@font-face { font-family: 'Hind'; font-style: normal; font-weight: 600; font-display: swap; src: url('../fonts/ui/hind-latin-ext-4d45fe.woff2') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Hind'; font-style: normal; font-weight: 600; font-display: swap; src: url('../fonts/ui/hind-latin-89d0ca.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/ui/inter-latin-ext-749a30.woff2') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/ui/inter-latin-1ab1ad.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 500; font-display: swap; src: url('../fonts/ui/inter-latin-ext-749a30.woff2') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 500; font-display: swap; src: url('../fonts/ui/inter-latin-1ab1ad.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 600; font-display: swap; src: url('../fonts/ui/inter-latin-ext-749a30.woff2') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 600; font-display: swap; src: url('../fonts/ui/inter-latin-1ab1ad.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Mukta'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/ui/mukta-devanagari-8db538.woff2') format('woff2'); unicode-range: U+0900-097F, U+1CD0-1CF4, U+1CF7-1CF9, U+200C-200D, U+20A8, U+20B9, U+20F0, U+25CC, U+A830-A839, U+A8E0-A8FF, U+11B00-11B0A; }
@font-face { font-family: 'Mukta'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/ui/mukta-latin-ext-217301.woff2') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Mukta'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/ui/mukta-latin-c4997f.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Mukta'; font-style: normal; font-weight: 500; font-display: swap; src: url('../fonts/ui/mukta-devanagari-574d88.woff2') format('woff2'); unicode-range: U+0900-097F, U+1CD0-1CF4, U+1CF7-1CF9, U+200C-200D, U+20A8, U+20B9, U+20F0, U+25CC, U+A830-A839, U+A8E0-A8FF, U+11B00-11B0A; }
@font-face { font-family: 'Mukta'; font-style: normal; font-weight: 500; font-display: swap; src: url('../fonts/ui/mukta-latin-ext-5ad140.woff2') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Mukta'; font-style: normal; font-weight: 500; font-display: swap; src: url('../fonts/ui/mukta-latin-55b0a5.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Mukta'; font-style: normal; font-weight: 600; font-display: swap; src: url('../fonts/ui/mukta-devanagari-86eaa0.woff2') format('woff2'); unicode-range: U+0900-097F, U+1CD0-1CF4, U+1CF7-1CF9, U+200C-200D, U+20A8, U+20B9, U+20F0, U+25CC, U+A830-A839, U+A8E0-A8FF, U+11B00-11B0A; }
@font-face { font-family: 'Mukta'; font-style: normal; font-weight: 600; font-display: swap; src: url('../fonts/ui/mukta-latin-ext-475a5c.woff2') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Mukta'; font-style: normal; font-weight: 600; font-display: swap; src: url('../fonts/ui/mukta-latin-0d77f4.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }

/* ==========================================================================
   MATERIAL 3 ROLE LAYER
   ==========================================================================
   The app is moving to Material 3. These are M3's colour ROLES mapped onto the
   values already in use below — no new colours are introduced here. A role says
   what a colour is FOR ("--md-primary-container"), never what it looks like
   ("--blossom"), which is why a theme change becomes a token edit instead of a
   sweep through 127 pages.

   The `on-` counterpart of every role is the colour guaranteed to be legible ON
   it. Use the pair together and contrast stops being decided per component:

       background: var(--md-primary-container);
       color:      var(--md-on-primary-container);

   Legacy tokens (--primary, --ink, --border …) still work and still drive these
   roles, so nothing breaks while modules migrate one at a time.
   ========================================================================== */
:root {
    /* ── accent roles ──────────────────────────────────────────────────── */
    /* Atlas Blue. Deep enterprise blue is the strongest "your money is safe
       here" signal a business app can send, and it sits far from the paid-green
       and overdue-red money hues below, so a status can never be mistaken for
       brand chrome. 6.4:1 on white. */
    --md-primary:               #0B57D0;
    --md-on-primary:            #FFFFFF;
    --md-primary-container:     #D8E2FF;   /* = --saffron-light            */
    --md-on-primary-container:  #001A41;   /* = --saffron-dark             */

    /* The vivid blue. Gradients, sparkline strokes, chart fills — anywhere
       nothing sits ON TOP of it. Never a text background. */
    --md-bold:                  #3B82F6;

    /* Slate. Neutral by design: with a blue primary, a second saturated hue
       would compete with it for attention, so the secondary role steps back
       and lets the money semantics own the colour. */
    --md-secondary:             #575E71;
    --md-on-secondary:          #FFFFFF;
    --md-secondary-container:   #DBE2F9;
    --md-on-secondary-container:#141B2C;

    --md-tertiary:              #006A60;   /* teal — links, data accents   */
    --md-on-tertiary:           #FFFFFF;
    --md-tertiary-container:    #9EF2E4;
    --md-on-tertiary-container: #00201C;

    /* Under the old rose brand, error had to be separated from primary by
       TONE because both sat in the red band. Atlas removes that constraint —
       a blue brand and a red error are hues apart — but the rule that came out
       of it stands: never rely on colour alone, always pair with an icon and
       text. Someone red-green colourblind reads the icon, not the hue. */
    --md-error:                 #BA1A1A;
    --md-on-error:              #FFFFFF;
    --md-error-container:       #FFDAD6;
    --md-on-error-container:    #410002;

    /* ── money semantics ───────────────────────────────────────────────────
       Credit and debit are conventions, not brand decisions. These are
       generated at fixed hues (150 / 32) and must NOT be re-pointed at brand
       roles when the theme changes: an owner scanning a day book should
       never have to learn what our brand colour means.
       Paid · received · credit → pos.  Overdue · spent · debit → neg. */
    --md-pos:                   #0C6D38;
    --md-on-pos:                #FFFFFF;
    --md-pos-container:         #9FF5B6;
    --md-on-pos-container:      #002209;

    --md-neg:                   #9A4431;
    --md-on-neg:                #FFFFFF;
    --md-neg-container:         #FFDBD1;
    --md-on-neg-container:      #370E00;

    /* ── warning ──────────────────────────────────────────────────────────
       Pending, maintenance, "needs attention" — neither an error nor a success.
       The modules were reaching for a raw amber in ~25 places because this role
       did not exist. Generated at hue 70: 30 degrees clear of debit-red (40),
       well clear of credit-green (150). */
    --md-warn:                  #895100;
    --md-on-warn:               #FFFFFF;
    --md-warn-container:        #FFDCBC;
    --md-on-warn-container:     #291800;

    /* ── a module home's one action ────────────────────────────────────────
       The filled bar a module home carries — "Add New Customer" on the CRM
       home, and whatever the same slot holds on the ten homes that follow it.

       Not `--md-primary`: the app bar directly above it is already the brand
       gradient, so a blue bar under a blue bar reads as more of the same
       surface rather than as the thing to press.

       Crimson — and deliberately the SAME crimson the print palette calls an
       alert, written as a reference rather than a second copy of the hex,
       because two literals drift and one does not. Frozen across both schemes
       for the reason `--grad-hero` is: white on it reads 6.6:1 either way, so
       there is no restatement in the dark block (the var() indirection follows
       `--md-paper-alert`, which IS restated there).

       NOT the delete colour. Destructive stays `.md-btn--danger` — tonal
       `--md-error`, an outlined red whisper. A filled red bar is the screen's
       invitation; a filled red bar for delete would be a trap. */
    --md-cta:                   var(--md-paper-alert);
    --md-on-cta:                var(--md-on-brand);

    /* ── white that is NOT a surface ───────────────────────────────────────
       theme_parity_test.php used to exempt white as "an absolute, not a
       palette choice". For text that is true. For a SURFACE it is the opposite
       — a white card is the most scheme-dependent decision a page makes — and
       treating the two the same is why dark mode painted white cards under
       near-white text on every unmigrated page.

       So the exemption is gone, and these three roles replace it. All are
       #FFFFFF in both schemes, but each says WHY it does not invert, which is
       what lets a later palette move them independently:

       --md-on-brand  sits on the brand gradient. --grad-hero is deliberately
                      the same blue in dark (Phase 1 §3.1), so a CTA on top of
                      it must not invert either or it goes dark-on-blue.
       --md-paper     stands in for something that is not part of the app's
                      surface at all: a printed ID card or payslip, a preview
                      of the public storefront, a rich-text canvas the owner
                      types black text into, the backing a transparent logo or
                      a QR code needs to stay scannable.
       --md-thumb     a switch thumb. It rides a coloured track, never a
                      surface, and a light thumb is the physical metaphor in
                      both schemes.

       Anything else that wants white wants --md-surface-container-lowest. */
    --md-on-brand:              #FFFFFF;
    --md-paper:                 #FFFFFF;
    --md-thumb:                 #FFFFFF;

    /* ── the ink that goes ON paper ────────────────────────────────────────
       --md-paper gave a printed artifact its white, and stopped there. The
       TEXT on it kept using --md-on-surface, which does invert — so under
       dark theme the HR identity card painted near-white text on its own
       white card, and exported a PNG in exactly that state. A white surface
       needed a reason not to invert; so does everything drawn on it.

       These four are the light palette's ink, restated as paper's own and
       frozen in both schemes. Use them ONLY inside something that is paper:
       an ID card, a payslip, a storefront preview. Anywhere else, the app's
       surface roles are correct and inverting is the point. */
    --md-paper-ink:             #1A1B20;   /* = light --md-on-surface         */
    --md-paper-ink-soft:        #44474F;   /* = light --md-on-surface-variant */
    --md-paper-line:            #C4C6D0;   /* = light --md-outline-variant    */
    --md-paper-alert:           #B3261E;   /* blood group, and nothing else   */

    /* ── tonal chips ON paper ──────────────────────────────────────────────
       The six .md-tint-* pairs, restated as paper's own and frozen, for the
       same reason the ink above is: those classes resolve to the app's
       *-container roles, which invert, so an icon chip on a printed card
       goes dark after sunset — and the PNG export, taken from the live DOM,
       bakes that in. A printed artifact wants the light palette's chips
       whatever the screen is doing.

       Pale ground, dark glyph: the pairing an inkjet reproduces honestly and
       a photocopier still separates. Use ONLY inside something that is
       paper — an ID card, a QR poster, a payslip. */
    --md-paper-blue:            #D8E2FF;   --md-paper-on-blue:   #001A41;
    --md-paper-teal:            #9EF2E4;   --md-paper-on-teal:   #00201C;
    --md-paper-green:           #9FF5B6;   --md-paper-on-green:  #002209;
    --md-paper-amber:           #FFDCBC;   --md-paper-on-amber:  #291800;
    --md-paper-slate:           #DBE2F9;   --md-paper-on-slate:  #141B2C;
    --md-paper-coral:           #FFDBD1;   --md-paper-on-coral:  #370E00;

    /* ── surfaces: the tile gradient stops already used app-wide ───────── */
    --md-surface:                    #F9F9FF;
    --md-surface-container-lowest:   #FFFFFF;
    --md-surface-container-low:      #F3F3FA;
    --md-surface-container:          #EDEDF4;
    --md-surface-container-high:     #E7E8EE;
    --md-surface-container-highest:  #E2E2E9;
    --md-on-surface:            #1A1B20;   /* = --ink                       */
    --md-on-surface-variant:    #44474F;   /* = --pv-sub, the flat-UI text  */
    /* #74777F until 2026-11-05: 4.48:1 on white, and ~50 rules use it as
       the quiet grey for words. Three steps darker clears 4.5 on white and on
       --md-surface; as a border nobody will see the change. */
    --md-outline:               #6E7179;
    /* Was #EBEEF3 — 1.16:1 against white, i.e. an invisible divider. M3 asks
       3:1 of non-text; tone 78 is the first value that reads as a line. */
    --md-outline-variant:       #C4C6D0;
    --md-inverse-surface:       #2F3036;
    --md-inverse-on-surface:    #F0F0F7;

    /* The one scrim behind every modal (APP_STANDARDS §7). A token because the
       value is a colour and colours live here: written inline it was invisible
       to the theme-parity test, which is how three different scrims ended up
       shipping. Navy-tinted rather than neutral black — the same ink as the
       app's own text, so a dialog reads as this app dimming itself. It does NOT
       re-point in dark: a dark scheme still needs the layer behind the dialog
       to go darker, not lighter. */
    --md-scrim:                 rgba(15, 23, 42, .62);

    /* ── brand marks (NOT theme roles) ─────────────────────────────────── */
    /* WhatsApp's green. It is not ours to re-tint and it must NOT invert with
       the theme — a WhatsApp button that goes pale in dark mode stops being
       recognisable as one, which is the entire job the colour does here.
       Declared once so the pages that need it stop writing #25D366 inline;
       there is no dark override on purpose. */
    --brand-whatsapp:           #25D366;
    --brand-whatsapp-ink:       #0B6B37;
    --brand-whatsapp-tint:      rgba(37, 211, 102, .10);

    /* The other marks an owner links their storefront to. Same argument as
       WhatsApp's green and the same rule: a brand mark is not ours to re-tint,
       so it does NOT follow the scheme. The ink values are the darkened stops
       — a mark drawn at its own hue on a 12% wash of itself, which is how the
       social list tints its rows; the raw brand blue would sit under 4.5:1 on
       that wash for anything smaller than a glyph.

       Declared here, and only here, because theme.css is the one file allowed
       to hold a colour (APP_STANDARDS §2.0) — miniwebsite/social.css mixes its
       washes out of these with color-mix() and holds no hex of its own. */
    --brand-facebook:           #1877F2;
    --brand-facebook-ink:       #0B4FA8;
    --brand-instagram:          #E4405F;
    --brand-instagram-ink:      #B02342;
    --brand-youtube:            #FF0000;
    --brand-youtube-ink:        #B71C1C;
    --brand-linkedin:           #0A66C2;
    --brand-linkedin-ink:       #084A8E;
    /* X's mark is literally black, and black on a dark surface is not a mark
       at all — this is the one brand colour that MUST flip, which is why it
       has an override below and WhatsApp does not. */
    --brand-x:                  #0F1419;
    --brand-x-ink:              #0F1419;

    /* The well a document or photo is viewed against, and the page a PDF is
       rendered on. Both are deliberately CONSTANT across themes: a scan is
       judged against its surround, and a well that flips from near-black to
       near-white changes what the picture appears to be. Every photo viewer
       worth copying does the same. Roles would invert; these must not. */
    --media-well:               #11121A;
    --media-page:               #FFFFFF;

    /* ── shape scale ───────────────────────────────────────────────────── */
    /* Flat: corners tighten. --md-shape-full stays round on purpose — moving
       it would square off every badge, avatar and nav indicator too. */
    --md-shape-xs:   4px;
    --md-shape-sm:   8px;
    --md-shape-md:  10px;
    --md-shape-lg:  12px;
    --md-shape-xl:  18px;
    --md-shape-full: 999px;

    /* ── elevation — FLAT ──────────────────────────────────────────────────
       Design decision: flat. But depth cannot simply be deleted. A card is
       #FFFFFF on a #F7F8FB ground — 1.05:1 apart — so with no shadow and no
       outline it dissolves into the page. Elevation therefore becomes an
       OUTLINE: these tokens are inset hairline rings, not drop shadows.

       Expressed as tokens rather than edited per component so that all five
       call sites in components.css flip without being touched, and so that
       reverting to a shadowed theme is a four-line change here.

       elev-3 is the one exception: the FAB floats above scrolling content, and
       with no shadow at all the list scrolls "under" it and it reads as pasted
       on. It keeps the smallest shadow that still separates it. Delete that
       line if you want the FAB flat too — nothing else depends on it. */
    --md-elev-0: none;
    --md-elev-1: inset 0 0 0 1px var(--md-outline-variant);
    --md-elev-2: inset 0 0 0 1px var(--md-outline-variant);
    --md-elev-3: 0 4px 10px -4px rgba(15,23,42,.28);

    /* ── motion ────────────────────────────────────────────────────────── */
    --md-ease:          cubic-bezier(.2,0,0,1);
    --md-ease-emphasized:cubic-bezier(.34,1.56,.64,1);
    --md-dur-short:  150ms;
    --md-dur-medium: 250ms;
    --md-dur-long:   400ms;

    /* ── state layer opacities (M3 spec) ───────────────────────────────── */
    --md-state-hover: .08;
    --md-state-focus: .12;
    --md-state-press: .12;
}

/* ==========================================================================
   DARK SCHEME
   The same six tonal palettes read at flipped tones — primary 80 instead of
   40, containers 30 instead of 90. Every `on-` pair below stays >=40 tone
   steps from its partner, so contrast holds without per-component checking.

   Opt-in only: nothing in the app sets data-theme="dark" yet. It exists now
   rather than later because retrofitting a second scheme across 127 migrated
   pages is a different job from defining it while 0 are migrated.

   Legacy tokens are NOT redefined here — they still drive un-migrated pages,
   which are light-only. A page is dark-ready exactly when it has stopped
   using them.
   ========================================================================== */
[data-theme="dark"] {
    --myra: #5FDBB4;   /* her emerald, dark */
    /* The customer mode's own hue, Dusk (aubergine until 2026-11-03) (see --md-mode-* in the light block). */
    --md-mode-customer:               #FFB1C9;
    --md-mode-customer-container:     #7E1F48;
    --md-on-mode-customer-container:  #FFD9E4;
    /* The employee mode's own hue (see --md-mode-* in the light block). */
    --md-mode-employee:               #C8BBFF;
    --md-mode-employee-container:     #3F2E85;
    --md-on-mode-employee-container:  #E6DEFF;
    --md-primary:               #ADC6FF;
    --md-on-primary:            #002E69;
    --md-primary-container:     #004494;
    --md-on-primary-container:  #D8E2FF;

    --md-bold:                  #60A5FA;

    --md-secondary:             #BFC6DC;
    --md-on-secondary:          #293042;
    --md-secondary-container:   #3F4759;
    --md-on-secondary-container:#DBE2F9;

    --md-tertiary:              #82D5C6;
    --md-on-tertiary:           #003730;
    --md-tertiary-container:    #005046;
    --md-on-tertiary-container: #9EF2E4;

    --md-error:                 #FFB4AB;
    --md-on-error:              #690005;
    --md-error-container:       #93000A;
    --md-on-error-container:    #FFDAD6;

    --md-pos:                   #83D99B;
    --md-on-pos:                #003919;
    --md-pos-container:         #005227;
    --md-on-pos-container:      #9FF5B6;

    --md-neg:                   #FFB4A1;
    --md-on-neg:                #690005;
    --md-neg-container:         #7D2C1B;
    --md-on-neg-container:      #FFDBD1;

    --md-warn:                  #FFB86B;
    --md-on-warn:               #472A00;
    --md-warn-container:        #683D00;
    --md-on-warn-container:     #FFDCBC;

    --md-surface:                    #121318;
    --md-surface-container-lowest:   #0D0E13;
    --md-surface-container-low:      #1A1B20;
    --md-surface-container:          #1E1F25;
    --md-surface-container-high:     #282A2F;
    --md-surface-container-highest:  #33353A;
    --md-on-surface:            #E2E2E9;
    --md-on-surface-variant:    #C4C6D0;
    --md-outline:               #8E9099;
    --md-outline-variant:       #44474F;
    --md-inverse-surface:       #E2E2E9;
    --md-inverse-on-surface:    #2F3036;

    /* Flat in dark too. The ring resolves against this scheme's own
       --md-outline-variant, so it stays visible on a dark ground. */
    --md-elev-1: inset 0 0 0 1px var(--md-outline-variant);
    --md-elev-2: inset 0 0 0 1px var(--md-outline-variant);
    --md-elev-3: 0 4px 12px -4px rgba(0,0,0,.6);

    /* Restated, not inherited, so the reason is visible from inside the dark
       block too: these three are white HERE as well, on purpose. See the
       block that defines them in :root. */
    --md-on-brand: #FFFFFF;
    --md-paper:    #FFFFFF;
    --md-thumb:    #FFFFFF;

    /* Paper does not invert, so neither does its ink. Restated here for the
       same reason the three above are: read from inside the dark block, the
       absence of these would look like an oversight rather than a decision. */
    --md-paper-ink:      #1A1B20;
    --md-paper-ink-soft: #44474F;
    --md-paper-line:     #C4C6D0;
    --md-paper-alert:    #B3261E;

    /* And neither do its tonal chips. Same decision, restated. */
    --md-paper-blue:  #D8E2FF;   --md-paper-on-blue:  #001A41;
    --md-paper-teal:  #9EF2E4;   --md-paper-on-teal:  #00201C;
    --md-paper-green: #9FF5B6;   --md-paper-on-green: #002209;
    --md-paper-amber: #FFDCBC;   --md-paper-on-amber: #291800;
    --md-paper-slate: #DBE2F9;   --md-paper-on-slate: #141B2C;
    --md-paper-coral: #FFDBD1;   --md-paper-on-coral: #370E00;
}

:root {
    --iris: var(--brand-accent);
    --iris-light: #DBE2F9;
    --iris-dark: #141B2C;
    --rose: var(--brand-primary);
    --rose-light: var(--saffron-light);
    --amber: var(--gold);
    --amber-light: var(--gold-light);
    --teal: var(--brand-success);
    --teal-light: var(--green-light);
    --ink: #1A1B20;
    --ink-soft: #44474F;
    --muted: #C4C6D0;
    --border: #C4C6D0;
    --surface: #FFFFFF;
    --white: #FFFFFF;
    --primary: var(--brand-primary);
    --primary-light: var(--saffron-light);
    --primary-dark: var(--saffron-dark);
    --secondary: var(--navy);
    --secondary-light: var(--navy-light);
    --tertiary: var(--brand-accent);
    --tertiary-light: var(--iris-light);
    --warning: var(--gold);
    --warning-light: var(--gold-light);
    --error: var(--brand-error);
    --error-light: #FFDAD6;
    --success: var(--brand-success);
    --success-light: var(--green-light);
    --text-primary: #1A1B20;
    --text-secondary: #44474F;
    --text-muted: #6E7179;   /* = --md-outline (was #74777F, 4.48:1 on white) */
    --background: #F9F9FF;
    --disabled: #E7E8EE;
    /* The light stop is a little deeper than it was (#4C82F7 until 2026-11-05):
       the white words on the right of a header — Home's "Website", Products'
       "Show / hide", Customers' "Plan a call" — read 4.0:1 there, and Google
       Play's pre-launch report wants 4.5. Every colour below took the same
       nudge (the least that clears 4.5 to 88% of the way across with the
       --hero-glass strip on top); navy, coffee, graphite and charcoal already
       cleared it and are unchanged. ap_colors() carries the same stops. */
    --grad-hero: linear-gradient(135deg, #003585 0%, #0B57D0 52%, #3774EB 125%);
    /* The frosted strip that rides a header (Home's four shortcuts, a module
       home's quick actions, Inbox's money row). Was .14 white: over the
       gradient's light end that alone took white words under 4.5:1. */
    --hero-glass: rgba(255, 255, 255, .08);

    /* ── The three MODES (2026-09-23, dashboard/partials/modes.php) ─────────
       One person can be three people in this app — an owner, a customer, an
       employee at somebody else's business — and the whole Home
       chrome recolours when they switch, so a reader who does not read still
       knows whose screen they are on. Owner keeps --grad-hero (the app's own
       blue); the other two get a sibling gradient each, built the same way
       (dark → mid → light stop, 135deg, white content on top). Scheme-
       INVARIANT like --grad-hero and for its reason: white sits on all of
       them, nothing on them may invert.
         customer  Dusk, plum to coral (owner's pick, 2026-11-03, K1 on
                   design_concepts/customer_app_preview.html; aubergine from
                   2026-10-06, a red before that, which read as the error colour)
         employee  violet
       Owner's solid role and its container pair are aliases of the primary
       family, so the dark scheme resolves them for free; customer and
       employee are hues the theme did not have, so they are spelled in both
       schemes. */
    --grad-mode-customer: linear-gradient(140deg, #4B0D3A 0%, #A3195B 50%, #F06A4D 120%);
    --grad-mode-employee: linear-gradient(135deg, #2A1B5E 0%, #5741A6 55%, #8B78D9 125%);
    --md-mode-owner:                  var(--md-primary);
    --md-mode-owner-container:        var(--md-primary-container);
    --md-on-mode-owner-container:     var(--md-on-primary-container);
    /* Spelled out, like employee's: aubergine is not a role the theme had
       (it was an alias of the error role while the mode was red). The dark
       values are in the dark block above. */
    --md-mode-customer:               #A3195B;
    --md-mode-customer-container:     #FFD9E4;
    --md-on-mode-customer-container:  #3E0021;
    --md-mode-employee:               #5741A6;
    --md-mode-employee-container:     #E6DEFF;
    --md-on-mode-employee-container:  #1C0A5C;

    /* ── The CUSTOMER app's hero, and its SAND ground ───────────────────────
       Values live here and not in dashboard.css because that is the rule this
       file exists to keep: colour is declared once, in theme.css, and every
       stylesheet downstream only maps it. The customer's Home is the one view
       that re-tints the surface family, so it needs the family SPELLED, and
       spelling it beside the app's own palette is what stops it becoming a
       second, private palette nobody can find.

       ── The gradient ────────────────────────────────────────────────────────
       Same two endpoints as --grad-hero, five stops instead of three. Two-stop
       ramps band across 300px of blue — the ramp is linear in sRGB and the eye
       finds the steps — and the mid-stops are the cheapest fix there is.
       Scheme-INVARIANT, exactly like --grad-hero and for its reason: everything
       on it is white, and a gradient that inverted would put dark text on
       pale blue after sunset. */
    --grad-hero-cv: linear-gradient(146deg,
        #00307A 0%, #063C97 22%, #0B57D0 54%, #2E71E4 82%, #4C82F7 108%);
    /* The two washes over it. Warm at the top-left carries the Sand ground UP
       into the hero so the two blocks read as one screen rather than a warm
       page under a cold lid; the blue at the top-right keeps the brand. Each
       carries its own mid-stops for the same anti-banding reason. */
    --wash-cv-warm: radial-gradient(132% 96% at 6% -22%,
        rgba(255, 206, 148, .28) 0%, rgba(255, 206, 148, .17) 26%,
        rgba(255, 206, 148, .07) 48%, rgba(255, 206, 148, .02) 64%, transparent 78%);
    --wash-cv-cool: radial-gradient(104% 80% at 98% 2%,
        rgba(124, 176, 255, .32) 0%, rgba(124, 176, 255, .19) 30%,
        rgba(124, 176, 255, .07) 52%, transparent 72%);
    /* Glass on that hero: a lit top edge, not a uniform wash. Pinned white at
       low alpha, so it survives both schemes with the surface it sits on. */
    --glass-cv: linear-gradient(168deg,
        rgba(255, 255, 255, .22) 0%, rgba(255, 255, 255, .15) 46%, rgba(255, 255, 255, .11) 100%);
    --glass-cv-soft: linear-gradient(150deg, rgba(255, 255, 255, .20) 0%, rgba(255, 255, 255, .13) 100%);
    --glass-cv-ring: rgba(255, 255, 255, .20);
    --glass-cv-lit:  rgba(255, 255, 255, .32);
    --glass-cv-fill: rgba(255, 255, 255, .22);
    /* The hero's ONE warm accent, for the figure that needs acting on — the
       literal `.dash-hero` already documents, reused so there is one of it. */
    --glass-cv-warn: linear-gradient(150deg, rgba(255, 220, 188, .30) 0%, rgba(255, 220, 188, .20) 100%);
    --on-cv-warn: #FFE7CE;

    /* SAND — the customer Home's ground. Tone for tone with the app's own
       surfaces (#F9F9FF and #FCFAF5 are the same lightness, they differ only
       in hue), so every contrast pair that passed on the cool ground still
       passes on the warm one and nothing downstream needs a second opinion
       about text colour. The dark set is a warm near-black, not a beige one. */
    --sand-surface:        #FCFAF5;
    --sand-lowest:         #FFFFFF;
    --sand-low:            #F7F2E9;
    --sand-container:      #F2ECE1;
    --sand-high:           #ECE5D9;
    --sand-highest:        #E7E0D3;
    /* Tone 78 warm — the tone the cool token uses, for the reason recorded
       there: anything lighter is an invisible divider. */
    --sand-outline:        #CFC7B8;
    --sand-surface-dark:   #16140F;
    --sand-lowest-dark:    #100F0B;
    --sand-low-dark:       #1E1B15;
    --sand-container-dark: #23201A;
    --sand-high-dark:      #2D2A23;
    --sand-highest-dark:   #38342C;
    --sand-outline-dark:   #4C4740;
    /* ── Section hero gradients ─────────────────────────────────────────────
       Siblings of --grad-hero for surfaces that carry WHITE content — the
       dashboard's section cards, and any module home that wants the same
       treatment. Recipes lifted verbatim from theme.html's vetted palettes
       (Emerald Ledger, Ocean Teal, Graphite Pro): each mid-stop holds white at
       6.4:1 or better, the same floor the blue hero meets.

       Scheme-INVARIANT on purpose, like --grad-hero and for the same reason:
       everything on them is white, and a gradient that inverted would put
       that white on a pastel. Do not redefine these under [data-theme=dark],
       and do not point them at role tokens — roles invert, these must not. */
    --grad-green: linear-gradient(135deg, #00391F 0%, #006D44 52%, #2E9E6B 125%);
    /* Amber — the same hue as --md-warn, so the doors above billing/index.php
       (Counter, Tables, Bill — design_concepts/billing_doors_concepts.html
       D2+C1) and the amber row tints below them (Udhari, Supplier dues) read
       as one colour, not two ambers that happen to be close. White holds
       6.5:1 on the mid stop and 3.7:1 on the last — below this family's 6.4
       floor for the reason --grad-green's own last stop already is (3.4:1):
       the far corner sits under a small caption, never the label. */
    --grad-amber: linear-gradient(135deg, #5C3600 0%, #895100 52%, #B87526 125%);
    /* Maroon — the band that says "you are working inside somebody else's
       business" (the staff ribbon, team-chrome.css). Deeper and browner than
       Myra's rose so the two never read as the same thing, and darker than
       --md-error, which is the colour of something going wrong: this is not an
       error, it is a standing fact about the session. White holds 9.1:1 on the
       mid stop and 7.0:1 on the last, above this family's 6.4 floor. Same
       scheme-invariance rule as its siblings. */
    --grad-maroon: linear-gradient(135deg, #4A0A0A 0%, #8E1B14 52%, #A62B21 125%);
    --grad-teal:  linear-gradient(135deg, #00363E 0%, #006874 52%, #2AA6B8 125%);
    /* The night: the desktop Plan page's pass card and Today's closing card.
       White holds 12:1 on the mid stop. Scheme-invariant like every gradient here. */
    --grad-night: linear-gradient(160deg, #0A1A3F 0%, #12306F 55%, #1E4FB5 130%);
    /* The ⚡ that opens Quick add (owner, 2026-11-02, design_concepts/
       action_button_v1_preview.html K1): the night with a gold bolt, so it no
       longer matches the selected tab's blue. Spelled out rather than
       var(--grad-night), which the customer mode re-tints. The gold is the dark
       scheme's --md-warn; it holds 8:1 on the mid stop. Scheme-invariant. */
    --grad-action: linear-gradient(160deg, #0A1A3F 0%, #12306F 55%, #1E4FB5 130%);
    --action-bolt: #FFB86B;
    --grad-slate: linear-gradient(135deg, #0F172A 0%, #334155 55%, #64748B 125%);
    /* Myra, the AI assistant — her identity everywhere she appears (FAB, CTA
       card, her module's hero). Rose, not wine: the lighter voice of the same
       Crimson Pro family (its dark/bold/dark-bold stops), which sits beside
       Atlas Blue instead of underneath it. Mid-stop holds white at 4.7:1.
       Same scheme-invariance rule as every gradient above. */
    --grad-crimson: linear-gradient(135deg, #9F1239 0%, #E11D48 52%, #FB7185 125%);
    /* Her ACCENT pair — text and glows that must flip with the scheme, unlike
       the gradient. Rose-600 on light (4.7:1), rose-400 on dark (7.2:1). */
    --myra: #00876E;   /* her emerald (owner, 2026-10-21: emerald everywhere), as her own skin */
    --grad-card1: linear-gradient(135deg, #0B57D0 0%, #3B82F6 100%);
    --grad-card2: linear-gradient(135deg, #1A1B20 0%, #2F3036 100%);
    --grad-card3: linear-gradient(135deg, #575E71 0%, #3F4759 100%);
    --grad-tonal: linear-gradient(135deg, #D8E2FF 0%, #DBE2F9 100%);
    /* Built from roles, not literals, so it inverts on its own — this is the
       page's ground, and a light ground behind dark cards was the last thing
       reading as "half converted" in dark mode. */
    --grad-ambient: linear-gradient(180deg, var(--md-surface) 0%, var(--md-surface-container-low) 55%, var(--md-surface) 100%);
    --grad-cta: linear-gradient(135deg, #003585 0%, #0B57D0 52%, #3774EB 125%);
    --hero-gradient: var(--grad-hero);
    --card-gradient-1: var(--grad-card1);
    --card-gradient-2: var(--grad-card2);
    --card-gradient-3: var(--grad-card3);
    --ambient-background: var(--grad-ambient);
    /* Roboto first: the browser takes Latin (and ₹) from Roboto and falls back
       per glyph to Noto Sans Devanagari for Marathi and Hindi (owner,
       2026-11-14, P1 of design_concepts/app_fonts_preview.html). Hind stays as
       the fallback it was the face for until then. */
    --font-primary: 'Roboto', 'Noto Sans Devanagari', 'Hind', 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
    /* The business-name wordmark (app bar, welcome card, auth logo, QR sheet)
       is the ONE place that wears a second face. Named for its role;
       --font-secondary is the legacy alias and says only "the other one". */
    --font-brand: 'Mukta', 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
    --font-secondary: var(--font-brand);
    --font-mono: ui-monospace, SFMono-Regular, Menlo, monospace;
    /* Weight ROLES. 600 is the ceiling (MATERIAL_DESIGN §3) — there is no token
       above it, so a banned weight cannot be written by reaching for one. Every
       font-weight in app CSS/PHP/JS resolves through these three; a literal
       number is a defect. Hind has no 550/700 faces: 550 snapped to 600 anyway. */
    --md-weight-regular: 400;
    --md-weight-medium: 500;
    --md-weight-semibold: 600;
    --display-lg: 32px;
    --heading-md: 20px;
    --title: 18px;
    --body-lg: 15px;
    --body-md: 14px;
    --caption: 12px;

    /* ── The desktop step (WEB_ADMIN_PLAN.md §4) ─────────────────────────────
       The scale above is phone-tuned: --display-lg is 32px because it is being
       read at arm's length on a 360px screen. A 1440px window sits further away
       and carries more at once, so a desktop page header needs ONE more step at
       the top and a slightly larger body — not a second scale.

       That is the whole of it: four tokens, all additive. Nothing in frontend/
       references them, so adding them cannot change a phone page (verified by a
       full page_audit and a 54-shot sweep in en and mr on the day they landed).
       web-admin/ uses --wa-display for wa_page_header()'s <h1> and --wa-body
       where a desktop table would otherwise be set at phone size.

       The weight ceiling is unchanged and still 600: a bigger size is how the
       desktop gets emphasis, never a heavier face. */
    --wa-display: 25px;   /* the desktop page title — one step above --heading-md */
    --wa-heading: 21px;   /* a section head inside a desktop panel               */
    --wa-body:    14px;   /* table and form text: --body-md, stated for the swap */
    --wa-caption: 12.5px; /* a desktop caption reads at arm's length, not 12px   */
    --radius-sm: 6px;
    --radius-md: 10px;
    --radius-lg: 12px;
    --radius-xl: 16px;
    --radius-full: 9999px;
    /* Empty room at the foot of every app page (owner: 150px on 2026-10-16,
       halved on 2026-11-03). Pages with a floating button or bar add its height. */
    --page-room: 75px;
    --space-4: 4px;
    --space-8: 8px;
    --space-10: 10px;
    --space-12: 12px;
    --space-16: 16px;
    --space-20: 20px;
    --space-24: 24px;
    --space-32: 32px;
    --space-40: 40px;
    --space-48: 48px;
    --elevation-1: 0 2px 4px rgba(11, 87, 208, 0.05);
    --elevation-2: 0 4px 10px rgba(11, 87, 208, 0.08), 0 2px 4px rgba(0,0,0,0.02);
    --elevation-3: 0 10px 20px rgba(11, 87, 208, 0.12), 0 4px 8px rgba(0,0,0,0.04);
    --elevation-4: 0 20px 40px rgba(11, 87, 208, 0.15), 0 10px 20px rgba(0,0,0,0.06);
    --motion-fast: 150ms cubic-bezier(0.34, 1.56, 0.64, 1);
    --motion-normal: 250ms cubic-bezier(0.34, 1.56, 0.64, 1);
    --viewport-width: 390px;
    /* The stage an image is cropped against. Deliberately fixed in both
       schemes: the point of it is a neutral ground to judge the picture on,
       and a stage that re-themes would change how the crop LOOKS between
       light and dark without changing what it IS. Named once here rather than
       hardcoded in eight pages, which is where it used to live. */
    --crop-stage: #18181B;
    --gold: #895100;
    --gold-light: #FFDCBC;
    --navy: #1A1B20;
    --navy-light: #F3F3FA;
    --saffron: var(--brand-primary);
    --saffron-light: #D8E2FF;
    --saffron-dark: #001A41;
    --green: var(--brand-success);
    --green-light: #9FF5B6;
    --slate: #44474F;
    --brand-primary: #0B57D0;
    --brand-accent: #006A60;
    --brand-success: #0C6D38;
    --brand-error: #BA1A1A;
}

/* ══════════════════════════════════════════════════════════════════════════
   DARK — the legacy aliases, and WHY this block sits down here
   ══════════════════════════════════════════════════════════════════════════
   `:root` and `[data-theme="dark"]` have the SAME specificity (0,1,0), so
   between them source order decides. The alias definitions above live in a
   `:root` block that comes AFTER the main dark block — which meant every
   alias override written up there was dead on arrival, silently losing to a
   `:root` forty lines later.

   That is why "the legacy aliases now invert" changed nothing on screen when
   it first landed: the rules were correct and never applied. Being last in the
   file is not a style choice here, it is the whole mechanism.
   ══════════════════════════════════════════════════════════════════════════ */
[data-theme="dark"] {
    /* Everything in the main dark block above redefines --md-*. Nothing
       redefined --white, --surface, --border or --ink, so a page still written
       in the old vocabulary painted a WHITE card in dark mode — and any --md-*
       text on top of it inverted to near-white. White on white. That is what
       MD3_MIGRATION_PLAN means by "dark mode is actively broken, not merely
       absent": the damage comes from partial tokenisation, where half a page
       follows the scheme and half does not.

       Pointing each alias at the role it already means fixes every unmigrated
       page at once, and costs nothing on a migrated one, which names the role
       directly. The aliases stay deprecated — a page still gets de-coloured
       when its turn comes — but it should not be UNREADABLE until then.

       Deliberately NOT redefined: --grad-hero and the other brand gradients.
       They paint the same blue in both schemes on purpose (Phase 1 §3.1), and
       anything sitting on them takes white or --brand-primary. */
    --ink:            var(--md-on-surface);
    --ink-soft:       var(--md-on-surface-variant);
    --muted:          var(--md-outline);
    --border:         var(--md-outline-variant);
    --surface:        var(--md-surface-container);
    --surface-hover:  var(--md-surface-container-high);
    --white:          var(--md-surface-container-lowest);
    --background:     var(--md-surface);
    --text-primary:   var(--md-on-surface);
    --text-secondary: var(--md-on-surface-variant);
    --text-muted:     var(--md-outline);
    --pv-sub:         var(--md-on-surface-variant);
    --disabled:       var(--md-surface-container-high);

    /* Tonal chip backgrounds: the light values are pale washes that vanish
       against a dark ground, so each takes its container role instead. */
    --primary-light:   var(--md-primary-container);
    --error-light:     var(--md-error-container);
    --success-light:   var(--md-pos-container);
    --warning-light:   var(--md-warn-container);
    --green-light:     var(--md-pos-container);
    --saffron-light:   var(--md-primary-container);
    --iris-light:      var(--md-secondary-container);
    --rose-light:      var(--md-primary-container);
    --amber-light:     var(--md-warn-container);
    --teal-light:      var(--md-tertiary-container);
    --navy-light:      var(--md-surface-container-high);
    --secondary-light: var(--md-surface-container-high);
    --tertiary-light:  var(--md-secondary-container);
    --gold-light:      var(--md-warn-container);

    /* The one brand mark that flips. X's logo is drawn in black on white and
       in white on black by its own brand book, so holding it at #0F1419 in
       dark mode hides it completely. Every other --brand-* stays put. */
    --brand-x:     #E7E9EA;
    --brand-x-ink: #E7E9EA;

    /* Foreground roles that were fixed dark values in light mode. */
    --navy:      var(--md-on-surface);
    --secondary: var(--md-on-surface);
    --slate:     var(--md-on-surface-variant);

    /* --myra, restated. It is set to rose-400 in the FIRST dark block (:289)
       and then to rose-600 by the legacy `:root` block at :419 — same
       specificity, later in the file, so the light value won and Myra's accent
       stayed #E11D48 in dark mode: 4.3:1 on --md-surface, under the 4.5 floor
       for text, which is exactly what the rose-400 value exists to avoid.
       Found while giving her an entry in the bottom dock. */
    --myra: #5FDBB4;   /* her emerald, dark */
}

/* ══════════════════════════════════════════════════════════════════════════
   APP COLOURS (2026-11-03, design_concepts/app_colour_preview.html B)
   The owner picks the app's colour on Profile (dashboard/appearance.php);
   commons/header.php writes it on <body data-color="<key>"> (staff working in a
   business wear the owner's). Each block is a skin like the Customer skin
   below: the primary family, light and dark, and the brand gradients (dark →
   mid → light stop, white holds on all three), so every rule that asks for
   --md-primary or --grad-hero follows with no rule of its own. Blue has no
   block: it is the app's own palette above. --brand-ink is the gradient's
   mid stop, for a glyph on a white disc sitting on the gradient (it does not
   invert). Customer and Employee Portal and the skins (Myra) keep their own
   colour: the :not()s step aside for them. Keys: ap_colors() in
   shared/session/appearance.php.
   ══════════════════════════════════════════════════════════════════════════ */
:root { --brand-ink: #0B57D0; }
body[data-color="navy"]:not([data-mode="customer"]):not([data-mode="employee"]):not([data-skin]) {
    --md-primary: #23408E; --md-on-primary: #FFFFFF; --md-primary-container: #DBE1FF; --md-on-primary-container: #00164E; --md-bold: #3A5BB8;
    --grad-hero: linear-gradient(135deg, #0B1F4F 0%, #23408E 52%, #4A69C2 125%); --grad-cta: var(--grad-hero); --hero-gradient: var(--grad-hero); --grad-mode-owner: var(--grad-hero);
    --grad-card1: linear-gradient(135deg, #23408E 0%, #3A5BB8 100%); --grad-tonal: linear-gradient(135deg, #DBE1FF 0%, #DBE1FF 100%);
    --brand-ink: #23408E; --brand-primary: #23408E; --primary: #23408E; --saffron: #23408E; --rose: #23408E;
    --primary-light: #DBE1FF; --saffron-light: #DBE1FF; --rose-light: #DBE1FF; --primary-dark: #00164E; --saffron-dark: #00164E; --md-paper-on-blue: #00164E;
    --elevation-1: 0 2px 4px rgba(35, 64, 142, 0.05); --elevation-2: 0 4px 10px rgba(35, 64, 142, 0.08), 0 2px 4px rgba(0,0,0,0.02);
    --elevation-3: 0 10px 20px rgba(35, 64, 142, 0.12), 0 4px 8px rgba(0,0,0,0.04); --elevation-4: 0 20px 40px rgba(35, 64, 142, 0.15), 0 10px 20px rgba(0,0,0,0.06);
}
[data-theme="dark"] body[data-color="navy"]:not([data-mode="customer"]):not([data-mode="employee"]):not([data-skin]) {
    --md-primary: #B4C5FF; --md-on-primary: #002A78; --md-primary-container: #20397F; --md-on-primary-container: #DBE1FF;
    --primary-light: #20397F; --saffron-light: #20397F; --rose-light: #20397F; --grad-tonal: linear-gradient(135deg, #20397F 0%, #20397F 100%);
}
body[data-color="sky"]:not([data-mode="customer"]):not([data-mode="employee"]):not([data-skin]) {
    --md-primary: #00639B; --md-on-primary: #FFFFFF; --md-primary-container: #CDE5FF; --md-on-primary-container: #001D32; --md-bold: #2B86C4;
    --grad-hero: linear-gradient(135deg, #003456 0%, #00639B 52%, #1D7FBA 125%); --grad-cta: var(--grad-hero); --hero-gradient: var(--grad-hero); --grad-mode-owner: var(--grad-hero);
    --grad-card1: linear-gradient(135deg, #00639B 0%, #2B86C4 100%); --grad-tonal: linear-gradient(135deg, #CDE5FF 0%, #CDE5FF 100%);
    --brand-ink: #00639B; --brand-primary: #00639B; --primary: #00639B; --saffron: #00639B; --rose: #00639B;
    --primary-light: #CDE5FF; --saffron-light: #CDE5FF; --rose-light: #CDE5FF; --primary-dark: #001D32; --saffron-dark: #001D32; --md-paper-on-blue: #001D32;
    --elevation-1: 0 2px 4px rgba(0, 99, 155, 0.05); --elevation-2: 0 4px 10px rgba(0, 99, 155, 0.08), 0 2px 4px rgba(0,0,0,0.02);
    --elevation-3: 0 10px 20px rgba(0, 99, 155, 0.12), 0 4px 8px rgba(0,0,0,0.04); --elevation-4: 0 20px 40px rgba(0, 99, 155, 0.15), 0 10px 20px rgba(0,0,0,0.06);
}
[data-theme="dark"] body[data-color="sky"]:not([data-mode="customer"]):not([data-mode="employee"]):not([data-skin]) {
    --md-primary: #94CCFF; --md-on-primary: #003352; --md-primary-container: #004A76; --md-on-primary-container: #CDE5FF;
    --primary-light: #004A76; --saffron-light: #004A76; --rose-light: #004A76; --grad-tonal: linear-gradient(135deg, #004A76 0%, #004A76 100%);
}
body[data-color="teal"]:not([data-mode="customer"]):not([data-mode="employee"]):not([data-skin]) {
    --md-primary: #006A6A; --md-on-primary: #FFFFFF; --md-primary-container: #9CF1F0; --md-on-primary-container: #002020; --md-bold: #00897F;
    --grad-hero: linear-gradient(135deg, #00363A 0%, #006A6A 52%, #148686 125%); --grad-cta: var(--grad-hero); --hero-gradient: var(--grad-hero); --grad-mode-owner: var(--grad-hero);
    --grad-card1: linear-gradient(135deg, #006A6A 0%, #00897F 100%); --grad-tonal: linear-gradient(135deg, #9CF1F0 0%, #9CF1F0 100%);
    --brand-ink: #006A6A; --brand-primary: #006A6A; --primary: #006A6A; --saffron: #006A6A; --rose: #006A6A;
    --primary-light: #9CF1F0; --saffron-light: #9CF1F0; --rose-light: #9CF1F0; --primary-dark: #002020; --saffron-dark: #002020; --md-paper-on-blue: #002020;
    --elevation-1: 0 2px 4px rgba(0, 106, 106, 0.05); --elevation-2: 0 4px 10px rgba(0, 106, 106, 0.08), 0 2px 4px rgba(0,0,0,0.02);
    --elevation-3: 0 10px 20px rgba(0, 106, 106, 0.12), 0 4px 8px rgba(0,0,0,0.04); --elevation-4: 0 20px 40px rgba(0, 106, 106, 0.15), 0 10px 20px rgba(0,0,0,0.06);
}
[data-theme="dark"] body[data-color="teal"]:not([data-mode="customer"]):not([data-mode="employee"]):not([data-skin]) {
    --md-primary: #80D5D4; --md-on-primary: #003737; --md-primary-container: #004F4F; --md-on-primary-container: #9CF1F0;
    --primary-light: #004F4F; --saffron-light: #004F4F; --rose-light: #004F4F; --grad-tonal: linear-gradient(135deg, #004F4F 0%, #004F4F 100%);
}
body[data-color="green"]:not([data-mode="customer"]):not([data-mode="employee"]):not([data-skin]) {
    --md-primary: #1B6D3B; --md-on-primary: #FFFFFF; --md-primary-container: #A4F4B4; --md-on-primary-container: #00210B; --md-bold: #2E8B4E;
    --grad-hero: linear-gradient(135deg, #00391A 0%, #1B6D3B 52%, #2F874D 125%); --grad-cta: var(--grad-hero); --hero-gradient: var(--grad-hero); --grad-mode-owner: var(--grad-hero);
    --grad-card1: linear-gradient(135deg, #1B6D3B 0%, #2E8B4E 100%); --grad-tonal: linear-gradient(135deg, #A4F4B4 0%, #A4F4B4 100%);
    --brand-ink: #1B6D3B; --brand-primary: #1B6D3B; --primary: #1B6D3B; --saffron: #1B6D3B; --rose: #1B6D3B;
    --primary-light: #A4F4B4; --saffron-light: #A4F4B4; --rose-light: #A4F4B4; --primary-dark: #00210B; --saffron-dark: #00210B; --md-paper-on-blue: #00210B;
    --elevation-1: 0 2px 4px rgba(27, 109, 59, 0.05); --elevation-2: 0 4px 10px rgba(27, 109, 59, 0.08), 0 2px 4px rgba(0,0,0,0.02);
    --elevation-3: 0 10px 20px rgba(27, 109, 59, 0.12), 0 4px 8px rgba(0,0,0,0.04); --elevation-4: 0 20px 40px rgba(27, 109, 59, 0.15), 0 10px 20px rgba(0,0,0,0.06);
}
[data-theme="dark"] body[data-color="green"]:not([data-mode="customer"]):not([data-mode="employee"]):not([data-skin]) {
    --md-primary: #89D89A; --md-on-primary: #00391A; --md-primary-container: #005228; --md-on-primary-container: #A4F4B4;
    --primary-light: #005228; --saffron-light: #005228; --rose-light: #005228; --grad-tonal: linear-gradient(135deg, #005228 0%, #005228 100%);
}
body[data-color="olive"]:not([data-mode="customer"]):not([data-mode="employee"]):not([data-skin]) {
    --md-primary: #4C6619; --md-on-primary: #FFFFFF; --md-primary-container: #CDED9A; --md-on-primary-container: #131F00; --md-bold: #627F2A;
    --grad-hero: linear-gradient(135deg, #1F2B05 0%, #4C6619 52%, #64812C 125%); --grad-cta: var(--grad-hero); --hero-gradient: var(--grad-hero); --grad-mode-owner: var(--grad-hero);
    --grad-card1: linear-gradient(135deg, #4C6619 0%, #627F2A 100%); --grad-tonal: linear-gradient(135deg, #CDED9A 0%, #CDED9A 100%);
    --brand-ink: #4C6619; --brand-primary: #4C6619; --primary: #4C6619; --saffron: #4C6619; --rose: #4C6619;
    --primary-light: #CDED9A; --saffron-light: #CDED9A; --rose-light: #CDED9A; --primary-dark: #131F00; --saffron-dark: #131F00; --md-paper-on-blue: #131F00;
    --elevation-1: 0 2px 4px rgba(76, 102, 25, 0.05); --elevation-2: 0 4px 10px rgba(76, 102, 25, 0.08), 0 2px 4px rgba(0,0,0,0.02);
    --elevation-3: 0 10px 20px rgba(76, 102, 25, 0.12), 0 4px 8px rgba(0,0,0,0.04); --elevation-4: 0 20px 40px rgba(76, 102, 25, 0.15), 0 10px 20px rgba(0,0,0,0.06);
}
[data-theme="dark"] body[data-color="olive"]:not([data-mode="customer"]):not([data-mode="employee"]):not([data-skin]) {
    --md-primary: #B1D180; --md-on-primary: #253600; --md-primary-container: #384E00; --md-on-primary-container: #CDED9A;
    --primary-light: #384E00; --saffron-light: #384E00; --rose-light: #384E00; --grad-tonal: linear-gradient(135deg, #384E00 0%, #384E00 100%);
}
body[data-color="saffron"]:not([data-mode="customer"]):not([data-mode="employee"]):not([data-skin]) {
    --md-primary: #A33F00; --md-on-primary: #FFFFFF; --md-primary-container: #FFDBCB; --md-on-primary-container: #360F00; --md-bold: #C2510F;
    --grad-hero: linear-gradient(135deg, #6B2400 0%, #A33F00 52%, #CB5718 125%); --grad-cta: var(--grad-hero); --hero-gradient: var(--grad-hero); --grad-mode-owner: var(--grad-hero);
    --grad-card1: linear-gradient(135deg, #A33F00 0%, #C2510F 100%); --grad-tonal: linear-gradient(135deg, #FFDBCB 0%, #FFDBCB 100%);
    --brand-ink: #A33F00; --brand-primary: #A33F00; --primary: #A33F00; --saffron: #A33F00; --rose: #A33F00;
    --primary-light: #FFDBCB; --saffron-light: #FFDBCB; --rose-light: #FFDBCB; --primary-dark: #360F00; --saffron-dark: #360F00; --md-paper-on-blue: #360F00;
    --elevation-1: 0 2px 4px rgba(163, 63, 0, 0.05); --elevation-2: 0 4px 10px rgba(163, 63, 0, 0.08), 0 2px 4px rgba(0,0,0,0.02);
    --elevation-3: 0 10px 20px rgba(163, 63, 0, 0.12), 0 4px 8px rgba(0,0,0,0.04); --elevation-4: 0 20px 40px rgba(163, 63, 0, 0.15), 0 10px 20px rgba(0,0,0,0.06);
}
[data-theme="dark"] body[data-color="saffron"]:not([data-mode="customer"]):not([data-mode="employee"]):not([data-skin]) {
    --md-primary: #FFB693; --md-on-primary: #591D00; --md-primary-container: #7D2E00; --md-on-primary-container: #FFDBCB;
    --primary-light: #7D2E00; --saffron-light: #7D2E00; --rose-light: #7D2E00; --grad-tonal: linear-gradient(135deg, #7D2E00 0%, #7D2E00 100%);
}
body[data-color="coffee"]:not([data-mode="customer"]):not([data-mode="employee"]):not([data-skin]) {
    --md-primary: #6F4A30; --md-on-primary: #FFFFFF; --md-primary-container: #FFDCC4; --md-on-primary-container: #2A1708; --md-bold: #8D6346;
    --grad-hero: linear-gradient(135deg, #2E1A0C 0%, #6F4A30 52%, #A37A5A 125%); --grad-cta: var(--grad-hero); --hero-gradient: var(--grad-hero); --grad-mode-owner: var(--grad-hero);
    --grad-card1: linear-gradient(135deg, #6F4A30 0%, #8D6346 100%); --grad-tonal: linear-gradient(135deg, #FFDCC4 0%, #FFDCC4 100%);
    --brand-ink: #6F4A30; --brand-primary: #6F4A30; --primary: #6F4A30; --saffron: #6F4A30; --rose: #6F4A30;
    --primary-light: #FFDCC4; --saffron-light: #FFDCC4; --rose-light: #FFDCC4; --primary-dark: #2A1708; --saffron-dark: #2A1708; --md-paper-on-blue: #2A1708;
    --elevation-1: 0 2px 4px rgba(111, 74, 48, 0.05); --elevation-2: 0 4px 10px rgba(111, 74, 48, 0.08), 0 2px 4px rgba(0,0,0,0.02);
    --elevation-3: 0 10px 20px rgba(111, 74, 48, 0.12), 0 4px 8px rgba(0,0,0,0.04); --elevation-4: 0 20px 40px rgba(111, 74, 48, 0.15), 0 10px 20px rgba(0,0,0,0.06);
}
[data-theme="dark"] body[data-color="coffee"]:not([data-mode="customer"]):not([data-mode="employee"]):not([data-skin]) {
    --md-primary: #E7BD9C; --md-on-primary: #43280F; --md-primary-container: #5B3A22; --md-on-primary-container: #FFDCC4;
    --primary-light: #5B3A22; --saffron-light: #5B3A22; --rose-light: #5B3A22; --grad-tonal: linear-gradient(135deg, #5B3A22 0%, #5B3A22 100%);
}
body[data-color="rose"]:not([data-mode="customer"]):not([data-mode="employee"]):not([data-skin]) {
    --md-primary: #A0225A; --md-on-primary: #FFFFFF; --md-primary-container: #FFD9E2; --md-on-primary-container: #3E001D; --md-bold: #C2477A;
    --grad-hero: linear-gradient(135deg, #560A2E 0%, #A0225A 52%, #D85989 125%); --grad-cta: var(--grad-hero); --hero-gradient: var(--grad-hero); --grad-mode-owner: var(--grad-hero);
    --grad-card1: linear-gradient(135deg, #A0225A 0%, #C2477A 100%); --grad-tonal: linear-gradient(135deg, #FFD9E2 0%, #FFD9E2 100%);
    --brand-ink: #A0225A; --brand-primary: #A0225A; --primary: #A0225A; --saffron: #A0225A; --rose: #A0225A;
    --primary-light: #FFD9E2; --saffron-light: #FFD9E2; --rose-light: #FFD9E2; --primary-dark: #3E001D; --saffron-dark: #3E001D; --md-paper-on-blue: #3E001D;
    --elevation-1: 0 2px 4px rgba(160, 34, 90, 0.05); --elevation-2: 0 4px 10px rgba(160, 34, 90, 0.08), 0 2px 4px rgba(0,0,0,0.02);
    --elevation-3: 0 10px 20px rgba(160, 34, 90, 0.12), 0 4px 8px rgba(0,0,0,0.04); --elevation-4: 0 20px 40px rgba(160, 34, 90, 0.15), 0 10px 20px rgba(0,0,0,0.06);
}
[data-theme="dark"] body[data-color="rose"]:not([data-mode="customer"]):not([data-mode="employee"]):not([data-skin]) {
    --md-primary: #FFB1C8; --md-on-primary: #5E1133; --md-primary-container: #7D294A; --md-on-primary-container: #FFD9E2;
    --primary-light: #7D294A; --saffron-light: #7D294A; --rose-light: #7D294A; --grad-tonal: linear-gradient(135deg, #7D294A 0%, #7D294A 100%);
}
body[data-color="indigo"]:not([data-mode="customer"]):not([data-mode="employee"]):not([data-skin]) {
    --md-primary: #3D4DB5; --md-on-primary: #FFFFFF; --md-primary-container: #DFE0FF; --md-on-primary-container: #000C62; --md-bold: #5B6BD1;
    --grad-hero: linear-gradient(135deg, #141C66 0%, #3D4DB5 52%, #6776E0 125%); --grad-cta: var(--grad-hero); --hero-gradient: var(--grad-hero); --grad-mode-owner: var(--grad-hero);
    --grad-card1: linear-gradient(135deg, #3D4DB5 0%, #5B6BD1 100%); --grad-tonal: linear-gradient(135deg, #DFE0FF 0%, #DFE0FF 100%);
    --brand-ink: #3D4DB5; --brand-primary: #3D4DB5; --primary: #3D4DB5; --saffron: #3D4DB5; --rose: #3D4DB5;
    --primary-light: #DFE0FF; --saffron-light: #DFE0FF; --rose-light: #DFE0FF; --primary-dark: #000C62; --saffron-dark: #000C62; --md-paper-on-blue: #000C62;
    --elevation-1: 0 2px 4px rgba(61, 77, 181, 0.05); --elevation-2: 0 4px 10px rgba(61, 77, 181, 0.08), 0 2px 4px rgba(0,0,0,0.02);
    --elevation-3: 0 10px 20px rgba(61, 77, 181, 0.12), 0 4px 8px rgba(0,0,0,0.04); --elevation-4: 0 20px 40px rgba(61, 77, 181, 0.15), 0 10px 20px rgba(0,0,0,0.06);
}
[data-theme="dark"] body[data-color="indigo"]:not([data-mode="customer"]):not([data-mode="employee"]):not([data-skin]) {
    --md-primary: #BCC2FF; --md-on-primary: #18237F; --md-primary-container: #2F3A99; --md-on-primary-container: #DFE0FF;
    --primary-light: #2F3A99; --saffron-light: #2F3A99; --rose-light: #2F3A99; --grad-tonal: linear-gradient(135deg, #2F3A99 0%, #2F3A99 100%);
}
body[data-color="graphite"]:not([data-mode="customer"]):not([data-mode="employee"]):not([data-skin]) {
    --md-primary: #3F4A5A; --md-on-primary: #FFFFFF; --md-primary-container: #D6E3F7; --md-on-primary-container: #101C2B; --md-bold: #56657A;
    --grad-hero: linear-gradient(135deg, #0F172A 0%, #334155 52%, #64748B 125%); --grad-cta: var(--grad-hero); --hero-gradient: var(--grad-hero); --grad-mode-owner: var(--grad-hero);
    --grad-card1: linear-gradient(135deg, #3F4A5A 0%, #56657A 100%); --grad-tonal: linear-gradient(135deg, #D6E3F7 0%, #D6E3F7 100%);
    --brand-ink: #334155; --brand-primary: #3F4A5A; --primary: #3F4A5A; --saffron: #3F4A5A; --rose: #3F4A5A;
    --primary-light: #D6E3F7; --saffron-light: #D6E3F7; --rose-light: #D6E3F7; --primary-dark: #101C2B; --saffron-dark: #101C2B; --md-paper-on-blue: #101C2B;
    --elevation-1: 0 2px 4px rgba(63, 74, 90, 0.05); --elevation-2: 0 4px 10px rgba(63, 74, 90, 0.08), 0 2px 4px rgba(0,0,0,0.02);
    --elevation-3: 0 10px 20px rgba(63, 74, 90, 0.12), 0 4px 8px rgba(0,0,0,0.04); --elevation-4: 0 20px 40px rgba(63, 74, 90, 0.15), 0 10px 20px rgba(0,0,0,0.06);
}
[data-theme="dark"] body[data-color="graphite"]:not([data-mode="customer"]):not([data-mode="employee"]):not([data-skin]) {
    --md-primary: #BCC7DB; --md-on-primary: #263141; --md-primary-container: #3C4758; --md-on-primary-container: #D6E3F7;
    --primary-light: #3C4758; --saffron-light: #3C4758; --rose-light: #3C4758; --grad-tonal: linear-gradient(135deg, #3C4758 0%, #3C4758 100%);
}
body[data-color="charcoal"]:not([data-mode="customer"]):not([data-mode="employee"]):not([data-skin]) {
    --md-primary: #2B2F36; --md-on-primary: #FFFFFF; --md-primary-container: #DDE3EA; --md-on-primary-container: #12161C; --md-bold: #454B54;
    --grad-hero: linear-gradient(135deg, #000000 0%, #22262C 52%, #4B5058 125%); --grad-cta: var(--grad-hero); --hero-gradient: var(--grad-hero); --grad-mode-owner: var(--grad-hero);
    --grad-card1: linear-gradient(135deg, #2B2F36 0%, #454B54 100%); --grad-tonal: linear-gradient(135deg, #DDE3EA 0%, #DDE3EA 100%);
    --brand-ink: #22262C; --brand-primary: #2B2F36; --primary: #2B2F36; --saffron: #2B2F36; --rose: #2B2F36;
    --primary-light: #DDE3EA; --saffron-light: #DDE3EA; --rose-light: #DDE3EA; --primary-dark: #12161C; --saffron-dark: #12161C; --md-paper-on-blue: #12161C;
    --elevation-1: 0 2px 4px rgba(43, 47, 54, 0.05); --elevation-2: 0 4px 10px rgba(43, 47, 54, 0.08), 0 2px 4px rgba(0,0,0,0.02);
    --elevation-3: 0 10px 20px rgba(43, 47, 54, 0.12), 0 4px 8px rgba(0,0,0,0.04); --elevation-4: 0 20px 40px rgba(43, 47, 54, 0.15), 0 10px 20px rgba(0,0,0,0.06);
}
[data-theme="dark"] body[data-color="charcoal"]:not([data-mode="customer"]):not([data-mode="employee"]):not([data-skin]) {
    --md-primary: #C3C8D0; --md-on-primary: #2B3038; --md-primary-container: #41474F; --md-on-primary-container: #DDE3EA;
    --primary-light: #41474F; --saffron-light: #41474F; --rose-light: #41474F; --grad-tonal: linear-gradient(135deg, #41474F 0%, #41474F 100%);
}

/* ══════════════════════════════════════════════════════════════════════════
   CUSTOMER SKIN (2026-10-06; Dusk since 2026-11-03,
   design_concepts/customer_app_preview.html K1: plum to coral, a two-colour
   gradient so it is never one of the twelve owner app colours)
   Customer Mode's Home has had its own colour since 2026-09-23, but only its hero, bar
   and nav pill: every page behind it (bills, bookings, orders, a business)
   and the Profile tab stayed the owner's blue, so the colour that says "this
   is your customer side" ended at the first tap.

   This carries it the whole way. It redefines the PRIMARY family and the
   brand gradients on <body>, so every rule that already asks for
   `--md-primary` or `--grad-hero` paints in the mode's colour (Dusk, plum to coral) with
   no rule of its own.

   Where it applies:
     body[data-mode="customer"]  the dashboard in Customer Mode (index.php)
     body[data-skin="customer"]  every customerview page (commons/header.php)
   Owner and Employee screens are untouched.

   On <body>, not :root, for two reasons: the mode is only known there, and a
   value set on <body> beats the :root and [data-theme="dark"] blocks above by
   inheritance, whatever their order. The legacy aliases are repeated because
   `--primary: var(--brand-primary)` was resolved at :root and does not follow.

   The colour was a red until 2026-10-06 and collided with the error role.
   Aubergine does not: money owed stays amber and coral, failures keep
   `--md-error`, and each still carries its icon and word (APP_STANDARDS:
   every state = colour + icon + word).
   ══════════════════════════════════════════════════════════════════════════ */
:root {
    /* The owner's blue under a name of its own, for the one place that must
       stay blue inside the customer skin: the Owner row of the mode dialog. */
    --grad-mode-owner: linear-gradient(135deg, #003585 0%, #0B57D0 52%, #3774EB 125%);
}
body[data-mode="customer"],
body[data-skin="customer"] {
    --md-primary:               #A3195B;
    --md-on-primary:            #FFFFFF;
    --md-primary-container:     #FFD9E4;
    --md-on-primary-container:  #3E0021;
    --md-bold:                  #C23C74;

    --grad-hero:     var(--grad-mode-customer);
    --grad-cta:      var(--grad-mode-customer);
    --hero-gradient: var(--grad-mode-customer);
    --grad-night:    linear-gradient(160deg, #2A0620 0%, #4B0D3A 55%, #A3195B 130%);
    --grad-card1:    linear-gradient(135deg, #A3195B 0%, #C23C74 100%);
    --grad-tonal:    linear-gradient(135deg, #FFD9E4 0%, #F8E1E8 100%);

    --brand-primary: #A3195B;
    --primary:       #A3195B;
    --saffron:       #A3195B;
    --rose:          #A3195B;
    --primary-light: #FFD9E4;
    --saffron-light: #FFD9E4;
    --rose-light:    #FFD9E4;
    --primary-dark:  #3E0021;
    --saffron-dark:  #3E0021;

    --elevation-1: 0 2px 4px rgba(163, 25, 91, 0.05);
    --elevation-2: 0 4px 10px rgba(163, 25, 91, 0.08), 0 2px 4px rgba(0,0,0,0.02);
    --elevation-3: 0 10px 20px rgba(163, 25, 91, 0.12), 0 4px 8px rgba(0,0,0,0.04);
    --elevation-4: 0 20px 40px rgba(163, 25, 91, 0.15), 0 10px 20px rgba(0,0,0,0.06);
}
[data-theme="dark"] body[data-mode="customer"],
[data-theme="dark"] body[data-skin="customer"],
body[data-theme="dark"][data-mode="customer"],
body[data-theme="dark"][data-skin="customer"] {
    --md-primary:               #FFB1C9;
    --md-on-primary:            #5F1136;
    --md-primary-container:     #7E1F48;
    --md-on-primary-container:  #FFD9E4;
    --md-bold:                  #FF8CB3;
    --primary-light: #7E1F48;
    --saffron-light: #7E1F48;
    --rose-light:    #7E1F48;
    --grad-tonal:    linear-gradient(135deg, #7E1F48 0%, #573843 100%);
}

/* ══════════════════════════════════════════════════════════════════════════
   MYRA SKIN (2026-10-18)
   Myra's chat is a WhatsApp-shaped contact in her own emerald, picked by the
   owner from design_concepts/myra_chat_preview.html ("use Emerald", and "do
   not consider current colors"). It applies to her pages only, through
   body[data-skin="myra"] (commons/header.php, $body_skin = 'myra').

   It redefines the primary family (dialogs, filled buttons, switches inside
   her pages turn emerald with no rule of their own), points her old crimson
   accents (--myra, --grad-crimson) at emerald so every card myra.css draws
   follows, and adds the chat's own roles (--mc-*): the wall, the two bubble
   colours, the ticks, the yellow notice. Myra's tile on Home and her rose
   elsewhere are untouched.
   ══════════════════════════════════════════════════════════════════════════ */
body[data-skin="myra"] {
    --md-primary:               #00876E;
    --md-on-primary:            #FFFFFF;
    --md-primary-container:     #B4F1DA;
    --md-on-primary-container:  #00211A;
    --md-bold:                  #00876E;
    --myra:                     #00876E;
    --grad-crimson: linear-gradient(135deg, #006D59 0%, #00876E 52%, #13B58A 125%);
    --grad-hero:    linear-gradient(135deg, #006D59 0%, #00876E 52%, #13B58A 125%);

    /* #00876E until 2026-11-05: links and card titles in her white bubble read
       4.36:1 (Play pre-launch report); one step deeper clears 4.5 on both bubbles. */
    --mc-accent:    #007A63;   /* buttons, links, the round mic */
    --mc-accent-hi: #13B58A;   /* her avatar ring, the online dot */
    --mc-online:    #25B86B;
    --mc-head:      #FFFFFF;   /* the white top bar */
    --mc-head-ink:  #0F1B1F;
    --mc-head-sub:  #5E6E75;
    --mc-wall:      #EEEAE3;   /* the chat's paper */
    --mc-doodle:    rgba(80, 66, 44, .06);
    --mc-in:        #FFFFFF;   /* her bubble */
    --mc-out:       #D8F8E7;   /* the owner's bubble */
    --mc-ink:       #111B21;
    --mc-ink2:      #5B6B74;   /* was WhatsApp's #667781: 4.09:1 on the owner's green bubble */
    --mc-out-ink2:  var(--mc-ink2);   /* the time and ticks inside the owner's bubble */
    --mc-line:      rgba(17, 27, 33, .10);
    --mc-chip:      #FFFFFF;   /* composer, chips, attached buttons */
    --mc-sys:       #FFF4C9;   /* the yellow notice */
    --mc-sys-ink:   #54471F;
    --mc-tick:      #2FA8E6;   /* read ticks */
    --mc-soft:      #E7F6F0;   /* an accent wash */
    --mc-inset:     #F4F2EE;   /* a card inside a bubble */
    --mc-team:      #C2410C;   /* a person from the team, by name */
    --mc-shadow:    0 1px .5px rgba(0, 0, 0, .13);
    --mc-lift:      0 6px 24px rgba(0, 0, 0, .18);
    /* The initials' discs, each a little deeper than it was (#E8336D #A15CF0
       #5D7BF0 #F0921A #13A3B8 #2BB673 #EB5A3C #6B7A86 until 2026-11-05) so the
       white letters clear 4.5:1 — the orange and the cyan read 2.4 and 3.0. */
    --mc-att-a: #E31A5A; --mc-att-b: #974BEE; --mc-att-c: #4769EE; --mc-att-d: #AA640B;
    --mc-att-e: #0F8090; --mc-att-f: #1F8554; --mc-att-g: #DA3816; --mc-att-h: #687783;
}
[data-theme="dark"] body[data-skin="myra"],
body[data-theme="dark"][data-skin="myra"] {
    --md-primary:               #5FDBB4;
    --md-on-primary:            #00382C;
    --md-primary-container:     #00513F;
    --md-on-primary-container:  #B4F1DA;
    --md-bold:                  #5FDBB4;
    --myra:                     #5FDBB4;

    --mc-accent:    #21C796;
    --mc-accent-hi: #21C796;
    --mc-head:      #1F2C33;
    --mc-head-ink:  #E9EDEF;
    --mc-head-sub:  #8696A0;
    --mc-wall:      #0B141A;
    --mc-doodle:    rgba(255, 255, 255, .04);
    --mc-in:        #1F2C33;
    --mc-out:       #0B5847;
    --mc-ink:       #E9EDEF;
    --mc-ink2:      #8696A0;
    --mc-out-ink2:  #AAC5BF;   /* on the green #0B5847 bubble #8696A0 was 2.75:1 */
    --mc-line:      rgba(233, 237, 239, .12);
    --mc-chip:      #1F2C33;
    --mc-sys:       #182229;
    --mc-sys-ink:   #E2C46D;
    --mc-tick:      #53BDEB;
    --mc-soft:      #13332B;
    --mc-inset:     #18252C;
    --mc-team:      #FB923C;
    --mc-shadow:    none;
    --mc-lift:      0 6px 24px rgba(0, 0, 0, .5);
}

/* ══════════════════════════════════════════════════════════════════════════
   MYRA IN THE APP'S COLOUR (2026-11-13, design_concepts/myra_ai_v13_preview.html,
   the owner: "make sure we use theme color only"). Her pages and Help and
   support now carry body[data-myra] (commons/header.php, $body_skin = 'myra')
   instead of the emerald skin above, so the owner's own colour (data-color)
   applies there too. Her chat's roles (--mc-*) and her old accents point at
   the theme. The emerald block stays for the computer's Myra (web-admin).
   One colour for every round mark: the theme's primary, its deep container
   in dark so white letters on it still read.
   ══════════════════════════════════════════════════════════════════════════ */
body[data-myra] {
    --myra:         var(--md-primary);
    --grad-crimson: var(--grad-hero);
    --mc-accent:    var(--md-primary);
    --mc-accent-hi: var(--md-primary);
    --mc-online:    var(--md-pos, #25B86B);
    --mc-head:      var(--md-surface-container-lowest);
    --mc-head-ink:  var(--md-on-surface);
    --mc-head-sub:  var(--md-on-surface-variant);
    --mc-wall:      var(--md-surface);
    --mc-doodle:    transparent;
    --mc-in:        var(--md-surface-container-lowest);
    --mc-out:       var(--md-primary-container);
    --mc-ink:       var(--md-on-surface);
    --mc-ink2:      var(--md-on-surface-variant);
    --mc-out-ink2:  var(--md-on-primary-container);
    --mc-line:      var(--md-outline-variant);
    --mc-chip:      var(--md-surface-container-lowest);
    --mc-sys:       var(--md-surface-container-high);
    --mc-sys-ink:   var(--md-on-surface-variant);
    --mc-tick:      var(--md-primary);
    --mc-soft:      color-mix(in srgb, var(--md-primary) 10%, var(--md-surface-container-lowest));
    --mc-inset:     var(--md-surface-container-low);
    --mc-team:      #C2410C;
    --mc-shadow:    none;
    --mc-lift:      0 8px 28px rgba(0, 0, 0, .18);
    --mc-att-a: var(--md-primary); --mc-att-b: var(--md-primary); --mc-att-c: var(--md-primary); --mc-att-d: var(--md-primary);
    --mc-att-e: var(--md-primary); --mc-att-f: var(--md-primary); --mc-att-g: var(--md-primary); --mc-att-h: var(--md-primary);
}
[data-theme="dark"] body[data-myra],
body[data-theme="dark"][data-myra] {
    --mc-team:      #FB923C;
    --mc-lift:      0 8px 28px rgba(0, 0, 0, .5);
    --mc-att-a: var(--md-primary-container); --mc-att-b: var(--md-primary-container); --mc-att-c: var(--md-primary-container); --mc-att-d: var(--md-primary-container);
    --mc-att-e: var(--md-primary-container); --mc-att-f: var(--md-primary-container); --mc-att-g: var(--md-primary-container); --mc-att-h: var(--md-primary-container);
}
