/* ATF Workflow CRM — desktop-first shell, fully responsive to 360px.
   ------------------------------------------------------------------
   Palette is derived from the company logo: brand blue #0001E5 and brand
   green #006400 (sampled from ATF Logo with Name.png).

   The logo blue is the ACCENT (active nav, primary CTA, focus). --brand is a
   slightly softened blue for calm, professional interactive surfaces; the true
   logo blue is --brand-strong (the mark, key CTAs, the active-nav rule). The
   sidebar is a refined neutral slate, on screen all day. Green is the
   Done/success colour; amber is Pending. Professional/minimal (19 Jul).

   Every colour below is a token so the night theme is a re-declaration, not a
   second stylesheet. */

:root {
  /* --- brand ------------------------------------------------------- */
  /* Brand blue is the accent, used sparingly (active nav, primary CTA, focus).
     A softer working blue carries most interactive surfaces so the interface
     reads calm and professional rather than saturated. */
  --brand:        #2547d0;
  --brand-strong: #0001E5;      /* the true logo blue, for the mark and key CTAs */
  --brand-ink:    #ffffff;
  --brand-dark:   #1a37ad;
  --brand-soft:   #eef1fb;
  --green:        #1f7a44;
  --green-soft:   #e9f4ec;

  /* --- sidebar (refined neutral slate — classy, not purple) --------- */
  --side-bg:      #1a2130;
  --side-bg-2:    #141a26;
  --side-ink:     #c3c9d6;
  --side-ink-dim: #838da0;
  --side-hover:   #232c3d;
  --side-active:  #2a3345;
  --side-active-ink: #ffffff;
  --side-active-bar: var(--brand-strong);

  /* --- surfaces ---------------------------------------------------- */
  --bg:           #f5f6f8;
  --card:         #ffffff;
  --card-2:       #f7f8fa;
  --line:         #e8eaf0;
  --line-strong:  #d6dae4;

  /* --- text -------------------------------------------------------- */
  --ink:          #1f2430;
  --ink-soft:     #5a6072;
  /* Was #949aa8 — 2.82:1 on white, which fails AA (4.5:1) and even the 3:1
     large-text floor. It is not decorative: it carries every form hint in the
     app and the notification-panel group labels (Past 7 days / Today / Next 7),
     which are the only non-colour carrier of a notification's urgency. */
  --ink-faint:    #6b7280;

  /* --- status ------------------------------------------------------ */
  --ok:           var(--green);
  --ok-bg:        var(--green-soft);
  --ok-line:      #bfe0c8;
  --warn:         #8a5a00;
  --warn-bg:      #fbf1dc;
  --warn-line:    #ecd3a0;
  --danger:       #c0271e;
  --danger-bg:    #fcece9;
  --danger-line:  #f0c6c0;
  --info:         #1a4f9c;
  --info-bg:      #eaf1fb;
  --info-line:    #c4d8f2;

  /* --- action button colours (refined) ----------------------------- */
  --btn-blue:   #2b5bd7;
  --btn-yellow: #c98a00;
  --btn-red:    #cf3b2e;
  --btn-green:  #1f7a44;
  --btn-grey:   #626a78;

  /* --- geometry — crisper, more minimal ---------------------------- */
  --radius:     8px;
  --radius-sm:  6px;
  --tap:        44px;
  --sidebar-w:  226px;
  --topbar-h:   58px;
  --shadow:     0 1px 2px rgba(20, 26, 38, .05), 0 1px 3px rgba(20, 26, 38, .04);
  --shadow-lg:  0 12px 34px rgba(20, 26, 38, .16);
  /* The app sets `outline: none` on buttons, action icons, the theme toggle and
     every input, so this halo is the ONLY focus indicator a keyboard user gets.
     At .2 alpha it composited to 1.39:1 — invisible, and well under the 3:1
     WCAG 1.4.11 needs for a non-text indicator. */
  --ring:       0 0 0 3px rgba(37, 71, 208, .55);
}

/* ---------------- night theme ----------------
   Declared for both the OS preference and an explicit [data-theme], because
   the toggle must be able to override the OS in BOTH directions — someone on a
   dark laptop who wants the light CRM is not an edge case. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { color-scheme: dark; }
}
:root[data-theme="dark"] { color-scheme: dark; }
/* Explicit, not merely absent: for OS=dark + user-picks-Light this would
   otherwise compute to `normal`, leaving the native select popup, date picker
   and scrollbars to the UA's default guess rather than the theme's choice. */
:root[data-theme="light"] { color-scheme: light; }

/* refined dark tokens — the same values under the explicit toggle and the OS
   preference (declared twice below; kept in sync deliberately). */
:root[data-theme="dark"] {
  --brand:        #6d8bff;
  --brand-strong: #8ba0ff;
  --brand-ink:    #0b0e16;
  --brand-dark:   #9db0ff;
  --brand-soft:   #1c2333;
  --green:        #4cc76a;
  --green-soft:   #123020;

  --side-bg:      #10141c;
  --side-bg-2:    #0b0e14;
  --side-ink:     #b8bfcc;
  --side-ink-dim: #71798a;
  --side-hover:   #1a1f29;
  --side-active:  #232a36;
  --side-active-ink: #ffffff;
  --side-active-bar: var(--brand-strong);

  --bg:           #0e1116;
  --card:         #161a21;
  --card-2:       #1b2029;
  --line:         #262b34;
  --line-strong:  #363c48;

  --ink:          #e4e7ec;
  --ink-soft:     #a1a8b5;
  --ink-faint:    #9aa3b2;   /* was #767d8b — 4.22:1, short of AA */

  --ok: #4cc76a;      --ok-bg: #123020;      --ok-line: #245c33;
  --warn: #e0a94a;    --warn-bg: #2f2610;    --warn-line: #5f4b1e;
  --danger: #ff7a70;  --danger-bg: #351512;  --danger-line: #6f2e29;
  --info: #71a8f5;    --info-bg: #10233f;    --info-line: #274a75;

  --btn-blue: #3a6bea; --btn-yellow: #b7860a; --btn-red: #d9483b;
  --btn-green: #2a9d4f; --btn-grey: #5b6270;

  --shadow:    0 1px 2px rgba(0, 0, 0, .45), 0 2px 8px rgba(0, 0, 0, .3);
  --shadow-lg: 0 12px 34px rgba(0, 0, 0, .6);
  --ring:      0 0 0 3px rgba(109, 139, 255, .6);   /* was .28 — 1.54:1 */
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --brand:        #6d8bff;
    --brand-strong: #8ba0ff;
    --brand-ink:    #0b0e16;
    --brand-dark:   #9db0ff;
    --brand-soft:   #1c2333;
    --green:        #4cc76a;
    --green-soft:   #123020;

    --side-bg:      #10141c;
    --side-bg-2:    #0b0e14;
    --side-ink:     #b8bfcc;
    --side-ink-dim: #71798a;
    --side-hover:   #1a1f29;
    --side-active:  #232a36;
    --side-active-ink: #ffffff;
    --side-active-bar: var(--brand-strong);

    --bg:           #0e1116;
    --card:         #161a21;
    --card-2:       #1b2029;
    --line:         #262b34;
    --line-strong:  #363c48;

    --ink:          #e4e7ec;
    --ink-soft:     #a1a8b5;
    --ink-faint:    #9aa3b2;   /* was #767d8b — 4.22:1, short of AA */

    --ok: #4cc76a;      --ok-bg: #123020;      --ok-line: #245c33;
    --warn: #e0a94a;    --warn-bg: #2f2610;    --warn-line: #5f4b1e;
    --danger: #ff7a70;  --danger-bg: #351512;  --danger-line: #6f2e29;
    --info: #71a8f5;    --info-bg: #10233f;    --info-line: #274a75;

    --btn-blue: #3a6bea; --btn-yellow: #b7860a; --btn-red: #d9483b;
    --btn-green: #2a9d4f; --btn-grey: #5b6270;

    --shadow:    0 1px 2px rgba(0, 0, 0, .45), 0 2px 8px rgba(0, 0, 0, .3);
    --shadow-lg: 0 12px 34px rgba(0, 0, 0, .6);
    --ring:      0 0 0 3px rgba(109, 139, 255, .6);   /* was .28 — 1.54:1 */
  }
}

