/* Mirror — customer dark theme
   ==========================================================================
   ❄️ GENERATED from the FROZEN shared-shell prototype. Do not hand-edit.
      source : docs/mirror-web-shared-shell-2026-09-01/prototype/dark.src.css
      sha256 : fa348c07a17d27a29ff696bced3ea2aedd62bb1baf491a476cc79757b0e1033f  (pinned in FROZEN.sha256)
      built  : docs/mirror-web-shared-shell-2026-09-01/prototype/ship.py
      buster : ?v=mwu-sharedshell-20260902a

   ⚖️ OD-SS-9. The dark THEME. ⚠️ Unlike the sheet above, this one DELIBERATELY
   reaches the frozen surfaces — by re-pointing the `--mirror-*` tokens their
   own CSS already reads. That is the ruling, and it is why the two sheets are
   separate files: merging them would destroy N1's guarantee.
   ⛔ Load AFTER the surface sheets, or the light defaults win.
   ========================================================================== */

/* ═══════════════════════════════════════════════════════════════════════════
   THE DARK THEME LAYER  —  ⚖️ OWNER RULING OD-SS-9 (2026-09-01)

   The customer website has Dark Mode. It is delivered as a THEME, not a
   redesign: every value below either re-points a Mirror token the frozen CSS
   already reads, or overrides a hard-coded literal the frozen CSS could not
   express as a token. ⛔ No frozen rule is edited and no frozen file changes.

   PROVENANCE — this is Home's existing dark language, not a new one:
     ground / section   #1a1a2e   dark-mode.css:24, :70
     alt / header       #16213e   dark-mode.css:30, :75
     deepest / footer   #0f1929   dark-mode.css:78, :145
     card / surface     #1e2a3a   dark-mode.css:52, :60, :95
     border             #2a3a4a   dark-mode.css:53, :61, :96
     text               #e8e8e8   dark-mode.css:25, :65
     muted text         #a0a0b0   dark-mode.css:87, :103
     accent (champagne) #d4a574   dark-mode.css:99, :134, :152

   THE ONE DESIGN RULE, and it is Home's too. dark-mode.css already splits
   brand by ROLE: brand stays a FILL with white on it (.mirror-chip:hover,
   .mirror-step-circle) while brand as a FOREGROUND becomes the champagne
   accent (.mirror-btn-outline, .mirror-trust-item .value, footer link hover).
   The three surfaces use --mirror-brand 39 times as a foreground and 16 as a
   fill, so the token becomes champagne — fixing all 39 at once — and the 9
   fills that paint WHITE content are restored to burgundy in §3.
   Measured: white on champagne 2.23:1; white on burgundy 10.72:1.

   ⚠️ WEB ADAPTATION, registered. The Flutter customer app has NO dark theme —
   no ThemeMode, darkTheme or ThemeData.dark anywhere in its lib/ — and
   mirror-tokens.css declares no dark block. Dark Mode has no app counterpart;
   it is a web decision, ruled by the owner on 2026-09-01.

   Every ratio quoted here is measured, which is the standard the Appointments
   prototype set for its own status tokens. The full table is in
   ../03-decision-record.md §OD-SS-9.
   ═══════════════════════════════════════════════════════════════════════ */


/* ── 1 · The root ─────────────────────────────────────────────────────────
   `color-scheme` makes the UA paint form controls, scrollbars and the canvas
   dark, so a native control never lands as a white slab. BOTH roots are keyed,
   because master.blade.php's toggle sets `data-theme` AND `.dark-mode`. */
html[data-theme="dark"], html.dark-mode { color-scheme: dark; }


/* ── 2 · The token re-map ─────────────────────────────────────────────────
   ⚠️ This block deliberately REACHES THE FROZEN SURFACES — that is the ruling,
   and it is exactly why the dark theme is its own layer rather than part of
   the chrome sheet, whose whole guarantee (SS-01) is that it cannot reach a
   surface. Nothing here is a frozen rule; every line is a custom property the
   frozen CSS already reads. */
