/* ═══════════════════════════════════════════════════════
   MECKLY-UI.CSS — Shared design system for all .shop pages
   Mechanic-first: dark, high contrast, grease-finger safe
   Version: 1.0 — extracted from index.html

   Usage in every .shop page:
     <link rel="stylesheet" href="/assets/fonts/fonts.css">
     <link rel="stylesheet" href="/assets/meckly-ui.css">
     <script src="/assets/nav.js"></script>

   Then add page-specific <style> below.
═══════════════════════════════════════════════════════ */

/* ── RESET ── */
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
html{-webkit-text-size-adjust:100%;overflow-x:hidden}
body{
  font-family:'Inter','Segoe UI',system-ui,sans-serif;
  background:var(--bg0);
  min-height:100dvh;
  color:var(--txt);
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
  visibility:hidden; /* revealed by security module */
}
body.ready{visibility:visible}
a{color:inherit;text-decoration:none}
button,input,select,textarea{font-family:inherit}
img{max-width:100%;height:auto;display:block}
/* MECKLY_HIDDEN_MEANS_HIDDEN_V1 — 4 Sep 2026. `hidden` is only an
   attribute, and the browser implements it as `display:none` at the very
   bottom of the cascade. Any class that sets `display` — and nearly
   every button, pill and bar in this app does — silently beats it, so an
   element marked hidden goes on drawing itself: an empty pill sitting in
   a row, present and clickable and meaning nothing. That has now
   happened twice (the blank red button beside Save on the quote). Made
   true here once, for every page, instead of one page at a time. */