/* ================= base ================= */
*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  /* A refined, professional sans stack. Segoe UI on Windows reads clean and
     businesslike; the rest are graceful fallbacks. */
  font-family: "Segoe UI", system-ui, -apple-system, "Inter", Roboto, "Helvetica Neue", Arial, sans-serif;
  font-size: 14.5px;
  line-height: 1.55;
  letter-spacing: .1px;
  color: var(--ink);
  background: var(--bg);
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* The shell never scrolls sideways. Wide content scrolls inside its own
     container instead — a page-level horizontal scroll on a phone is the
     "scroll trap" that makes a table impossible to read. */
  overflow-x: hidden;
}

a { color: var(--brand); }

h1 { font-size: 1.28rem; margin: 0 0 14px; font-weight: 600; }
h2 { font-size: 1.05rem; margin: 24px 0 10px; font-weight: 600; }
h3 { font-size: .95rem; margin: 18px 0 8px; font-weight: 600; }
.sub { color: var(--ink-soft); font-size: .87rem; margin: -8px 0 16px; }

/* ================= app shell ================= */
.app { display: flex; min-height: 100vh; }

/* ---- sidebar ---- */
.sidebar {
  position: fixed; inset: 0 auto 0 0; z-index: 60;
  width: var(--sidebar-w);
  background: var(--side-bg);
  color: var(--side-ink);
  display: flex; flex-direction: column;
  overflow-y: auto; overscroll-behavior: contain;
}
.sidebar-brand {
  display: flex; align-items: center; gap: 10px;
  height: var(--topbar-h); flex: none;
  padding: 0 14px;
  background: var(--side-bg-2);
  color: #fff; text-decoration: none;
  font-weight: 600; letter-spacing: .02em;
}
.sidebar-brand img { height: 26px; width: auto; display: block; }

.nav { padding: 6px 0 26px; }
.nav a, .nav .nav-group-btn {
  display: flex; align-items: center; gap: 9px;
  width: 100%; min-height: 42px; padding: 9px 15px;
  color: var(--side-ink); text-decoration: none;
  font-size: .89rem; font-weight: 500;
  background: none; border: 0; text-align: left; cursor: pointer;
  font-family: inherit;
}
.nav a:hover, .nav .nav-group-btn:hover { background: var(--side-hover); color: #fff; }
/* Active item: a subtle fill with a brand-blue rule down the left — a restrained,
   professional highlight rather than a solid saturated block. */
.nav a.active {
  background: var(--side-active); color: var(--side-active-ink); font-weight: 600;
  box-shadow: inset 3px 0 0 var(--side-active-bar);
}
.nav .nav-group-btn .chev {
  margin-left: auto; font-size: .7rem; transition: transform .18s ease; opacity: .8;
}
.nav .nav-group-btn[aria-expanded="true"] .chev { transform: rotate(180deg); }

/* Sub-items sit slightly inset with a rule, matching the reference CRM. */
.nav-sub { display: none; background: var(--side-bg-2); }
.nav-sub.open { display: block; }
.nav-sub a {
  padding-left: 30px; font-size: .85rem; font-weight: 400;
  color: var(--side-ink-dim); min-height: 38px;
}
.nav-sub a::before { content: "–"; margin-right: 6px; opacity: .6; }
.nav-sub a.active { color: var(--side-active-ink); }

/* A section this user may see but not act in. */
.nav a.readonly { opacity: .55; }
.nav a.readonly::after { content: "👁"; margin-left: auto; font-size: .75em; }

/* ---- topbar ---- */
.topbar {
  position: sticky; top: 0; z-index: 40;
  height: var(--topbar-h); flex: none;
  display: flex; align-items: center; gap: 10px;
  padding: 0 16px;
  background: var(--card);
  border-bottom: 1px solid var(--line);
}
/* Three zones: left (menu + title), a centred brand mark, right (controls).
   The left and right zones flex equally so the logo sits truly centred. */
.topbar-left  { flex: 1 1 0; min-width: 0; display: flex; align-items: center; gap: 10px; }
.topbar-right { flex: 1 1 0; min-width: 0; display: flex; align-items: center; justify-content: flex-end; gap: 8px; }
.topbar-title {
  font-weight: 600; font-size: .98rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.topbar-logo {
  flex: none; display: inline-flex; align-items: center;
  height: 100%; padding: 8px 4px;
}
.topbar-logo img { height: 30px; width: auto; display: block; }

.user-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 11px; border-radius: 999px;
  background: var(--brand-soft); color: var(--brand);
  font-size: .8rem; font-weight: 600; cursor: pointer;
  max-width: 34vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  list-style: none;
}
.user-chip::-webkit-details-marker { display: none; }
.user-chip .caret { font-size: .7em; opacity: .8; }
.user-chip .chip-icon { display: none; }   /* shown only on mobile */

/* Account / logout dropdown */
.menu { position: relative; }
.menu > summary { user-select: none; }
.menu[open] > summary { box-shadow: var(--ring); border-radius: 999px; }
.menu-panel {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 70;
  min-width: 180px; padding: 6px;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow-lg);
}
.menu-head { padding: 8px 10px 10px; border-bottom: 1px solid var(--line); margin-bottom: 6px; }
.menu-name { font-weight: 700; font-size: .88rem; }
.menu-role { font-size: .76rem; color: var(--ink-soft); }
.menu-item {
  display: flex; align-items: center; gap: 8px;
  padding: 9px 10px; border-radius: var(--radius-sm);
  text-decoration: none; color: var(--ink); font-size: .86rem; font-weight: 600;
}
.menu-item:hover { background: var(--card-2); }
.menu-item.danger { color: var(--danger); }
.menu-item.danger:hover { background: var(--danger-bg); }
.icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; flex: none;
  border: 1px solid transparent; border-radius: var(--radius-sm);
  background: none; color: var(--ink-soft); cursor: pointer;
  font-size: 1.05rem; line-height: 1; text-decoration: none;
}
.icon-btn:hover { background: var(--card-2); color: var(--ink); border-color: var(--line); }
.icon-btn:focus-visible { outline: none; box-shadow: var(--ring); }
.bell { position: relative; }
.bell-count {
  position: absolute; top: 1px; right: 0;
  min-width: 16px; height: 16px; padding: 0 4px;
  border-radius: 999px; background: var(--danger); color: #fff;
  font-size: .62rem; font-weight: 800; line-height: 16px; text-align: center;
}