html[data-theme="dark"], html.dark-mode {
  /* grounds — the existing Mirror dark ladder.
     Separation ground→surface 1.18, surface→field 1.25; the light theme's own
     equivalent (#F5F5F5→#FFFFFF) is 1.09, so the layering reads at least as
     clearly in dark as it does in light.
     ⚠️ --mirror-ground was #0f1929 in the first build — the deepest rung — and
     driving it showed why that was wrong: #0f1929 is also Home's FOOTER, so on
     Appointments (whose body IS --mirror-ground) the footer dissolved into the
     page and the shell lost its bottom edge. #1a1a2e is Home's own body ground
     (dark-mode.css:24), which keeps the footer distinct on all three pages and
     is the more faithful mapping in the first place. Found by measuring, not
     by looking. */
  --mirror-ground:              #1a1a2e;
  --mirror-surface:             #1e2a3a;
  --mirror-field-fill:          #2a3a4a;
  --mirror-csearch-field-fill:  #2a3a4a;

  /* text — every value measured against all three grounds, AA or better */
  --mirror-ink:                 #e8e8e8;   /* 13.92 / 11.84 / 9.51 */
  --mirror-text:                #e8e8e8;
  --mirror-body:                #d5d9e0;   /* 12.05 / 10.25 / 8.23 */
  --mirror-chrome-dark:         #d5d9e0;
  --mirror-hint-strong:         #a8b0be;   /*  7.81 /  6.65 / 5.34 */
  --mirror-hint:                #9aa3b4;   /*  6.72 /  5.71 / 4.59 */
  --mirror-gray1:               #9aa3b4;

  /* lines — the dark values sit at the SAME relationship to their ground as
     the light ones do (light divider #E5E5E5 on #FFFFFF = 1.26; dark #33415a
     on #1e2a3a = 1.41), so a divider stays a divider and does not become a
     border. */
  --mirror-line-soft:           #33415a;
  --mirror-gray2:               #33415a;
  --mirror-line:                #46586c;
  --mirror-gray:                #46586c;
  --mirror-line-strong:         #5a6d84;
  --mirror-hairline:            #243244;
  --mirror-disabled:            #3d4a5e;

  /* brand — the FOREGROUND role. --mirror-brand-dark and --mirror-text-on-brand
     are deliberately NOT changed: they belong to the burgundy fills restored
     in §3 and to the status pills. */
  --mirror-brand:               #d4a574;   /* 7.66 / 6.52 / 5.23 */
  --mirror-brand-rgb:           212, 165, 116;
  --mirror-brand-fill:          #711D43;   /* dark-only: the identity fill */

  /* semantic colours whose token is read as a FOREGROUND only */
  --mirror-error:               #FF8A80;   /* 7.47 / 6.36 / 5.10 */
  --mirror-error-bg:            #3A1D22;
  --mirror-error-fg:            #FFB4AB;   /* 8.97 on the banner above */
  --mirror-csearch-trash:       #FF8A80;

  /* shadows — a shadow computed for a white page is invisible on a dark one.
     Same geometry, same blur, same spread; only the alpha moves. */
  --mirror-card-shadow:         0 1px 2px rgba(0,0,0,.50), 0 2px 6px rgba(0,0,0,.40);
  --mirror-overlay-shadow:      0 24px 70px rgba(0,0,0,.65);
  --mirror-nav-shadow:          0 -10px 31px rgba(0,0,0,.45);
  --mirror-csearch-card-shadow: 0 10px 31px 3px rgba(0,0,0,.45);
  --mirror-csearch-menu-shadow: 0 4px 14px rgba(0,0,0,.60);
  --mirror-shadow-md:           0 10px 28px rgba(0,0,0,.45);
}

/* ⛔ NOT re-pointed, and each for a reason the audit recorded rather than an
   omission:
     --mirror-text-on-brand #FFFFFF  still sits on burgundy (10.72:1) and on
                                     every status pill (5.02–6.19:1)
     --mirror-status-pending
     --mirror-status-processing
     --mirror-status-completed       FILL-ONLY tokens. White on them measures
                                     5.02 / 5.75 / 5.13 in BOTH themes, so
                                     lightening them would break the pills to
                                     fix nothing
     --mirror-brand-dark #55162F     the hover partner of the restored fills
     gender chips, --mirror-male,
     --mirror-female, --mirror-gold,
     --mirror-honey                  bright fills that carry their own ground */