[hidden]{display:none!important}
::-webkit-scrollbar{width:3px;height:3px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{background:var(--bd3);border-radius:2px}

/* ── ANIMATIONS ── */
@keyframes mu-spin{to{transform:rotate(360deg)}}
@keyframes mu-fadeIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
@keyframes mu-pulse{0%,100%{opacity:1}50%{opacity:.5}}
@keyframes mu-slideUp{from{opacity:0;transform:translateY(16px)}to{opacity:1;transform:none}}

/* ── DESIGN TOKENS ── */
:root{
  /* MECKLY_NATIVE_LOOKUP_DARK_V1 — 25 Aug 2026. Native <select> dropdown
     popups (and any other browser-native control popup — <input
     type="date">, <input type="color">, scrollbars) are NOT CSS-styleable.
     The browser paints them itself, using whichever colour scheme it
     thinks the page wants. Nothing here ever told it — so on the dark
     theme (the default) the closed <select> box correctly showed light
     text on a dark background (that part routes through --txt/--bg like
     everything else), but the OPEN dropdown list ignored all of that and
     rendered the browser's own default LIGHT popup — light text landing
     on a white background it was never designed to sit on. That's the
     washed-out/illegible state/make pickers she flagged.
     Fix: tell the browser which scheme to use for its own native UI. */
  color-scheme: dark;

  /* Brand */
  --brand:#1a6fdb;
  --brand-d:#0d47a1;
  /* MECKLY_CONTRAST_AUDIT_V1 — --brand itself fails WCAG AA as TEXT on a
     dark card (3.78:1). Fine as a button fill (white text on it passes
     easily) — this variant is specifically for text/link colour. Real
     computed value: lightened toward white until it passes (4.64:1). */
  --brand-text:#3580DF;
  --g-brand:linear-gradient(135deg,#1a6fdb,#0d47a1);
  /* MECKLY_LIGHT_THEME_GWARN_V1: quote.html's VIN-gate button referenced
     var(--g-warn) with no fallback and no definition anywhere — the
     browser silently dropped the background entirely (guaranteed-invalid
     value), so the button had no visible fill in either theme. */
  --g-warn:linear-gradient(135deg,#f5a623,#c9820a);
  /* MECKLY_GGREEN_V1: referenced across 7 pages (crosscheck, instore,
     parts-approval, services, setup, close + others) with no fallback
     and never defined anywhere — background silently dropped entirely,
     e.g. a progress-bar fill and a confirm button had no visible
     background on any of those pages the whole time. */
  --g-green:linear-gradient(135deg,#22d988,#16a34a);

  /* ── STATUS COLOURS ──
     These are the 5 pipeline states.
     Colour = status. One glance. No reading required.
  */
  --s-booked:         #4f8ef7;
  --s-booked-text:    #fff;

  --s-quoted-bg:      #F0EBD8;
  --s-quoted-text:    #1a2744;  /* always blue-family, never brown */

  --s-parts:          #f97316;
  --s-parts-text:     #fff;

  /* MECKLY_ACTION_BUTTON_V1 — 20 Sep 2026. The one orange an ACTION is
     drawn in: outlined, never filled. See .mu-act below for why it is
     its own token rather than --s-parts, which is a fill. */
  --act:              #f97316;

  --s-progress-bg:    #f5d623;
  --s-progress-text:  #1a2744;  /* always blue-family */

  --s-finished:       #22d988;
  --s-finished-text:  #04200f;

  --s-cancelled:      #64748b;
  --s-cancelled-text: rgba(255,255,255,.75);

  /* Background scale */
  --bg0:#070c14;
  --bg1:#0b1525;
  /* MECKLY_NATIVE_POPUP_SOLID_V1 — 7 Sep 2026, her report: "on a dark
     theme all our lookup pop-ups for adding cars, both on the main
     booking and on the fast quote, are washed out."

     It was never color-scheme — that is set below and computes to dark
     correctly. It is that --bg2/3/4 are TRANSLUCENT OVERLAYS (see the
     note beside --surface-1), meant to sit on top of --bg0. Inside the
     page that works everywhere. An open <select> list is not inside the
     page: the browser draws it on the OS's own surface, which on Windows
     is white. A 4%-white option background composited over white IS
     white, and --txt is near-white — so the makes came out white on
     white, exactly as she photographed.

     This is the solid surface for anything the OS draws for us. It must
     never be an alpha overlay, in either theme. */
  --popup-bg:#131c2e;
  --bg2:rgba(255,255,255,.04);
  --bg3:rgba(255,255,255,.07);
  --bg4:rgba(255,255,255,.11);

  /* Text scale */
  --txt:#F0F8FF;
  --txt2:rgba(240,248,255,.82);
  --muted:rgba(240,248,255,.48);
  --faint:rgba(240,248,255,.48); /* MECKLY_CONTRAST_AUDIT_V1 — was .24, real WCAG fail (2.0-2.1:1), computed fix */

  /* Border scale */
  --bd:rgba(255,255,255,.07);
  --bd2:rgba(255,255,255,.12);
  --bd3:rgba(255,255,255,.20);

  /* MECKLY_VISIBLE_OUTLINE_V1 — 20 Sep 2026, her words: "ensure all our
     buttons have a clearly visible outline. The outline on some is so
     faded against white I can't see it."

     She is right and it is measurable. --bd2 is the border every
     neutral button was drawn with, and in the LIGHT theme it computes
     to #cfcfcf against the card it sits on: 1.55:1. WCAG asks 3:1 of a
     UI component's boundary, so a button edge at 1.55:1 is not a faint
     edge, it is an invisible one.

     A button's outline is the only thing saying "this is a button",
     so it gets a token of its own rather than borrowing the one used
     for table rules and card seams, which are meant to be quiet.
     3.55:1 dark, 3.23:1 light — computed, not eyeballed. */
  --btn-bd:rgba(255,255,255,.38);

  /* MECKLY_DARK_MODE_IS_NOT_A_FALLBACK_V1 — the ground under a row with
     unsaved changes. It was only ever `var(--bg-warning, #fff8e6)` on a
     token nothing defined, so every shop on the dark theme got a cream
     row on a black page. Amber at low strength here, the same family
     the rest of the app warns in. */
  --bg-warning:rgba(245,166,35,.13);

  /* MECKLY_LIGHT_THEME_V1: solid panel surfaces — sidebar, drawer, toast.
     Separate from --bg2/3/4 because those are translucent overlays meant
     to sit on top of --bg0, not stand-alone solid panels. */
  --surface-1:#0a1020;
  --surface-2:#0d1526;

  /* Semantic colours */
  --green:#22d988;
  --green-s:rgba(34,217,136,.10);
  --green-b:rgba(34,217,136,.25);
  /* JOBCARD_LEDGER_V1 — 31 Aug 2026, her ask: converting the hardcoded
     greens scattered across meckly-jobcard.js/index.html/calendar.html
     to var(--green) surfaced a real, new contrast problem — dark theme's
     green is bright enough for dark text, but light theme's new #028A0F
     is dark enough that the SAME dark text fails WCAG AA (3.81:1,
     computed). --on-green is the real fix: the text colour that goes ON
     TOP of a --green fill, themed alongside it rather than hardcoded
     once for both. */
  --on-green:#04200f;
  --red:#f06060;
  --red-s:rgba(240,96,96,.10);
  --red-b:rgba(240,96,96,.28);
  --amber:#f5a623;
  --amber-s:rgba(245,166,35,.10);
  --amber-b:rgba(245,166,35,.25);

  /* Shape */
  --r:12px;
  --r2:10px;
  --r3:8px;

  /* Typography */
  --mono:'JetBrains Mono',ui-monospace,monospace;

  /* Layout */
  --sb-w:220px;         /* sidebar width on desktop */
  --tap:52px;           /* minimum tap target — grease finger rule */
  --max-content:900px;  /* max content width on pages without sidebar */
}

/* ═══════════════════════════════════════════════════════
   LAYOUT — sidebar + content (injected by nav.js)
═══════════════════════════════════════════════════════ */
.mu-layout{display:flex;min-height:100dvh}

/* ── DESKTOP SIDEBAR ── */
.mu-sidebar{
  width:var(--sb-w);flex-shrink:0;
  background:var(--surface-1);border-right:1px solid var(--bd2);
  display:flex;flex-direction:column;
  position:fixed;top:0;left:0;bottom:0;z-index:100;overflow:hidden;
}
.mu-sb-head{padding:18px 16px 14px;border-bottom:1px solid var(--bd);display:flex;align-items:center;gap:10px;flex-shrink:0}
/* MECKLY_BIG_SHOP_LOGO_V1 — her ask: a big logo top-left. This is the
   shop's own mark once branding.logo_url is set (nav.js swaps the wrench
   glyph for the image), so it is the client's identity on their own
   screen, and 34px was too small to read as one. The gradient tile stays
   as the fallback for a shop that has not uploaded a logo yet. */
.mu-sb-logo{width:46px;height:46px;border-radius:11px;flex-shrink:0;background:var(--g-brand);display:flex;align-items:center;justify-content:center;font-size:23px;overflow:hidden}
.mu-sb-logo img{width:100%;height:100%;object-fit:contain;border-radius:11px}
.mu-sb-shop{font-size:14px;font-weight:900;letter-spacing:.5px;color:var(--txt);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mu-sb-body{flex:1;overflow-y:auto;padding:8px}
.mu-sb-sec{font-size:9px;font-weight:800;text-transform:uppercase;letter-spacing:.12em;color:var(--faint);padding:12px 8px 4px}
.mu-sb-link{
  display:flex;align-items:center;gap:10px;
  padding:9px 10px;border-radius:8px;
  color:var(--muted);font-size:13px;font-weight:600;
  cursor:pointer;transition:background .12s,color .12s;
  text-decoration:none;border:none;background:transparent;
  width:100%;text-align:left;min-height:40px;
  -webkit-tap-highlight-color:transparent;
}
.mu-sb-link:hover{background:var(--bg3);color:var(--txt)}
.mu-sb-link.active{background:rgba(26,111,219,.14);color:var(--brand);font-weight:700}
.mu-sb-icon{font-size:15px;width:22px;text-align:center;flex-shrink:0}
.mu-sb-soon{margin-left:auto;font-size:8px;font-weight:800;color:var(--faint);background:var(--bg3);padding:2px 6px;border-radius:4px;letter-spacing:.06em;flex-shrink:0}
.mu-sb-div{height:1px;background:var(--bd);margin:4px 8px}
.mu-sb-foot{padding:12px 10px calc(12px + env(safe-area-inset-bottom));border-top:1px solid var(--bd);flex-shrink:0}
.mu-sb-user{display:flex;align-items:center;gap:8px}
.mu-sb-av{
  width:32px;height:32px;border-radius:50%;background:var(--g-brand);
  display:flex;align-items:center;justify-content:center;
  font-family:var(--mono);font-size:11px;font-weight:800;color:#fff;
  flex-shrink:0;border:2px solid rgba(26,111,219,.35);
}
.mu-sb-uname{font-size:12px;font-weight:700;color:var(--txt);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mu-sb-urole{font-size:10px;color:var(--muted);margin-top:1px;text-transform:capitalize}
.mu-sb-logout{
  margin-left:auto;width:30px;height:30px;border-radius:50%;
  border:1px solid rgba(240,96,96,.22);background:rgba(240,96,96,.08);
  color:#f06060;font-size:14px;cursor:pointer;flex-shrink:0;
  display:flex;align-items:center;justify-content:center;transition:background .12s;
  -webkit-tap-highlight-color:transparent;
}
.mu-sb-logout:hover{background:rgba(240,96,96,.20)}

/* ── MAIN CONTENT AREA ── */
.mu-content{
  flex:1;
  margin-left:var(--sb-w);
  min-width:0;
  display:flex;
  flex-direction:column;
}

/* ── MOBILE TOP BAR ── */
.mu-topbar{
  display:none; /* shown on mobile via media query */
  height:54px;
  /* MECKLY_TOPBAR_LIGHT_V1: was hardcoded rgba(7,12,20,.92) — the one
     shared chrome element missed through the whole light-theme rollout,
     so it stayed dark on mobile even once the sidebar was correctly light. */
  background:var(--surface-1);
  backdrop-filter:blur(24px);-webkit-backdrop-filter:blur(24px);
  border-bottom:1px solid var(--bd);
  align-items:center;padding:0 16px;gap:10px;
  position:sticky;top:0;z-index:90;
}
.mu-tb-logo{width:32px;height:32px;border-radius:8px;flex-shrink:0;background:var(--g-brand);display:flex;align-items:center;justify-content:center;font-size:15px}
.mu-tb-shop{font-size:15px;font-weight:900;letter-spacing:.5px;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mu-tb-btn{
  width:40px;height:40px;border-radius:50%;
  border:1px solid var(--bd2);background:var(--bg2);
  color:var(--muted);cursor:pointer;
  display:flex;align-items:center;justify-content:center;
  flex-shrink:0;transition:background .12s;
  -webkit-tap-highlight-color:transparent;
}
.mu-tb-btn:hover{background:var(--bg3);color:var(--txt)}
.mu-tb-btn.spin svg,.mu-tb-btn.spin{animation:mu-spin .6s linear infinite}
.mu-tb-av{
  width:40px;height:40px;border-radius:50%;flex-shrink:0;
  display:flex;align-items:center;justify-content:center;
  font-family:var(--mono);font-size:12px;font-weight:800;
  color:#fff;background:var(--g-brand);cursor:pointer;
  border:2px solid rgba(26,111,219,.45);
  -webkit-tap-highlight-color:transparent;
}
.mu-tb-menu{
  width:40px;height:40px;border-radius:50%;
  border:1px solid var(--bd2);background:var(--bg2);
  color:var(--muted);cursor:pointer;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;
  flex-shrink:0;transition:background .12s;
  -webkit-tap-highlight-color:transparent;
}
.mu-tb-menu:hover{background:var(--bg3)}
.mu-tb-menu span{display:block;width:15px;height:1.5px;background:currentColor;border-radius:1px}

/* ── MOBILE DRAWER ── */
.mu-overlay{
  position:fixed;inset:0;z-index:200;
  background:rgba(0,0,0,.70);backdrop-filter:blur(6px);
  opacity:0;visibility:hidden;transition:opacity .2s,visibility 0s .2s;
  display:none; /* shown on mobile */
}
.mu-overlay.open{opacity:1;visibility:visible;transition:opacity .2s}
.mu-drawer{
  position:fixed;top:0;right:0;bottom:0;z-index:201;
  width:min(300px,90vw);
  background:linear-gradient(180deg,var(--surface-2),var(--bg0));
  border-left:1px solid var(--bd2);
  box-shadow:-24px 0 64px rgba(0,0,0,.75);
  transform:translateX(110%);
  transition:transform .26s cubic-bezier(.4,0,.2,1);
  display:none;flex-direction:column;overflow:hidden; /* shown on mobile */
}
.mu-drawer.open{transform:translateX(0)}
.mu-dr-body{flex:1;overflow-y:auto;padding:16px 10px 8px}
.mu-dr-sec{font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:.10em;color:var(--faint);padding:12px 10px 5px}
.mu-dr-link{
  display:flex;align-items:center;gap:12px;
  padding:12px 10px;border-radius:var(--r2);
  color:var(--txt2);font-size:14px;font-weight:600;
  cursor:pointer;transition:background .12s;
  text-decoration:none;border:none;background:transparent;
  width:100%;text-align:left;min-height:var(--tap);
  -webkit-tap-highlight-color:transparent;
}
.mu-dr-link:hover,.mu-dr-link.active{background:var(--bg3);color:var(--txt)}
.mu-dr-icon{width:36px;height:36px;border-radius:var(--r3);display:flex;align-items:center;justify-content:center;font-size:16px;flex-shrink:0;background:var(--bg3);border:1px solid var(--bd)}
.mu-dr-icon.hi{background:rgba(26,111,219,.15);border-color:rgba(26,111,219,.28)}
.mu-dr-div{height:1px;background:var(--bd);margin:4px 10px}
.mu-dr-foot{padding:12px 10px calc(16px + env(safe-area-inset-bottom));border-top:1px solid var(--bd);flex-shrink:0}
.mu-dr-user{display:flex;align-items:center;gap:10px}
.mu-dr-av{width:40px;height:40px;border-radius:50%;background:var(--g-brand);display:flex;align-items:center;justify-content:center;font-family:var(--mono);font-size:12px;font-weight:800;color:#fff;flex-shrink:0;border:2px solid rgba(26,111,219,.35)}
.mu-dr-uname{font-size:14px;font-weight:700;color:var(--txt)}
.mu-dr-urole{font-size:11px;color:var(--muted);margin-top:2px;text-transform:capitalize}
.mu-dr-logout{margin-left:auto;height:36px;padding:0 14px;border-radius:999px;background:rgba(240,96,96,.10);color:#f06060;font-size:12px;font-weight:700;cursor:pointer;white-space:nowrap;transition:background .12s;border:1px solid rgba(240,96,96,.22);-webkit-tap-highlight-color:transparent}
.mu-dr-logout:hover{background:rgba(240,96,96,.22)}

/* ═══════════════════════════════════════════════════════
   SHARED COMPONENTS
═══════════════════════════════════════════════════════ */

/* ── PAGE WRAP (for pages without sidebar, like workflow/quote/close) ── */
.mu-page{
  max-width:var(--max-content);
  margin:0 auto;
  padding:16px 16px calc(80px + env(safe-area-inset-bottom));
}
@media(max-width:640px){.mu-page{padding:12px 12px calc(80px + env(safe-area-inset-bottom))}}

/* ── BACK NAV (for detail pages) ── */
.mu-back-nav{
  height:54px;
  background:var(--surface-1);
  backdrop-filter:blur(24px);-webkit-backdrop-filter:blur(24px);
  border-bottom:1px solid var(--bd);
  display:flex;align-items:center;padding:0 16px;gap:10px;
  position:sticky;top:0;z-index:90;
}
/* MECKLY_BACKNAV_LIGHT_V1: same undefined-dark bug as .mu-topbar
   (change137) — a completely separate shared component, never touched.
   Also: on narrow screens the customer-name portion (flex-shrink:0)
   could push the action button (e.g. Save Draft) off-screen entirely
   since nothing before it was allowed to give up space for it. */
@media (max-width:480px){
  .mu-nav-ref{display:none}
}
/* MECKLY_BRAND_UNIFORM_V1: .mu-back-nav had no shop branding at all —
   shared logo+name, same fetch mechanism (brand.js) as everywhere else.
   Hidden on narrow screens where this bar is already tight. */
.mu-back-brand-logo{width:24px;height:24px;border-radius:6px;background:var(--g-brand);display:flex;align-items:center;justify-content:center;font-size:12px;flex-shrink:0}
.mu-back-brand-name{font-size:13px;font-weight:800;color:var(--txt);flex-shrink:0;white-space:nowrap}
.mu-back-brand-sep{width:1px;height:14px;background:var(--bd2);flex-shrink:0}
@media (max-width:600px){.mu-back-brand-name,.mu-back-brand-sep{display:none}}
.mu-back-btn{
  display:flex;align-items:center;gap:5px;
  height:36px;padding:0 14px 0 10px;
  border-radius:999px;border:1px solid var(--bd2);
  background:var(--bg2);color:var(--muted);
  font-size:13px;font-weight:700;cursor:pointer;
  text-decoration:none;transition:all .12s;flex-shrink:0;
  -webkit-tap-highlight-color:transparent;
}
.mu-back-btn:hover{color:var(--txt);background:var(--bg3)}
.mu-back-btn svg{width:15px;height:15px;stroke:currentColor;fill:none;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round}
.mu-nav-title{font-size:14px;font-weight:800;color:var(--txt);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;letter-spacing:-.02em}
.mu-nav-ref{font-family:var(--mono);font-size:12px;color:var(--muted);flex-shrink:0}

/* ── STATUS CHIPS ── */
.mu-chip{display:inline-flex;align-items:center;padding:4px 10px;border-radius:999px;font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.05em}
.mu-chip-booked{background:var(--s-booked);color:var(--s-booked-text)}
.mu-chip-quoted{background:var(--s-quoted-bg);color:var(--s-quoted-text)}
.mu-chip-parts{background:var(--s-parts);color:var(--s-parts-text)}
.mu-chip-progress{background:var(--s-progress-bg);color:var(--s-progress-text)}
.mu-chip-finished{background:var(--s-finished);color:var(--s-finished-text)}
.mu-chip-cancelled{background:var(--s-cancelled);color:var(--s-cancelled-text)}

/* ── BUTTONS ── */
.mu-btn{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  min-height:var(--tap);
  padding:0 20px;
  border-radius:var(--r2);border:none;
  font-size:15px;font-weight:800;
  cursor:pointer;transition:filter .12s,transform .08s;
  letter-spacing:-.01em;text-decoration:none;
  -webkit-tap-highlight-color:transparent;
}
.mu-btn:active{transform:scale(.98)}
.mu-btn:hover{filter:brightness(1.08)}
.mu-btn:disabled{opacity:.5;cursor:not-allowed;filter:none;transform:none}

.mu-btn-primary{background:var(--g-brand);color:#fff;box-shadow:0 4px 16px rgba(26,111,219,.30)}
.mu-btn-green{background:linear-gradient(135deg,#22d988,#0f9e75);color:#04200f;box-shadow:0 4px 16px rgba(34,217,136,.22)}
.mu-btn-orange{background:linear-gradient(135deg,#f97316,#c25a00);color:#fff;box-shadow:0 4px 16px rgba(249,115,22,.28)}
.mu-btn-yellow{background:linear-gradient(135deg,#f5d623,#c9a800);color:#1a2744;box-shadow:0 4px 16px rgba(245,214,35,.22)}
.mu-btn-red{background:linear-gradient(135deg,#f06060,#c0392b);color:#fff;box-shadow:0 4px 16px rgba(240,96,96,.22)}
.mu-btn-ghost{background:var(--bg2);color:var(--muted);border:1px solid var(--btn-bd);box-shadow:none}
.mu-btn-ghost:hover{background:var(--bg3);color:var(--txt);border-color:var(--bd3)}

/* ── THE ACTION BUTTON ──────────────────────────────────────────────
   MECKLY_ACTION_BUTTON_V1 — 20 Sep 2026, her ask for the stock section:
   "all buttons on the stock page look too much the same, it's shocking."
   They did. Navigation was an underline tab strip and the actions were
   borderless pills, so nothing on the page carried more weight than
   anything else. Navigation and action need two different languages,
   and this is the action one.

   The shape is the day board's per-booking chips — the outlined orange
   ○ Quote / ○ Parts / ○ Invoice on a job card — which is what she
   pointed at. Those rules live inline in index.html AND again in
   mechanic-home.html, so a third copy for stock would have been a
   third place to edit. This is the one definition; those two pages can
   adopt it without changing how they look.

   Two deliberate differences from the chip:

     SIZE. The chip is 10.5px text in 3px of padding — about 21px tall.
     Right for a status marker crammed onto a dense day board, far too
     small for the row of buttons you actually reach for on a phone.
     38px minimum here, which is a thumb.

     COLOUR. The chip hard-codes #f97316. On the light theme that is
     2.55:1 against the card it sits on — it fails WCAG AA for text
     (4.5:1) and fails even the 3:1 asked of a UI component, so those
     chips are genuinely hard to read in light mode today. --act is
     #f97316 on dark (6.04:1, comfortable) and #C2410C on light
     (4.71:1 on --bg3, 5.18:1 on white). Computed, not eyeballed.

   OUTLINED, NEVER FILLED. Filled amber already means "something is
   wrong" across this app — low stock, on-hand below zero, an invoice
   that does not add up. An action drawn like a warning teaches people
   to stop reading warnings. Outline = something you can do; fill =
   something that needs you. */
.mu-act{display:inline-flex;align-items:center;justify-content:center;gap:6px;
  min-height:38px;padding:8px 14px;border-radius:8px;
  background:transparent;border:1px solid var(--act);color:var(--act);
  font-family:inherit;font-size:13px;font-weight:700;line-height:1.15;
  text-decoration:none;white-space:nowrap;cursor:pointer;
  transition:background .12s ease,border-color .12s ease,color .12s ease}
.mu-act:hover:not(:disabled){background:color-mix(in srgb,var(--act) 12%,transparent)}
.mu-act:disabled{opacity:.42;cursor:default}
.mu-act .mu-act-ico{font-size:15px;line-height:1;flex-shrink:0}
/* Destructive actions borrow the shape and swap the colour, so Delete
   never reads as one more thing it is safe to press. */
.mu-act.mu-act-danger{border-color:var(--red);color:var(--red)}
.mu-act.mu-act-danger:hover:not(:disabled){background:var(--red-s)}
/* A filter is STATE, not an action, so it is neither orange nor a
   call to action until it is switched on — then it says so. */
.mu-act.mu-act-state{border-color:var(--btn-bd);color:var(--txt2)}
.mu-act.mu-act-state:hover:not(:disabled){background:var(--bg3);color:var(--txt)}
.mu-act.mu-act-state[aria-pressed="true"]{border-color:var(--brand);color:var(--brand-text);background:var(--bg3)}
/* ── THE QUANTITY BAND ───────────────────────────────────────────────
   MECKLY_QTY_IS_ORANGE_V1 — 20 Sep 2026, her ask: "ensure the qty
   columns in all of our stock tables has a bit of an orange tint to it,
   to help mechanics know when things are out of stock etc."

   One token, every stock table, so the quantity is in the same place
   and the same colour whichever screen somebody is on — In Stock,
   Buy-Stock, Receive, Pay-Creditors, Returns, Cores. It was defined on
   In Stock alone before this, which is how a convention starts and then
   quietly fails to spread.

   A BIT of a tint, deliberately. Orange elsewhere in this app means
   "something is wrong" — low stock, on-hand below zero, an invoice that
   does not add up — and those states colour the FIGURE, strongly. This
   sits behind them at a tenth of that strength: enough to find the
   column across a wide table without reading a heading, far too faint
   to read as a warning of its own or to fight the number on top of it.
   The band is never on the figure. */
/* MECKLY_DARK_MODE_IS_NOT_A_FALLBACK_V1 — 20 Sep 2026. The band alone
   was built for the light theme and quietly failed on the dark one: a
   warm wash at 9% over a near-black ground composites to hsl(12, 15%,
   13%), which is brown. Every candidate did — .14 of the same orange,
   a lighter orange, a lighter orange at .15 — because the ground is
   what dominates at low alpha, not the tint. It is not a colour that
   was picked badly; it is a technique that only works on white.
   Measured five ways before changing the approach rather than the hex.

   So the hue comes from an EDGE instead: a rail down both sides of the
   column at a strength where orange is still orange, with the wash kept
   behind it for the sweep. Drawn as an inset shadow rather than a
   border so it costs no layout in a grid or a table cell. */
:root{ --qty-band:rgba(249,115,22,.09); --qty-edge:rgba(249,115,22,.45); }
:root[data-theme="light"]{ --qty-band:rgba(194,65,12,.07); --qty-edge:rgba(194,65,12,.30); }
.mck-qty{background:var(--qty-band);
  box-shadow:inset 1px 0 0 var(--qty-edge), inset -1px 0 0 var(--qty-edge)}

/* A hairline between the things you DO and the filters that only change
   what you are looking at. Hidden on a phone: a vertical rule in a
   wrapped row lands wherever the wrap happens to fall. */
.mu-act-sep{width:1px;align-self:stretch;margin:2px;background:var(--btn-bd);flex:0 0 auto}
@media (max-width:560px){.mu-act-sep{display:none}}

/* On a phone the row wraps. It must NOT stretch to fill: growing each
   button to fill its line turned one wrapped button into a full-width
   slab and pushed the next one off the screen edge. Natural width,
   tighter padding, and they pack three or four to a line. */
@media (max-width:560px){
  .mu-act{flex:0 1 auto;min-width:0;padding:8px 11px}
  .mu-act .mu-act-lbl{overflow:hidden;text-overflow:ellipsis}
}

/* Small button variant */
.mu-btn-sm{min-height:36px;padding:0 14px;font-size:12px;font-weight:700;border-radius:var(--r3)}

/* ── CARDS ── */
.mu-card{
  background:#0d1525;
  border-radius:var(--r);
  border:1px solid var(--bd2);
  overflow:hidden;
}
.mu-card-head{
  padding:14px 16px;
  border-bottom:1px solid var(--bd);
  display:flex;align-items:center;justify-content:space-between;gap:10px;
}
.mu-card-title{font-size:13px;font-weight:800;text-transform:uppercase;letter-spacing:.06em;color:var(--txt2)}
.mu-card-body{padding:16px}

/* ── DATA ROWS (for detail pages) ── */
.mu-drow{display:flex;align-items:baseline;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--bd);gap:12px}
.mu-drow:last-child{border-bottom:none}
.mu-dl{font-size:13px;color:var(--muted);flex-shrink:0;font-weight:500}
.mu-dv{font-size:14px;font-weight:700;color:var(--txt);text-align:right}
.mu-dv-mono{font-family:var(--mono);font-size:13px;font-weight:500;color:var(--txt);text-align:right}

/* ── FORM ELEMENTS ── */
.mu-field{display:flex;flex-direction:column;gap:6px}
.mu-label{font-size:12px;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.06em}
.mu-input{
  width:100%;
  min-height:var(--tap);
  padding:0 14px;
  border-radius:var(--r2);
  border:1px solid var(--bd2);
  background:var(--bg2);
  color:var(--txt);
  font-size:16px; /* 16px prevents iOS zoom */
  outline:none;
  transition:border-color .15s,background .15s;
}
.mu-input::placeholder{color:var(--muted)}
.mu-input:focus{border-color:rgba(26,111,219,.5);background:rgba(26,111,219,.04);box-shadow:0 0 0 3px rgba(26,111,219,.12)}
textarea.mu-input{min-height:100px;padding:12px 14px;resize:vertical;line-height:1.5}
select.mu-input{cursor:pointer}

/* MECKLY_NATIVE_POPUP_SOLID_V1 — every <select> in the app, not the four
   pages that had already been patched by hand with a hard-coded #1a2236.
   Those hard-codes fixed the dark theme one page at a time and were wrong
   on the light one; this is one rule, both themes, and a form added
   tomorrow gets it without anyone remembering.

   Deliberately unqualified: it has to reach a <select> nobody has given a
   class to, which is exactly how the fast quote's Make/Model pickers were
   missed. */
select option,
select optgroup{
  background-color:var(--popup-bg);
  color:var(--txt);
}
select option:disabled{color:var(--faint)}

/* ── TOAST ── */
#toast,.mu-toast{
  position:fixed;
  bottom:calc(20px + env(safe-area-inset-bottom));
  left:50%;
  transform:translateX(-50%) translateY(120px);
  background:var(--surface-1);
  backdrop-filter:blur(16px);
  color:var(--txt);
  border:1px solid var(--bd2);
  border-radius:999px;
  padding:13px 24px;
  font-size:14px;font-weight:700;
  z-index:400;
  white-space:nowrap;pointer-events:none;
  transition:transform .3s cubic-bezier(.34,1.56,.64,1);
  box-shadow:0 12px 40px rgba(0,0,0,.6);
  max-width:calc(100vw - 32px);text-align:center;
}
#toast.show,.mu-toast.show{transform:translateX(-50%) translateY(0)}

/* ── SPINNER ── */
.mu-spinner{
  width:28px;height:28px;border-radius:50%;
  border:2.5px solid var(--bd2);
  border-top-color:var(--brand);
  animation:mu-spin .75s linear infinite;
}
.mu-loading{
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:14px;min-height:50dvh;
  color:var(--faint);font-size:11px;font-weight:700;
  text-transform:uppercase;letter-spacing:.08em;
}

/* ── EMPTY STATE ── */
.mu-empty{
  padding:60px 20px;text-align:center;
  color:var(--faint);font-size:13px;font-weight:700;
  text-transform:uppercase;letter-spacing:.08em;
}

/* ── SECTION HEADERS ── */
.mu-sec-head{
  display:flex;align-items:center;gap:10px;
  padding:10px 0 8px;margin-top:22px;
  border-bottom:2px solid var(--sc,var(--bd2));
}
.mu-sec-head:first-of-type{margin-top:12px}
.mu-sec-title{font-size:13px;font-weight:900;text-transform:uppercase;letter-spacing:.06em;color:var(--sc,var(--txt))}
.mu-sec-count{font-family:var(--mono);font-size:13px;font-weight:700;color:var(--sc,var(--muted));background:var(--bg3);padding:3px 10px;border-radius:999px;border:1px solid var(--bd2)}

/* ── BADGE / TAG ── */
.mu-badge{display:inline-flex;align-items:center;padding:2px 8px;border-radius:4px;font-size:11px;font-weight:700;white-space:nowrap}
.mu-badge-green{background:var(--green-s);color:var(--green);border:1px solid var(--green-b)}
.mu-badge-amber{background:var(--amber-s);color:var(--amber);border:1px solid var(--amber-b)}
.mu-badge-red{background:var(--red-s);color:var(--red);border:1px solid var(--red-b)}
.mu-badge-muted{background:var(--bg3);color:var(--muted);border:1px solid var(--bd2)}

/* ── DIVIDER ── */
.mu-div{height:1px;background:var(--bd);margin:16px 0}

/* ── AVATAR ── */
.mu-av{border-radius:50%;display:flex;align-items:center;justify-content:center;font-family:var(--mono);font-weight:800;color:#fff;flex-shrink:0}
.mu-av-sm{width:24px;height:24px;font-size:9px}
.mu-av-md{width:36px;height:36px;font-size:13px}
.mu-av-lg{width:48px;height:48px;font-size:16px}

/* ── UTILITY ── */
.mu-mono{font-family:var(--mono)}
.mu-muted{color:var(--muted)}
.mu-faint{color:var(--faint)}
.mu-hidden{display:none!important}
.mu-truncate{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* ═══════════════════════════════════════════════════════
   RESPONSIVE — mobile breakpoint
   Sidebar hides, top bar shows
═══════════════════════════════════════════════════════ */
@media(max-width:860px){
  .mu-sidebar{display:none}
  .mu-content{margin-left:0}
  .mu-topbar{display:flex}
  .mu-overlay{display:block}
  .mu-drawer{display:flex}
}

/* ═══════════════════════════════════════════════════════
   LEGACY ALIASES — maps old index.html class names to
   the mu-* system. Allows index.html to work without
   renaming every element. Future pages use mu-* directly.
═══════════════════════════════════════════════════════ */
.layout{display:flex;min-height:100dvh}
.sidebar{width:var(--sb-w);flex-shrink:0;background:var(--surface-1);border-right:1px solid var(--bd2);display:flex;flex-direction:column;position:fixed;top:0;left:0;bottom:0;z-index:100;overflow:hidden}
.sb-head{padding:18px 16px 14px;border-bottom:1px solid var(--bd);display:flex;align-items:center;gap:10px;flex-shrink:0}
.sb-logo{width:34px;height:34px;border-radius:9px;flex-shrink:0;background:var(--g-brand);display:flex;align-items:center;justify-content:center;font-size:17px}
.sb-shop{font-size:14px;font-weight:900;letter-spacing:.5px;color:var(--txt);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sb-body{flex:1;overflow-y:auto;padding:8px}
.sb-sec-lbl{font-size:9px;font-weight:800;text-transform:uppercase;letter-spacing:.12em;color:var(--faint);padding:12px 8px 4px}
.sb-link{display:flex;align-items:center;gap:10px;padding:9px 10px;border-radius:8px;color:var(--muted);font-size:13px;font-weight:600;cursor:pointer;transition:background .12s,color .12s;text-decoration:none;border:none;background:transparent;width:100%;text-align:left;min-height:40px}
.sb-link:hover{background:var(--bg3);color:var(--txt)}
.sb-link.active{background:rgba(26,111,219,.14);color:var(--brand);font-weight:700}
.sb-link-icon{font-size:15px;width:22px;text-align:center;flex-shrink:0}
.sb-link-soon{margin-left:auto;font-size:8px;font-weight:800;color:var(--faint);background:var(--bg3);padding:2px 6px;border-radius:4px;letter-spacing:.06em;flex-shrink:0}
.sb-div{height:1px;background:var(--bd);margin:4px 8px}
.sb-foot{padding:12px 10px calc(12px + env(safe-area-inset-bottom));border-top:1px solid var(--bd);flex-shrink:0}
.sb-user{display:flex;align-items:center;gap:8px}
.sb-av{width:32px;height:32px;border-radius:50%;background:var(--g-brand);display:flex;align-items:center;justify-content:center;font-family:var(--mono);font-size:11px;font-weight:800;color:#fff;flex-shrink:0;border:2px solid rgba(26,111,219,.35)}
.sb-uname{font-size:12px;font-weight:700;color:var(--txt);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sb-urole{font-size:10px;color:var(--muted);margin-top:1px;text-transform:capitalize}
.sb-logout{margin-left:auto;width:30px;height:30px;border-radius:50%;border:1px solid rgba(240,96,96,.22);background:rgba(240,96,96,.08);color:#f06060;font-size:14px;cursor:pointer;flex-shrink:0;display:flex;align-items:center;justify-content:center;transition:background .12s}
.sb-logout:hover{background:rgba(240,96,96,.20)}
.content{flex:1;margin-left:var(--sb-w);min-width:0;display:flex;flex-direction:column}
.top-bar{display:none;height:54px;background:rgba(7,12,20,.92);backdrop-filter:blur(24px);-webkit-backdrop-filter:blur(24px);border-bottom:1px solid var(--bd);align-items:center;padding:0 14px;gap:10px;position:sticky;top:0;z-index:90}
.tb-logo{width:32px;height:32px;border-radius:8px;flex-shrink:0;background:var(--g-brand);display:flex;align-items:center;justify-content:center;font-size:15px}
.tb-shop{font-size:15px;font-weight:900;letter-spacing:.5px;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tb-btn{width:40px;height:40px;border-radius:50%;border:1px solid var(--bd2);background:var(--bg2);color:var(--muted);cursor:pointer;display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:background .12s}
.tb-btn:hover{background:var(--bg3);color:var(--txt)}
.tb-btn.spin svg{animation:mu-spin .6s linear infinite}
.tb-avatar{width:40px;height:40px;border-radius:50%;flex-shrink:0;display:flex;align-items:center;justify-content:center;font-family:var(--mono);font-size:12px;font-weight:800;color:#fff;background:var(--g-brand);cursor:pointer;border:2px solid rgba(26,111,219,.45)}
.tb-menu{width:40px;height:40px;border-radius:50%;border:1px solid var(--bd2);background:var(--bg2);color:var(--muted);cursor:pointer;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;flex-shrink:0;transition:background .12s}
.tb-menu:hover{background:var(--bg3)}
.tb-menu span{display:block;width:15px;height:1.5px;background:currentColor;border-radius:1px}
.drawer-overlay{position:fixed;inset:0;z-index:200;background:rgba(0,0,0,.70);backdrop-filter:blur(6px);opacity:0;visibility:hidden;transition:opacity .2s,visibility 0s .2s;display:none}
.drawer-overlay.open{opacity:1;visibility:visible;transition:opacity .2s}
.drawer{position:fixed;top:0;right:0;bottom:0;z-index:201;width:min(300px,90vw);background:linear-gradient(180deg,var(--surface-2),var(--bg0));border-left:1px solid var(--bd2);box-shadow:-24px 0 64px rgba(0,0,0,.75);transform:translateX(110%);transition:transform .26s cubic-bezier(.4,0,.2,1);display:none;flex-direction:column;overflow:hidden}
.drawer.open{transform:translateX(0)}
.drawer-body{flex:1;overflow-y:auto;padding:16px 10px 8px}
.drawer-sec-lbl{font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:.10em;color:var(--faint);padding:12px 10px 5px}
.drawer-link{display:flex;align-items:center;gap:12px;padding:12px 10px;border-radius:var(--r2);color:var(--txt2);font-size:14px;font-weight:600;cursor:pointer;transition:background .12s;text-decoration:none;border:none;background:transparent;width:100%;text-align:left;min-height:52px}
.drawer-link:hover,.drawer-link.active{background:var(--bg3);color:var(--txt)}
.drawer-link-icon{width:36px;height:36px;border-radius:var(--r3);display:flex;align-items:center;justify-content:center;font-size:16px;flex-shrink:0;background:var(--bg3);border:1px solid var(--bd)}
.drawer-link-icon.hi{background:rgba(26,111,219,.15);border-color:rgba(26,111,219,.28)}
.drawer-div{height:1px;background:var(--bd);margin:4px 10px}
.drawer-foot{padding:12px 10px calc(16px + env(safe-area-inset-bottom));border-top:1px solid var(--bd);flex-shrink:0}
.drawer-user{display:flex;align-items:center;gap:10px}
.drawer-av{width:40px;height:40px;border-radius:50%;background:var(--g-brand);display:flex;align-items:center;justify-content:center;font-family:var(--mono);font-size:12px;font-weight:800;color:#fff;flex-shrink:0;border:2px solid rgba(26,111,219,.35)}
.drawer-uname{font-size:14px;font-weight:700;color:var(--txt)}
.drawer-urole{font-size:11px;color:var(--muted);margin-top:2px;text-transform:capitalize}
.drawer-logout{margin-left:auto;height:36px;padding:0 14px;border-radius:999px;background:rgba(240,96,96,.10);color:#f06060;font-size:12px;font-weight:700;cursor:pointer;white-space:nowrap;transition:background .12s;border:1px solid rgba(240,96,96,.22)}
.drawer-logout:hover{background:rgba(240,96,96,.22)}
#toast{position:fixed;bottom:calc(20px + env(safe-area-inset-bottom));left:50%;transform:translateX(-50%) translateY(120px);background:var(--surface-1);backdrop-filter:blur(16px);color:var(--txt);border:1px solid var(--bd2);border-radius:999px;padding:13px 24px;font-size:14px;font-weight:700;z-index:400;white-space:nowrap;pointer-events:none;transition:transform .3s cubic-bezier(.34,1.56,.64,1);box-shadow:0 12px 40px rgba(0,0,0,.6);max-width:calc(100vw - 32px);text-align:center}
#toast.show{transform:translateX(-50%) translateY(0)}
@media(max-width:860px){
  .sidebar{display:none}
  .content{margin-left:0}
  .top-bar{display:flex}
  .drawer-overlay{display:block}
  .drawer{display:flex}
}

/* ═══════════════════════════════════════════════════════
   MECKLY_LIGHT_THEME_V1 — light theme token overrides
   Applied when <html data-theme="light">. Set/read by /assets/theme.js.
   PILOT SCOPE (6 Aug 2026): this file + index.html only. Every other
   page still hardcodes its own inline colours and will stay dark until
   converted page by page — see meckly-change-history.md.
═══════════════════════════════════════════════════════ */
/* ═══════════════════════════════════════════════════════
   MECKLY_LIGHT_THEME_CONTRAST_V1 — darker muted/faint text and
   stronger card/border opacities. The original light values (muted
   .50, faint .30, bg2 .045) were tuned by eye against a dark canvas
   and read as washed-out/foggy on a light one — bumped for real
   legibility, not just technically-passes-contrast.
═══════════════════════════════════════════════════════ */
:root[data-theme="light"]{
  /* MECKLY_CONTRAST_AUDIT_V1 — light theme's --brand as text already
     passes AA on white (4.84:1), no lightened variant needed here. */
  --brand-text:#1a6fdb;

  /* MECKLY_ACTION_BUTTON_V1 — #f97316 is 2.55:1 on --bg3 here and
     2.80:1 on white: it fails AA for text and fails the 3:1 asked of a
     UI component. #C2410C is the same orange darkened until it passes —
     4.71:1 on --bg3, 4.96:1 on --bg2, 5.18:1 on white. Computed with
     the WCAG relative-luminance formula, the same way --faint was
     tuned above. Dark theme keeps #f97316, which clears 6:1 there. */
  --act:#C2410C;
  /* The light theme's version of the same: the original hard-coded
     cream, which was right here all along and wrong everywhere else. */
  --bg-warning:#FFF8E6;

  /* MECKLY_NATIVE_LOOKUP_DARK_V1 — same fix as the base :root block above,
     the other direction: light theme's native select/date-picker popups
     must render with the browser's LIGHT scheme, or the reverse problem
     happens (dark-tuned popup on a page that's now light). */
  color-scheme: light;

  /* MECKLY_NATIVE_POPUP_SOLID_V1 — solid on this side too. The light
     theme's --bg2/3/4 are opaque already, but the token exists so the
     one rule below never has to know which theme it is in. */
  --popup-bg:#FFFFFF;

  /* MECKLY_WHITE_BG_V1: she said the cool grey canvas fill everywhere
     reads as cold/muddy, wants plain white instead. */
  --bg0:#FFFFFF;
  --bg1:#FFFFFF;
  /* MECKLY_OFFWHITE_CARDS_V1: same complaint extended to card/section
     backgrounds — was a navy-tinted overlay reading as cool grey, now
     solid warm off-white tones instead. */
  --bg2:#FAFAF9;
  --bg3:#F5F4F1;
  --bg4:#EDEBE6;

  --txt:#10192B;
  --txt2:rgba(16,25,43,.82);
  /* JOBCARD_LEDGER_V1 — 31 Aug 2026, her ask: no grey anywhere in the
     light theme. muted/faint/border tokens were rgba(navy, opacity) —
     same real opacity values already WCAG-audited below (see
     MECKLY_LIGHT_THEME_CONTRAST_V2 / MECKLY_CONTRAST_AUDIT_V1 history),
     just the underlying colour swapped from navy (16,25,43) to charcoal
     (36,36,36) = #242424, so none of the prior contrast tuning work is
     lost, only the hue changes. */
  --muted:rgba(36,36,36,.80);
  --faint:rgba(36,36,36,.63); /* JOBCARD_LEDGER_V1 — .62 (the direct navy->charcoal carry-over) came out to 4.48:1, just under WCAG AA; bumped one point to .63 (4.61:1), real computed fix same as the prior navy-based one this replaces */

  --bd:rgba(36,36,36,.14);
  --bd2:rgba(36,36,36,.22);
  --bd3:rgba(36,36,36,.34);
  /* MECKLY_VISIBLE_OUTLINE_V1 — .22 (the value --bd2 carries) is
     1.55:1 here; .52 is 3.23:1 on --bg3 and 3.32:1 on white. */
  --btn-bd:rgba(36,36,36,.52);

  --surface-1:#FFFFFF;
  --surface-2:#F7F9FC;

  /* ══════════════════════════════════════════════════════════════
     MECKLY_A_BADGE_HAS_TO_BE_READABLE_V1 — 2 Oct 2026, her report on
     the Staff page: "this staff page is shocking, look at that green,
     and can you look if that green appears anywhere else and replace it
     with something visible on both light and dark theme."

     She was right, and it was not one page. The semantic inks here were
     chosen for the DARK theme and the light theme only ever darkened
     ONE of them. Measured as they are actually painted — the ink on a
     10% wash of itself, which is the .mu-badge-* pattern used across
     the app — the light theme was:

         --green on --green-s   3.95:1   (the darkened one, still short)
         --red   on --red-s     2.87:1
         --amber on --amber-s   1.82:1

     4.5:1 is the AA line for text this size. Amber at 1.82 is not "a
     bit low"; it is a label nobody can read.

     JOBCARD_LEDGER_V1 picked #028A0F for light green and computed it
     against WHITE (4.52:1), which it clears. What it did not check is
     the wash these badges actually sit on, where it does not. So green
     moves one step darker and red and amber get the same treatment they
     should have had then.

     Every value below clears 4.5:1 BOTH on its own 10% wash AND on the
     plain card — computed, not eyeballed, and held by
     test/a-badge-has-to-be-readable.mjs. The dark theme is untouched:
     it was never the problem. */
  --green:#046b11;
  --green-s:rgba(4,107,17,.10);
  --green-b:rgba(4,107,17,.25);
  /* white clears AA against #046b11 comfortably; #04200f (dark theme's
     --on-green) would not, which is why this override exists. */
  --on-green:#fff;

  --red:#b91c1c;
  --red-s:rgba(185,28,28,.10);
  --red-b:rgba(185,28,28,.28);

  --amber:#9a4f04;
  --amber-s:rgba(154,79,4,.10);
  --amber-b:rgba(154,79,4,.25);
}
/* Sidebar/drawer/toast surfaces are solid panels, not glass over the
   canvas colour, so they need a visible border in light mode where the
   dark theme relied on brightness contrast alone. */
:root[data-theme="light"] .mu-sidebar,
:root[data-theme="light"] .sidebar{
  box-shadow:1px 0 0 var(--bd);
}
:root[data-theme="light"] .mu-drawer,
:root[data-theme="light"] .drawer{
  box-shadow:-1px 0 0 var(--bd),-24px 0 64px rgba(16,25,43,.18);
}
:root[data-theme="light"] #toast{
  box-shadow:0 12px 32px rgba(16,25,43,.18);
}