/* Theme toggle: a sliding track whose knob carries the sun/moon. */
.theme-toggle {
  position: relative; width: 58px; height: 30px; flex: none;
  border-radius: 999px; border: 1px solid var(--line-strong);
  background: linear-gradient(90deg, #cfe3ff, #eef3ff);
  cursor: pointer; padding: 0;
  transition: background .3s ease;
}
:root[data-theme="dark"] .theme-toggle,
:root:not([data-theme="light"]) .theme-toggle {
  background: linear-gradient(90deg, #14183a, #232a55);
}
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .theme-toggle {
    background: linear-gradient(90deg, #cfe3ff, #eef3ff);
  }
}
.theme-toggle .knob {
  position: absolute; top: 2px; left: 2px;
  width: 24px; height: 24px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 4px rgba(0,0,0,.3);
  display: flex; align-items: center; justify-content: center;
  font-size: .8rem; line-height: 1;
  transition: transform .3s cubic-bezier(.4, 1.4, .5, 1), background .3s ease;
}
.theme-toggle[aria-pressed="true"] .knob { transform: translateX(28px); background: #2b2f55; }
.theme-toggle:focus-visible { outline: none; box-shadow: var(--ring); }

.hamburger { display: none; }

/* ---- main ---- */
.main {
  flex: 1; min-width: 0;                /* min-width:0 lets tables shrink */
  margin-left: var(--sidebar-w);
  display: flex; flex-direction: column;
}
.content { flex: 1; padding: 20px 22px 56px; max-width: 1500px; width: 100%; }
.foot {
  padding: 14px 22px; border-top: 1px solid var(--line);
  color: var(--ink-faint); font-size: .76rem;
}

.scrim {
  display: none;
  position: fixed; inset: 0; z-index: 50;
  background: rgba(10, 10, 30, .5);
}
.scrim.open { display: block; }

/* ================= cards ================= */
.card {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 18px;
  box-shadow: var(--shadow); margin-bottom: 16px;
}
.card-head {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-bottom: 14px;
}
.card-head h1, .card-head h2 { margin: 0; }
.card-head .spacer { flex: 1; }

/* Card tints. These exist so no screen has to hardcode one.
   Several Phase 0-4 screens set `style="background:#f2fbf5"` (and #fffaf0,
   #fbfcfd) inline. An inline style beats every rule in this file, so the
   legacy-class compat block near the bottom could not reach them and those
   screens rendered near-white text on near-white cards in the dark theme —
   the upload dropzone, the parsed-PO review, the sticker config and the MTC
   certify screen were all unreadable. Use these instead of a literal colour. */
.card-ok    { background: var(--ok-bg);   border-color: var(--ok-line); }
.card-warn  { background: var(--warn-bg); border-color: var(--warn-line); }
.card-muted { background: var(--bg); }
.card-off   { background: var(--bg); opacity: .75; }

.page-head {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 16px;
}
.page-head .spacer { flex: 1; }

/* ================= buttons ================= */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  min-height: 40px; padding: 8px 16px;
  border-radius: var(--radius-sm); border: 1px solid var(--line-strong);
  background: var(--card); color: var(--ink);
  font-size: .88rem; font-weight: 600; font-family: inherit;
  text-decoration: none; cursor: pointer; white-space: nowrap;
}
.btn:hover { background: var(--card-2); }
.btn:focus-visible { outline: none; box-shadow: var(--ring); }
.btn:disabled, .btn[aria-disabled="true"] { opacity: .5; cursor: not-allowed; }
.btn-primary { background: var(--brand-strong); border-color: var(--brand-strong); color: var(--brand-ink); }
.btn-primary:hover { background: var(--brand-dark); border-color: var(--brand-dark); }
.btn-green { background: var(--btn-green); border-color: var(--btn-green); color: #fff; }
.btn-danger { background: var(--card); border-color: var(--danger-line); color: var(--danger); }
.btn-danger:hover { background: var(--danger-bg); }
.btn-grey { background: var(--btn-grey); border-color: var(--btn-grey); color: #fff; }
.btn-sm { min-height: 33px; padding: 5px 11px; font-size: .8rem; }
.btn-row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }

/* Square colour-coded action buttons, as in the reference CRM's Actions column. */
.act {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 30px; flex: none;
  border: 0; border-radius: 5px; cursor: pointer;
  color: #fff; font-size: .82rem; line-height: 1; text-decoration: none;
  font-family: inherit;
}
.act:focus-visible { outline: none; box-shadow: var(--ring); }
.act-blue   { background: var(--btn-blue); }
.act-yellow { background: var(--btn-yellow); }
.act-red    { background: var(--btn-red); }
.act-green  { background: var(--btn-green); }
.act-grey   { background: var(--btn-grey); }
.act:hover { filter: brightness(1.1); }
.act-group { display: flex; gap: 5px; flex-wrap: wrap; }

/* ================= forms ================= */
.field { margin-bottom: 14px; min-width: 0; }
.field > label {
  display: block; font-size: .78rem; font-weight: 600;
  color: var(--ink-soft); margin-bottom: 5px;
}
.field .req { color: var(--danger); }
.field .hint { font-size: .75rem; color: var(--ink-faint); margin-top: 4px; font-weight: 400; }

input[type=text], input[type=password], input[type=number], input[type=search],
input[type=date], input[type=email], input[type=tel], select, textarea {
  width: 100%; min-height: 40px; padding: 8px 11px;
  border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  background: var(--card); color: var(--ink);
  font: inherit; font-size: 16px;      /* 16px stops iOS zoom-on-focus */
}
@media (min-width: 700px) {
  input[type=text], input[type=password], input[type=number], input[type=search],
  input[type=date], input[type=email], input[type=tel], select, textarea { font-size: .9rem; }
}
textarea { min-height: 80px; resize: vertical; }
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--brand); box-shadow: var(--ring);
}
input:disabled, select:disabled, textarea:disabled, input[readonly] {
  background: var(--card-2); color: var(--ink-soft); cursor: not-allowed;
}
select { appearance: none; background-image: none; padding-right: 30px; }
.select-wrap { position: relative; }
.select-wrap::after {
  content: "▾"; position: absolute; right: 11px; top: 50%;
  transform: translateY(-50%); pointer-events: none; color: var(--ink-soft); font-size: .8rem;
}

.grid { display: grid; gap: 0 16px; grid-template-columns: 1fr; }
@media (min-width: 640px)  { .grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 900px)  { .grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1100px) { .grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.check { display: flex; align-items: center; gap: 9px; min-height: 34px; cursor: pointer; }
.check input[type=checkbox] { width: 18px; height: 18px; accent-color: var(--brand); flex: none; }
.check span { font-size: .87rem; }
.check.disabled { opacity: .5; cursor: not-allowed; }

/* ================= tables ================= */
/* The wrapper is the ONLY thing allowed to scroll sideways. */
.table-wrap {
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--card);
}
table { width: 100%; border-collapse: collapse; font-size: .86rem; }
/* Full grid lines and centred text on every list (user preference, 19 Jul) —
   matches the reference CRM's tabular look. */
thead th {
  background: var(--card-2); color: var(--ink);
  font-size: .76rem; font-weight: 700; text-transform: none;
  text-align: center; white-space: nowrap;
  padding: 11px 10px; border: 1px solid var(--line-strong);
}
tbody td {
  padding: 11px 10px; border: 1px solid var(--line);
  text-align: center; vertical-align: middle;
}
tbody tr:hover { background: var(--card-2); }
/* Lists are centred throughout (user preference); `.left` no longer left-aligns
   a table cell. Numbers still right-align for readable columns of figures. */
/* All list tables are centred (user preference, 19 Jul), so `.left` no longer
   left-aligns. But `text-align` INHERITS into form controls, and two of these
   cells contain text inputs — the Add Quotation description and comment fields,
   which take up to 2000 characters. Typing a long description that grows
   outward from the middle of the field is unusable, so inputs opt back out.
   Numeric cells re-align right through their own .c-qty/.c-cost/... rules. */
td.left, th.left { text-align: center; }
td.left input, td.left textarea { text-align: left; }
td.num { text-align: right; font-variant-numeric: tabular-nums; }
.mono { font-family: ui-monospace, "Cascadia Mono", Menlo, Consolas, monospace; font-size: .92em; }

/* The per-column search row. */
tr.filters th { background: var(--card); padding: 8px 8px; border-bottom: 1px solid var(--line); }
tr.filters input, tr.filters select { min-height: 34px; font-size: .82rem; padding: 5px 8px; }
tr.filters .clear-filters {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 5px;
  background: var(--btn-blue); color: #fff; border: 0; cursor: pointer;
  font-weight: 700; line-height: 1;
}

/* A soft-deleted row: struck through, dimmed, with who did it. */
tr.deleted td { opacity: .62; text-decoration: line-through; }
tr.deleted td.no-strike { text-decoration: none; }
.deleted-by { font-size: .72rem; color: var(--danger); display: block; text-decoration: none; }

/* A row needing attention — a salesperson with a missing daily report, a
   below-threshold DeskTrack day. Built on the existing --warn-bg token, which
   is declared in all three theme blocks, rather than a new custom property: an
   undefined property falls back to currentColor and silently loses its colour.
   `:hover` is restated or the generic tbody hover would erase the tint. */
tr.row-warn td { background: var(--warn-bg); }
tbody tr.row-warn:hover td { background: var(--warn-bg); filter: brightness(.97); }

.empty { text-align: center; padding: 44px 20px; color: var(--ink-soft); }
.empty .big { font-size: 2rem; margin-bottom: 8px; opacity: .55; }

/* ================= chips / badges ================= */
.chip {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 10px; border-radius: 999px;
  font-size: .74rem; font-weight: 700; white-space: nowrap;
  border: 1px solid var(--line); background: var(--card-2); color: var(--ink-soft);
}
.chip-done    { background: var(--ok-bg);     color: var(--ok);     border-color: var(--ok-line); }
.chip-pending { background: var(--warn-bg);   color: var(--warn);   border-color: var(--warn-line); }
.chip-danger  { background: var(--danger-bg); color: var(--danger); border-color: var(--danger-line); }
.chip-info    { background: var(--info-bg);   color: var(--info);   border-color: var(--info-line); }
.chip-brand   { background: var(--brand-soft); color: var(--brand); border-color: var(--brand); }
.chips { display: flex; flex-wrap: wrap; gap: 8px; }
a.chip { text-decoration: none; }
a.chip:hover { background: var(--card-2); }
.badge-count {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--brand); color: var(--brand-ink);
  padding: 6px 13px; border-radius: 6px; font-size: .82rem; font-weight: 700;
}