/* ── 3 · Burgundy restored where the fill paints WHITE content ────────────
   The rule is mechanical rather than a matter of taste: a fill is restored if
   and only if the frozen CSS paints --mirror-text-on-brand (or a literal #fff)
   ON it. Nine selectors qualify. Everything else follows the accent, which is
   what keeps the frozen design's monochrome pairings intact — a champagne
   label still gets a champagne indicator, not a burgundy one. */
html[data-theme="dark"] .mirror-profile-header,                  html.dark-mode .mirror-profile-header,
html[data-theme="dark"] .mirror-profile-photo-badge,                html.dark-mode .mirror-profile-photo-badge,
html[data-theme="dark"] .mirror-profile-button,                         html.dark-mode .mirror-profile-button,
html[data-theme="dark"] .mirror-appt-btn,                         html.dark-mode .mirror-appt-btn,
html[data-theme="dark"] .mirror-csearch-filter-badge,       html.dark-mode .mirror-csearch-filter-badge,
html[data-theme="dark"] .mirror-csearch-pager [aria-current],  html.dark-mode .mirror-csearch-pager [aria-current],
html[data-theme="dark"] .mirror-csearch-retry,                 html.dark-mode .mirror-csearch-retry,
html[data-theme="dark"] .mirror-csearch-apply,                       html.dark-mode .mirror-csearch-apply {
  background: var(--mirror-brand-fill);
}

/* The step dots keep the accent, so a dot and its label stay ONE hue exactly
   as the frozen design has them — and the dot's hard-coded #fff numeral flips
   to the ground colour instead, measuring 7.66:1 on champagne. White would
   have been 2.23:1, so the pairing survives at no legibility cost. */
html[data-theme="dark"] .mirror-appt-step[data-phase="past"]::before,
html.dark-mode          .mirror-appt-step[data-phase="past"]::before,
html[data-theme="dark"] .mirror-appt-step[data-phase="current"]::before,
html.dark-mode          .mirror-appt-step[data-phase="current"]::before {
  color: var(--mirror-ground);
}


/* ── 4 · The dual-role status tokens ──────────────────────────────────────
   --mirror-status-cancelled and --mirror-status-neutral are read BOTH as pill
   fills (white on them: 5.62 / 6.19 — fine in either theme) AND as foreground
   text (2.58 / 2.34 on the dark surface — not fine). The token cannot be
   lightened without breaking the pills, so ONLY the foreground uses move. */
html[data-theme="dark"] .mirror-appt-error svg,                   html.dark-mode .mirror-appt-error svg,
html[data-theme="dark"] .mirror-appt-step[data-phase="stopped"],  html.dark-mode .mirror-appt-step[data-phase="stopped"] {
  color: #FF7B72;                                        /* 6.76 / 5.75 / 4.62 */
}
html[data-theme="dark"] .mirror-appt-btn--danger, html.dark-mode .mirror-appt-btn--danger {
  color: #FF7B72;
  box-shadow: inset 0 0 0 2px #FF7B72;
}
html[data-theme="dark"] .mirror-appt-btn--danger:hover, html.dark-mode .mirror-appt-btn--danger:hover {
  background: rgba(255,123,114,.12);
}
html[data-theme="dark"] .mirror-appt-step[data-phase="halted"], html.dark-mode .mirror-appt-step[data-phase="halted"] {
  color: #B9BFCC;                                        /* 9.25 / 7.87 / 6.32 */
}


/* ── 5 · The hard-coded literals the frozen CSS could not tokenise ────────
   ⛔ Everything NOT listed here was audited and is correct in BOTH themes:
   the #fff avatar ring and the #fff step numerals that sit on brand, the white
   pill text on a status fill, the white shimmer sweep across the wordmark
   loader, and the gender chips, which carry their own ground. */

/* loading skeleton — a light-grey shimmer is a white strobe on a dark page */
html[data-theme="dark"] .mirror-appt-shimmer, html.dark-mode .mirror-appt-shimmer {
  background: linear-gradient(90deg, #243244 25%, #2e3d52 37%, #243244 63%);
}

/* placeholder and unset-value text (was #9E9E9E) */
html[data-theme="dark"] .mirror-csearch-field--keyword input::placeholder,
html.dark-mode          .mirror-csearch-field--keyword input::placeholder,
html[data-theme="dark"] .f-select[data-set="no"] .v,
html.dark-mode          .f-select[data-set="no"] .v { color: #9aa3b4; }

/* the filter glyph was a near-black ink literal (#141B34) */
html[data-theme="dark"] .mirror-csearch-filter-toggle, html.dark-mode .mirror-csearch-filter-toggle {
  color: var(--mirror-ink);
}

/* the search field's inset hairline + top highlight, inverted */
html[data-theme="dark"] .mirror-csearch-field--keyword input, html.dark-mode .mirror-csearch-field--keyword input {
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.08), inset 0 1px 0 rgba(255,255,255,.04);
}

/* image placeholder — a 16% black block reads as a light patch on dark */
html[data-theme="dark"] .csearch-row-media, html.dark-mode .csearch-row-media {
  background: rgba(255,255,255,.06);
}

/* the desktop pane elevation — an 8% warm-black shadow does not exist on a
   dark ground, so the panes lose their edge entirely without this */
html[data-theme="dark"] #view-hub,        html.dark-mode #view-hub,
html[data-theme="dark"] .a-master,        html.dark-mode .a-master,
html[data-theme="dark"] .a-detail-pane,   html.dark-mode .a-detail-pane {
  box-shadow: 0 1px 0 var(--mirror-line-soft), 0 10px 40px rgba(0,0,0,.55);
}
html[data-theme="dark"] .mirror-appt-card:hover, html.dark-mode .mirror-appt-card:hover {
  box-shadow: 0 2px 6px rgba(0,0,0,.45), 0 8px 20px rgba(0,0,0,.35);
}

/* scrims — a 28–45% black veil is too thin to separate an overlay from a page
   that is already dark */
html[data-theme="dark"] .mirror-profile-scrim, html.dark-mode .mirror-profile-scrim { background: rgba(0,0,0,.62); }
html[data-theme="dark"] .mirror-appt-scrim, html.dark-mode .mirror-appt-scrim { background: rgba(0,0,0,.55); }
html[data-theme="dark"] .mirror-csearch-scrim, html.dark-mode .mirror-csearch-scrim { background: rgba(0,0,0,.62); }

/* the toast keeps the app's own Colors.black87 — white on it is ~15:1 — but on
   a dark page it needs an edge, or it reads as a hole rather than a surface */
html[data-theme="dark"] .mirror-toast, html.dark-mode .mirror-toast,
html[data-theme="dark"] .mirror-toast, html.dark-mode .mirror-toast {
  border: 1px solid var(--mirror-line-soft);
}


/* ── 6 · The shared chrome in dark ────────────────────────────────────────
   ⛔ NOT DESIGNED HERE. Home's own dark rules were already extracted verbatim
   (SS-01) and re-scoped onto the chrome wrapper (SS-02): the header takes
   #16213e from dark-mode.css:29-32 — whose `!important` beats custom.css:6720's
   #1c1c24 — the footer #0f1929 from dark-mode.css:145, and the nav links, the
   two toggles and the outline button from the same file. The mobile action row
   brings its own dark block from header.blade.php.

   The customer bottom bar needs nothing at all: it is fully token-driven, so
   §2 themes it — ground, hairline, shadow and the champagne accent, including
   the masked icons, which paint `background-color: currentColor`.

   One line is added, because Home has no counterpart for it: the divider under
   the header resolves through `--dark-divider-color`, a LIGHT-theme site
   variable, so it is re-pointed at the dark border. */
html[data-theme="dark"] .mirror-ss-chrome, html.dark-mode .mirror-ss-chrome {
  border-color: #2a3a4a;
}


/* ── Production only · the page ground ────────────────────────────────────
   ⚠️ Not in the frozen sheet because it could not be: the prototype's ground
   came from each surface's own `body{}` rule, and production's comes from
   portal.css:119-126 — a gradient over hard-coded light stops that rendered
   #f4f6fa in dark. Measured on the runtime.
   The three grounds below are the frozen prototype's own, per surface, matched
   through the `:has()` scoping production already uses. */
html[data-theme="dark"] body:has(.mirror-profile),
html.dark-mode          body:has(.mirror-profile),
html[data-theme="dark"] body:has(#customer-search),
html.dark-mode          body:has(#customer-search) {
  background: var(--mirror-surface);
}
html[data-theme="dark"] body:has(.mirror-appt),
html.dark-mode          body:has(.mirror-appt) {
  background: var(--mirror-ground);
}