/* ================= alerts ================= */
.alert {
  padding: 11px 14px; border-radius: var(--radius-sm);
  font-size: .86rem; margin-bottom: 14px; border: 1px solid;
}
.alert-error { background: var(--danger-bg); border-color: var(--danger-line); color: var(--danger); }
.alert-info  { background: var(--info-bg);   border-color: var(--info-line);   color: var(--info); }
.alert-warn  { background: var(--warn-bg);   border-color: var(--warn-line);   color: var(--warn); }
.alert-ok    { background: var(--ok-bg);     border-color: var(--ok-line);     color: var(--ok); }

/* ================= modals ================= */
.modal-back {
  position: fixed; inset: 0; z-index: 90;
  background: rgba(10, 10, 30, .55);
  display: flex; align-items: center; justify-content: center;
  padding: 16px; overflow-y: auto;
}
.modal-back[hidden] { display: none; }
.modal {
  background: var(--card); border-radius: var(--radius);
  box-shadow: var(--shadow-lg); width: 100%; max-width: 520px;
  max-height: calc(100vh - 32px); overflow-y: auto;
  padding: 22px;
}
.modal.wide { max-width: 860px; }
.modal h2 { margin: 0 0 16px; font-size: 1.08rem; }
.modal-actions {
  display: flex; gap: 9px; justify-content: flex-start; align-items: center;
  margin-top: 18px; flex-wrap: wrap;
}

/* ================= masters sub-nav ================= */
.with-subnav { display: flex; gap: 20px; align-items: flex-start; }
.subnav {
  flex: none; width: 190px;
  display: flex; flex-direction: column; gap: 2px;
  position: sticky; top: calc(var(--topbar-h) + 16px);
}
.subnav a {
  padding: 9px 13px; border-radius: var(--radius-sm);
  text-align: center; text-decoration: none;
  color: var(--ink); font-size: .85rem; font-weight: 500;
}
.subnav a:hover { background: var(--card-2); }
.subnav a.active { background: var(--brand-soft); color: var(--brand); font-weight: 700; }
.subnav-body { flex: 1; min-width: 0; }

/* ================= mini tabs ================= */
.tabs {
  display: flex; gap: 2px; border-bottom: 1px solid var(--line);
  margin-bottom: 16px; overflow-x: auto; -webkit-overflow-scrolling: touch;
}
.tabs a {
  padding: 9px 15px; text-decoration: none; white-space: nowrap;
  color: var(--brand); font-size: .87rem;
  border: 1px solid transparent; border-bottom: 0;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}
.tabs a.active {
  background: var(--card); color: var(--ink); font-weight: 600;
  border-color: var(--line); margin-bottom: -1px;
}

/* ================= key/value ================= */
.kv { display: grid; grid-template-columns: minmax(110px, 160px) 1fr; gap: 8px 16px; font-size: .88rem; }
.kv dt { color: var(--ink-soft); font-size: .8rem; font-weight: 600; }
.kv dd { margin: 0; word-break: break-word; }

/* ================= loader ================= */
/* Shown on login and while a slow page is fetched. The mark scales gently and
   a brand-coloured bar sweeps beneath it. */
.loader-wrap {
  position: fixed; inset: 0; z-index: 200;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 20px;
  background: var(--bg);
  transition: opacity .35s ease, visibility .35s ease;
}
.loader-wrap.hide { opacity: 0; visibility: hidden; }
.loader-logo { width: 118px; height: auto; animation: atf-pulse 1.5s ease-in-out infinite; }
.loader-bar {
  width: 190px; height: 4px; border-radius: 999px;
  background: var(--line); overflow: hidden; position: relative;
}
.loader-bar::after {
  content: ""; position: absolute; inset: 0;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--brand), var(--green), var(--brand));
  transform: translateX(-100%);
  animation: atf-sweep 1.15s ease-in-out infinite;
}
.loader-text { color: var(--ink-soft); font-size: .82rem; letter-spacing: .04em; }
@keyframes atf-pulse {
  0%, 100% { transform: scale(1);    opacity: 1; }
  50%      { transform: scale(1.07); opacity: .82; }
}
@keyframes atf-sweep {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(100%); }
}

/* ================= login ================= */
.login-page {
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  padding: 20px; background: var(--bg);
}
.login-card {
  width: 100%; max-width: 400px; background: var(--card);
  border: 1px solid var(--line); border-radius: 14px;
  box-shadow: var(--shadow-lg); padding: 30px 26px;
}
.login-logo { text-align: center; margin-bottom: 22px; }
.login-logo img { width: 158px; height: auto; }

/* ================= theme-aware logo ================= */
/* The artwork ships in two cuts (see scripts/make_logo_assets.py): brand blue
   for light surfaces, white-and-green reversed for dark ones. Both are in the
   markup and CSS picks; swapping the `src` in JS would flash the wrong cut on
   first paint. The sidebar always uses the reversed cut — it is navy in both
   themes. */
.logo-dark { display: none; }
.logo-light { display: inline-block; }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .logo-light { display: none; }
  :root:not([data-theme="light"]) .logo-dark  { display: inline-block; }
}
:root[data-theme="dark"] .logo-light { display: none; }
:root[data-theme="dark"] .logo-dark  { display: inline-block; }
:root[data-theme="light"] .logo-light { display: inline-block; }
:root[data-theme="light"] .logo-dark  { display: none; }

/* ================= utilities ================= */
.regret { color: var(--danger); font-style: italic; font-weight: 700; }

/* notifications — full page list */
.notif-list { padding: 4px 0; }
.notif { display: flex; align-items: center; gap: 10px; padding: 10px 14px; border-bottom: 1px solid var(--line); }
.notif:last-child { border-bottom: 0; }
.notif-body { flex: 1; min-width: 0; display: flex; flex-direction: column; text-decoration: none; }
.notif-title { font-weight: 600; color: var(--ink); }
.notif-title:hover { color: var(--brand); }

/* notifications — bell dropdown panel */
.bell-menu .menu-panel.notif-panel {
  width: 340px; max-width: 90vw; padding: 0;
  max-height: 70vh; overflow-y: auto; overscroll-behavior: contain;
}
@media (max-width: 420px) { .bell-menu .menu-panel.notif-panel { width: 300px; } }
.notif-panel-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 11px 14px; border-bottom: 1px solid var(--line);
  position: sticky; top: 0; background: var(--card); z-index: 1;
}
.notif-panel-body { padding: 4px 0 6px; }
.notif-group-label {
  font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  color: var(--ink-faint); padding: 8px 14px 3px;
}
.notif-empty { padding: 26px 14px; text-align: center; }
.dot { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.dot-red { background: var(--danger); }
.dot-green { background: var(--ok); }
.dot-blue { background: var(--info); }
.dot-grey { background: var(--ink-faint); }
.notif-tick {
  flex: none; width: 26px; height: 26px; border-radius: 6px;
  border: 1px solid var(--ok-line); background: var(--ok-bg); color: var(--ok);
  cursor: pointer; font-weight: 800; line-height: 1;
}
.notif-tick:hover { background: var(--ok); color: #fff; }
.notif-tick.blocked { border-color: var(--warn-line); background: var(--warn-bg); color: var(--warn); }
/* A Work-Order notice whose tick the server will refuse until the real step is
   done. Marked up front so it does not look like an ordinary dismissible row. */
.notif-tick-action { border-color: var(--info-line); background: var(--info-bg); color: var(--info); }
.notif-tick-action:hover { background: var(--info); color: #fff; }
/* The refusal, shown in the row. A title tooltip alone is invisible: the
   pointer has already left the button by the time the response lands. */
.notif-blocked-msg {
  flex-basis: 100%; margin: 6px 0 0; padding: 6px 8px;
  border-radius: var(--radius-sm);
  background: var(--warn-bg); color: var(--warn);
  font-size: .78rem; line-height: 1.4;
}
/* Shown when another user changed something but this page has unsaved input,
   so refreshing automatically would throw that input away. */
/* Who ticked a department, and that department's remark, under the Done chip
   on the dashboard. Small and quiet — the chip is the signal, these are detail. */
/* ================= charts (inline SVG, no library) ================= */
/* Theme tokens, not baked-in hex: a chart with hardcoded fills is the same bug
   that made four screens unreadable in dark mode. */
.chart-row { display: flex; gap: 18px; align-items: center; flex-wrap: wrap; }
.chart-total { font-size: 20px; font-weight: 700; fill: var(--ink); }
.chart-caption { font-size: 9px; fill: var(--ink-soft); }
.slice-1 { stroke: var(--warn); }     /* Pending */
.slice-2 { stroke: var(--info); }     /* Partial */
.slice-3 { stroke: var(--ok); }       /* Dispatched */
.chart-legend { list-style: none; margin: 0; padding: 0; font-size: .84rem; }
.chart-legend li { display: flex; align-items: center; gap: 8px; margin: 4px 0; }
.chart-legend strong { margin-left: auto; }
.key { width: 11px; height: 11px; border-radius: 3px; display: inline-block; flex: none; }
.key-1 { background: var(--warn); }
.key-2 { background: var(--info); }
.key-3 { background: var(--ok); }

.chart-bars {
  display: flex; gap: 6px; align-items: flex-end;
  overflow-x: auto; padding-bottom: 4px;
  min-width: 0;          /* let the scroller actually scroll — see .grid2 > * */
}
.chart-row { min-width: 0; }
.chart-row svg { flex: none; max-width: 100%; height: auto; }
.bar-col { flex: 1 0 34px; display: flex; flex-direction: column; align-items: center; gap: 4px; }
/* On a phone, shrink the columns so all twelve months FIT rather than scroll.
   They scrolled before, which put the current month — the one anyone opening
   this screen is actually looking for — off the right-hand edge by default. */
@media (max-width: 560px) {
  .chart-bars { gap: 3px; }
  .bar-col { flex: 1 0 18px; }
  .bar-label { font-size: .6rem; transform: rotate(-45deg); transform-origin: center; }
}
.bar-track {
  width: 100%; height: var(--bar-h); display: flex; align-items: flex-end;
  background: var(--bg); border-radius: var(--radius-sm);
}
.bar-fill { width: 100%; background: var(--brand); border-radius: var(--radius-sm); min-height: 0; }
.bar-label { font-size: .68rem; color: var(--ink-soft); white-space: nowrap; }

/* A certificate that a re-issue replaced. Still downloadable — it may already
   be with the customer — but visibly no longer the live one. */
tr.is-superseded td { color: var(--ink-soft); }
tr.is-superseded td.mono { text-decoration: line-through; }

.dept-by { font-size: .72rem; color: var(--ink-soft); margin-top: 3px; }
.dept-remark {
  font-size: .72rem; color: var(--ink-soft); margin-top: 2px;
  font-style: italic; max-width: 150px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  margin-left: auto; margin-right: auto;
}
.remark-form { display: flex; gap: 6px; align-items: center; }
.remark-form input { min-width: 0; }
.modal-wide { max-width: 780px; width: 96vw; }

.stale-pill {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: 18px; z-index: 200;
  padding: 10px 16px; border-radius: 999px;
  border: 1px solid var(--brand); background: var(--brand); color: var(--brand-ink);
  font: inherit; font-size: .85rem; font-weight: 600;
  box-shadow: var(--shadow-lg); cursor: pointer;
}
.stale-pill:hover { background: var(--brand-dark); border-color: var(--brand-dark); }

.notif-more {
  display: block; padding: 10px 14px; text-align: center;
  border-top: 1px solid var(--line); color: var(--brand);
}
.muted { color: var(--ink-soft); }
.small { font-size: .8rem; }
.nowrap { white-space: nowrap; }
.right { text-align: right; }
.center { text-align: center; }
.mt0 { margin-top: 0; } .mb0 { margin-bottom: 0; }
.stack > * + * { margin-top: 12px; }
.hide { display: none !important; }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ==========================================================================
   RESPONSIVE
   ==========================================================================
   Two things change on a narrow screen: the sidebar becomes an off-canvas
   drawer behind a hamburger, and any table marked .cards collapses into one
   card per row. The card transform is CSS-only — each cell prints its own
   column heading from the data-label the template stamps on it — so it cannot
   fall out of step with a JS list of headings. */

@media (max-width: 1023px) {
  .sidebar {
    transform: translateX(-100%);
    transition: transform .25s ease;
    box-shadow: var(--shadow-lg);
  }
  .sidebar.open { transform: translateX(0); }
  .main { margin-left: 0; }
  .hamburger { display: inline-flex; }
  .content { padding: 16px 14px 48px; }

  /* The Masters sub-tabs stay a vertical list on mobile too (user preference,
     18 Jul) — a horizontal scroll strip hid the tabs off-screen.
     align-items:stretch is essential: the base rule uses flex-start (so the
     desktop subnav column doesn't stretch tall), but in this column layout
     flex-start makes .subnav-body shrink to the table's content width and push
     the page sideways. Stretch makes it fill the viewport so the table scrolls
     inside its own wrapper instead. */
  .with-subnav { flex-direction: column; gap: 12px; align-items: stretch; }
  .subnav {
    width: 100%; position: static;
    flex-direction: column; gap: 4px;
  }
  .subnav a { text-align: left; }
  .subnav-body { width: 100%; }
}

/* Mobile renders the SAME table layout as desktop (user preference, 18 Jul):
   no card transform. Wide tables scroll horizontally inside their own
   .table-wrap, so the page body still never scrolls sideways — the box does.
   `table.cards` is kept as a class name so existing markup is unchanged; it no
   longer triggers a card layout. */
@media (max-width: 767px) {
  body { font-size: 15px; }
  h1 { font-size: 1.14rem; }
  .card { padding: 14px; }
  table { font-size: .84rem; }
  th, td { padding: 9px 10px; }

  /* Compact the account control so the centred logo has room: show a person
     icon instead of the full name. The name and role stay in the dropdown. */
  .user-chip .chip-name, .user-chip .caret { display: none; }
  .user-chip .chip-icon { display: inline; font-size: 1rem; }
  .user-chip { padding: 6px 9px; max-width: none; }
}

/* 360px: the narrowest phone we support. The page never scrolls sideways; wide
   tables scroll within .table-wrap. */
@media (max-width: 400px) {
  .content { padding: 12px 10px 44px; }
  .card { padding: 12px; border-radius: 8px; }
  .btn { padding: 8px 12px; font-size: .84rem; }
  .btn-row { gap: 6px; }
  .user-chip { max-width: 26vw; }
  .topbar { padding: 0 8px; gap: 6px; }
  /* Free room for the centred logo and account chip on a phone: the page name
     is already the h1 just below, so the top-bar title is redundant here. */
  .topbar-title { display: none; }
  .topbar-logo img { height: 26px; }
  .modal { padding: 16px; }
  .kv { grid-template-columns: 1fr; gap: 2px 0; }
  .kv dd { margin-bottom: 8px; }
}

@media print {
  .sidebar, .topbar, .foot, .scrim, .act-group, .btn { display: none !important; }
  .main { margin-left: 0; }
  .card { box-shadow: none; border: 0; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important; animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}

/* ==========================================================================
   Phase 0-4 compatibility — theme-aware versions of the classes the Work Order,
   Parts, Stickers, Upload and MTC screens still use. These predate the CRM V2
   rewrite; defining them here (in tokens) keeps those screens styled and
   correct in BOTH themes instead of falling back to hardcoded light colours
   (which is why the WO Progress panel was invisible in dark mode).
   ========================================================================== */

.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch;
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--card); }

.badge {
  display: inline-block; padding: 2px 9px; border-radius: 999px;
  font-size: .72rem; font-weight: 700; white-space: nowrap;
  background: var(--card-2); color: var(--ink-soft); border: 1px solid var(--line);
}
.badge-ok     { background: var(--ok-bg);     color: var(--ok);     border-color: var(--ok-line); }
.badge-warn   { background: var(--warn-bg);   color: var(--warn);   border-color: var(--warn-line); }
.badge-danger { background: var(--danger-bg); color: var(--danger); border-color: var(--danger-line); }
.badge-304 { background: var(--warn-bg); color: var(--warn); border-color: var(--warn-line); }
.badge-316 { background: var(--danger-bg); color: var(--danger); border-color: var(--danger-line); }

/* Stat tiles (dashboard, WO Progress). Buttons that ARE a stat inherit this. */
.stats { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; margin-bottom: 8px; }
@media (min-width: 700px) { .stats { grid-template-columns: repeat(3, 1fr); } }
.stat {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 14px; box-shadow: var(--shadow); color: var(--ink);
}
.stat .n { font-size: 1.5rem; font-weight: 700; color: var(--brand); line-height: 1.1; }
.stat .l { font-size: .74rem; color: var(--ink-soft); text-transform: uppercase; letter-spacing: .05em; }
.stat.on { border-color: var(--ok-line); background: var(--ok-bg); }
.stat.on .n { color: var(--ok); }

.note-box { background: var(--card-2); border-left: 3px solid var(--brand);
  padding: 10px 12px; font-size: .84rem; color: var(--ink-soft);
  border-radius: 0 6px 6px 0; white-space: pre-wrap; }
.pill-list { display: flex; flex-wrap: wrap; gap: 6px; }
/* Scoped to <form>: the CRM V2 list tables use <tr class="filters"> for their
   per-column search row, and turning THAT into a grid destroys the table. */
form.filters { display: grid; grid-template-columns: 1fr; gap: 10px; }
@media (min-width: 700px) { form.filters { grid-template-columns: 2fr 1fr 1fr auto; align-items: end; } }
.grid2 { display: grid; grid-template-columns: 1fr; gap: 0 14px; }
/* A grid item's min-width defaults to `auto`, i.e. "as wide as my content",
   so a child that scrolls internally (a chart, a wide table) pushes the whole
   grid — and therefore the page — sideways instead of scrolling inside itself.
   This is what made the vendor analytics page 510px wide at a 360px viewport. */
.grid2 > * { min-width: 0; }
@media (min-width: 700px) { .grid2 { grid-template-columns: 1fr 1fr; } }
.hint { font-size: .76rem; color: var(--ink-faint); font-weight: 400; margin-top: 4px; }
.wo-note { font-style: italic; font-weight: 700; color: var(--brand); font-size: .86rem; }

/* ------------------------------------------------------------------
   Leads (P4 Phase 1)
   ------------------------------------------------------------------ */

/* Stage badges. The colours are the user's, named in models.LEAD_STAGES, and
   the charts phase must reuse these exact classes so a stage reads the same
   colour on a badge and in a chart.

   Built only from tokens that are DEFINED IN BOTH THEMES. An undefined custom
   property does not error - it falls back to currentColor and the badge quietly
   loses its colour, which is how an orphan --accent token shipped during
   CRM V2. Purple has no token of its own, so RFQ borrows the brand family
   rather than inventing a hex that would be wrong in dark mode. */
.badge.stage-red    { background: var(--danger-bg); color: var(--danger);   border-color: var(--danger-line); }
.badge.stage-grey   { background: var(--card-2);    color: var(--ink-soft); border-color: var(--line); }
.badge.stage-orange { background: var(--warn-bg);   color: var(--warn);     border-color: var(--warn-line); }
.badge.stage-blue   { background: var(--info-bg);   color: var(--info);     border-color: var(--info-line); }
.badge.stage-purple { background: var(--brand-soft); color: var(--brand-strong); border-color: var(--brand); }
.badge.stage-green  { background: var(--ok-bg);     color: var(--ok);       border-color: var(--ok-line); }

/* The per-salesperson strip above View Leads. */
.chip-row { display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--card-2);
  color: var(--ink-soft); font-size: .85rem; text-decoration: none;
}
.chip strong { color: var(--ink); }
.chip:hover { border-color: var(--brand); color: var(--ink); }
.chip-on { background: var(--brand); border-color: var(--brand); color: #fff; }
.chip-on strong { color: #fff; }
.chip-idle { border-color: var(--warn-line); }

/* Comment history inside the popup. Capped and scrolled: a lead worked for a
   year has a long history, and letting it grow pushes the "add a comment" box
   off the bottom - which is the one control people open the popup to reach. */
.comment-history {
  max-height: 260px; overflow-y: auto; margin-bottom: 12px;
  border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 10px;
  background: var(--card-2);
}
.comment-history .comment { padding: 6px 0; border-bottom: 1px solid var(--line); }
.comment-history .comment:last-child { border-bottom: 0; }
.comment-history .comment > div:last-child { white-space: pre-wrap; word-break: break-word; }

/* ================= HR leave calendar (P4 Phase 2) =================
   Every colour below resolves to a token defined in ALL THREE theme blocks
   (--ok/--info/--warn/--danger and their -bg pairs), so nothing falls back to
   currentColor in either theme. No new custom properties are introduced. */
table.cal { width: 100%; border-collapse: collapse; table-layout: fixed; }
table.cal th { padding: 6px; font-size: .74rem; color: var(--ink-soft);
               text-align: center; border-bottom: 1px solid var(--line); }
.cal-cell { height: 76px; vertical-align: top; border: 1px solid var(--line);
            padding: 4px; cursor: pointer; position: relative; }
.cal-cell:hover { background: var(--card-2); }
.cal-out { background: var(--card-2); opacity: .5; }
.cal-today { outline: 2px solid var(--brand); outline-offset: -2px; }
.cal-num { font-size: .8rem; font-weight: 600; }
.cal-tag { font-size: .68rem; margin-top: 2px; }
.cal-hol { font-size: .66rem; color: var(--danger); margin-top: 2px;
           line-height: 1.15; }
.cal-hol-opt { color: var(--info); }
.leave-dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%;
             vertical-align: middle; margin-right: 4px; }
.leave-green  { background: var(--ok); }
.leave-blue   { background: var(--info); }
.leave-orange { background: var(--warn); }
.leave-red    { background: var(--danger); }
.leave-hol    { background: var(--danger); opacity: .5; }
.cal-legend { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 10px;
              font-size: .76rem; color: var(--ink-soft); }
/* Balance summary key/value table, shared by leave + slip screens. */
table.kv { width: 100%; border-collapse: collapse; }
table.kv td { padding: 5px 4px; border-bottom: 1px solid var(--line); font-size: .86rem; }
table.kv td.k { color: var(--ink-soft); }
table.kv tr:last-child td { border-bottom: 0; }
table.kv tr.kv-total td { border-top: 2px solid var(--line-strong); }
td.right, th.right { text-align: right; }

/* Vendor last-price memory hint (P4 cross-feature 17), under a PO line's item. */
.lastprice-hint { font-size: .72rem; color: var(--info); margin-top: 3px; cursor: help; }
/* #33 vendor price comparison — each vendor's latest, best (lowest) in green. */
.pricecompare-hint { font-size: .72rem; color: var(--ink-faint); margin-top: 2px; }
.pricecompare-hint .pc-item { cursor: help; }
.pricecompare-hint .pc-best { color: var(--ok); font-weight: 700; }

/* #37 WO progress — slim two-tone bar: blue = department checks, green =
   dispatched quantity. Semantic colours from vars, so it tracks the theme. */
.wo-prog-wrap { display: flex; align-items: center; gap: 6px; margin-top: 5px; max-width: 190px; }
.wo-prog { position: relative; flex: 1 1 auto; height: 8px; min-width: 56px;
  background: var(--card-2); border: 1px solid var(--line); border-radius: 6px;
  overflow: hidden; display: flex; }
.wo-prog-fill { height: 100%; }
.wo-prog-checks { background: var(--brand); }
.wo-prog-disp { background: var(--ok); }
.wo-prog-label { font-size: .64rem; font-weight: 700; color: var(--ink-soft);
  min-width: 30px; text-align: right; }

/* #49 backup health card — a status dot coloured by freshness. */
.backup-card-row { display: flex; align-items: center; gap: 10px; }
.backup-dot { width: 12px; height: 12px; border-radius: 50%; flex: none; background: var(--ink-faint); }
.backup-card.is-fresh .backup-dot { background: var(--ok); }
.backup-card.is-stale .backup-dot { background: var(--danger); }
.backup-card.is-empty .backup-dot { background: var(--warn); }
.backup-card.is-unconfigured .backup-dot { background: var(--ink-faint); }
.backup-card.is-stale { border-color: var(--danger-line); }

/* #50 changelog notes */
.changelog-notes { margin: 4px 0 0; padding-left: 20px; }
.changelog-notes li { margin: 3px 0; }

/* --------------------------------------------------------------------------
   Honest share control (P4 cross-feature 18).
   -------------------------------------------------------------------------- */
.share-wrap { position: relative; display: inline-block; }
.share-menu { position: absolute; top: calc(100% + 6px); right: 0; z-index: 60;
              width: 260px; background: var(--card); border: 1px solid var(--line);
              border-radius: var(--radius); box-shadow: var(--shadow-lg); padding: 6px; }
.share-item { display: block; width: 100%; text-align: left; background: transparent;
              border: 0; padding: 9px 10px; border-radius: var(--radius-sm);
              font-size: .88rem; color: var(--ink); cursor: pointer; text-decoration: none; }
.share-item:hover { background: var(--brand-soft); }
.share-note { font-size: .72rem; color: var(--ink-soft); padding: 8px 10px 4px;
              border-top: 1px solid var(--line); margin-top: 4px; line-height: 1.4; }

/* --------------------------------------------------------------------------
   Global search box (P4 cross-feature 20) — topbar input + results dropdown.
   -------------------------------------------------------------------------- */
.topbar-search { position: relative; display: flex; align-items: center; gap: 6px;
                 background: var(--card-2); border: 1px solid var(--line);
                 border-radius: 999px; padding: 3px 10px; }
.topbar-search .search-icon { font-size: .82rem; opacity: .7; }
.topbar-search-input { border: 0; background: transparent; color: var(--ink);
                       font-size: .84rem; width: 150px; outline: none; }
.topbar-search-input::placeholder { color: var(--ink-faint); }
.search-results { position: absolute; top: calc(100% + 8px); right: 0; width: 340px;
                  max-width: 86vw; max-height: 68vh; overflow-y: auto;
                  background: var(--card); border: 1px solid var(--line);
                  border-radius: var(--radius); box-shadow: var(--shadow-lg); z-index: 70;
                  padding: 6px; }
.search-group { margin-bottom: 6px; }
.search-group-head { font-size: .68rem; text-transform: uppercase; letter-spacing: .05em;
                     color: var(--ink-faint); padding: 6px 8px 2px; }
.search-item { display: flex; flex-direction: column; gap: 1px; padding: 7px 8px;
               border-radius: var(--radius-sm); text-decoration: none; color: var(--ink); }
.search-item:hover, .search-item.active { background: var(--brand-soft); }
.search-item-label { font-size: .85rem; font-weight: 500; }
.search-item-detail { font-size: .74rem; color: var(--ink-soft); }
.search-empty { padding: 14px; font-size: .84rem; color: var(--ink-soft); text-align: center; }
.search-all { display: block; text-align: center; padding: 8px; font-size: .8rem;
              color: var(--brand); text-decoration: none; border-top: 1px solid var(--line);
              margin-top: 4px; }
.search-all:hover { background: var(--card-2); }
@media (max-width: 720px) { .topbar-search-input { width: 96px; } }

/* --------------------------------------------------------------------------
   Charts (P4 Phase 3). ECharts renders into .chart-box; everything around it is
   the app's own card language. Every colour below is an existing token, so the
   cards are theme-correct in light and dark without a new custom property.
   -------------------------------------------------------------------------- */
.chart-group { margin: 0 0 18px; }
.chart-group-title { font-size: 1rem; color: var(--ink-soft); margin: 6px 0 10px;
                     text-transform: uppercase; letter-spacing: .04em; }
/* Auto-fit grid: two-up on a wide screen, one-up on a phone. The hero (map)
   always spans the whole row. */
.chart-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
              gap: 16px; }
.chart-card { background: var(--card); border: 1px solid var(--line);
              border-radius: var(--radius); box-shadow: var(--shadow);
              padding: 14px 16px 12px; min-width: 0; display: flex; flex-direction: column; }
.chart-card.chart-hero { grid-column: 1 / -1; }
.chart-card-head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.chart-title { font-size: .95rem; font-weight: 600; color: var(--ink); margin: 0; flex: 1;
               white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chart-tools { display: flex; align-items: center; gap: 4px; flex: none; }
.chart-tool { border: 1px solid var(--line); background: var(--card-2); color: var(--ink-soft);
              border-radius: var(--radius-sm); width: 28px; height: 26px; cursor: pointer;
              font-size: .85rem; line-height: 1; }
.chart-tool:hover { color: var(--ink); border-color: var(--line-strong); }
.chart-period { border: 1px solid var(--line); background: var(--card-2); color: var(--ink);
                border-radius: var(--radius-sm); height: 26px; font-size: .78rem; padding: 0 4px; }
.chart-note { font-size: .72rem; color: var(--ink-faint); margin: 0 0 6px;
              border-left: 2px solid var(--warn-line); padding-left: 8px; }
.chart-partial { font-size: .66rem; font-weight: 600; text-transform: uppercase; letter-spacing: .04em;
                 color: var(--warn); background: var(--warn-bg); border: 1px solid var(--warn-line);
                 border-radius: 999px; padding: 1px 8px; flex: none; }
.chart-box { width: 100%; min-height: 120px; }
/* Celebration Feed (H7) — a list, not an ECharts canvas. */
.chart-feed { height: 100%; overflow-y: auto; }
.chart-feed-row { display: flex; align-items: center; gap: 10px; padding: 8px 4px;
                  border-bottom: 1px solid var(--line); font-size: .88rem; }
.chart-feed-row:last-child { border-bottom: 0; }
.chart-feed .cf-icon { font-size: 1.1rem; }
.chart-feed .cf-text { flex: 1; color: var(--ink); }
.chart-feed .cf-date { color: var(--ink-soft); font-size: .8rem; }
.chart-empty { display: flex; align-items: center; justify-content: center;
               min-height: 120px; font-size: .82rem; text-align: center; padding: 12px; }
/* Expand toggles the card to fill the viewport. */
.chart-card.chart-expanded { position: fixed; inset: 12px; z-index: 60; margin: 0;
                             overflow: auto; box-shadow: var(--shadow-lg); }
.chart-card.chart-expanded .chart-box { height: calc(100vh - 96px) !important; }
@media (max-width: 560px) {
  .chart-grid { grid-template-columns: 1fr; }
  .chart-card.chart-hero .chart-box { height: 360px !important; }
}

/* ---- P5 system settings editor ---- */
.settings-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 14px 20px;
  margin-bottom: 18px;
}

/* ---- P5 new-joiner onboarding cards ---- */
.joiner-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
                gap: 16px; margin-bottom: 20px; }
.joiner-card { border: 1px solid var(--line); border-radius: var(--radius); padding: 14px 16px;
               background: var(--card); box-shadow: var(--shadow); }
.joiner-card h3 { margin: 0 0 2px; font-size: 15px; }
.joiner-bar { height: 8px; border-radius: 5px; background: var(--card-2);
              border: 1px solid var(--line); overflow: hidden; margin: 10px 0; }
.joiner-bar > span { display: block; height: 100%; background: var(--brand); border-radius: 5px; }
.joiner-items { list-style: none; margin: 8px 0 0; padding: 0; }
.joiner-items li { display: flex; align-items: center; gap: 8px; padding: 3px 0; font-size: 13px; }
.joiner-items .tick { width: 18px; text-align: center; }
.joiner-items .done { color: var(--ok); }
.joiner-items .todo { color: var(--ink-faint); }
.joiner-items form { display: inline; }
.joiner-items .linkbtn { background: none; border: none; padding: 0; cursor: pointer;
                         color: var(--brand); font: inherit; text-decoration: underline; }

/* ---- P5 client last-quoted hint (#22) ---- */
.last-quoted-hint { font-size: 11px; color: var(--ink-faint); margin-top: 4px; }
.last-quoted-hint .lq-copy { color: var(--brand); font-weight: 700; text-decoration: none; }
.last-quoted-hint .lq-copy:hover { text-decoration: underline; }

/* ---- P5 quote revision compare (theme-agnostic low-alpha tints) ---- */
tr.cmp-changed > td { background: rgba(201, 138, 0, .13); }
tr.cmp-added   > td { background: rgba(31, 122, 68, .13); }
tr.cmp-removed > td { background: rgba(192, 39, 30, .13); text-decoration: line-through; }
