/* ============================================================
   APQP Manager Enterprise — premium application theme
   Inter typography · deep automotive gradients · gradient icon
   tiles · per-module brand colours · soft depth.
   ============================================================ */

/* ---- Inter (vendored, offline) ---- */
@font-face { font-family:'Inter'; font-style:normal; font-weight:400; font-display:swap;
  src:url("../vendor/css/fonts/inter-latin.da03732a27e1.woff2") format('woff2'); }
@font-face { font-family:'Inter'; font-style:normal; font-weight:500; font-display:swap;
  src:url("../vendor/css/fonts/inter-latin-500.51205681a1ba.woff2") format('woff2'); }
@font-face { font-family:'Inter'; font-style:normal; font-weight:600; font-display:swap;
  src:url("../vendor/css/fonts/inter-latin-600.2ede57db1a3a.woff2") format('woff2'); }
@font-face { font-family:'Inter'; font-style:normal; font-weight:700; font-display:swap;
  src:url("../vendor/css/fonts/inter-latin-700.8ca0a5155296.woff2") format('woff2'); }
@font-face { font-family:'Inter'; font-style:normal; font-weight:800; font-display:swap;
  src:url("../vendor/css/fonts/inter-latin-800.900ae45e40b8.woff2") format('woff2'); }

:root {
  --brand-900: #0a1020;
  --brand-800: #101c38;
  --brand-700: #16264c;
  --accent: #2563eb;
  --accent-600: #1d4ed8;
  --accent-soft: #eaf1fe;
  --sky: #0ea5e9;
  --indigo: #6366f1;
  --violet: #8b5cf6;
  --amber: #f59e0b;
  --emerald: #10b981;
  --teal: #14b8a6;
  --rose: #f43f5e;
  --ok: #10b981;
  --ok-soft: #e7f7ef;
  --warn: #d97706;
  --warn-soft: #fdf3e3;
  --danger: #e11d48;
  --danger-soft: #fdeaef;
  --ink: #0f172a;
  --ink-soft: #64748b;
  --line: #e6eaf1;
  --bg: #f4f6fb;
  --card: #ffffff;
  /* A step off --card for quiet fills: table heads, chips, hover rows.
     It was used in twelve places with a hard-coded light hex as the
     fallback and DEFINED nowhere — so in Midnight every one of them
     rendered a pale box with pale text on it, which is invisible. */
  --surface-1: #ffffff;
  --surface-2: #f4f7fb;
  /* Secondary text. Used in forty-nine places and defined NOWHERE, which
     for an inherited property means every one of them fell back to --ink:
     measured at rgb(15,23,42), the same colour as the heading beside it.
     Nothing receded anywhere in the product. It is an alias of --ink-soft
     rather than a second value, because `.text-muted-2` already reads that
     one for the same job and two greys would drift. */
  --muted: var(--ink-soft);
  --radius: 16px;
  --radius-sm: 12px;
  --sidebar-w: 256px;
  --shadow-xs: 0 1px 2px rgba(16, 24, 40, 0.05);
  --shadow-sm: 0 4px 18px rgba(16, 24, 40, 0.07);
  --shadow: 0 12px 30px rgba(16, 24, 40, 0.13);
  --shadow-lg: 0 18px 46px rgba(8, 17, 45, 0.30);
}

html, body { height: 100%; }
body {
  background: var(--bg);
  color: var(--ink);
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  font-size: 0.9rem;
  letter-spacing: -0.01em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
h1, h2, h3, h4, h5, h6, .fw-bold, .fw-semibold, .page-title, .kpi-value { letter-spacing: -0.02em; }
a { text-decoration: none; }

/* ============================================================
   ProQ top navbar — glassmorphism bar + animated mega-menu
   ============================================================ */
.proq-body { background: var(--bg); }

.proq-nav {
  background: linear-gradient(120deg, #0e225a 0%, #16308f 38%, #1d4ed8 74%, #2f6bf6 100%) !important;
  box-shadow: 0 6px 22px rgba(8, 17, 45, .35), inset 0 1px 0 rgba(255, 255, 255, .14);
  border-bottom: 1px solid rgba(255, 255, 255, .07);
  padding: .5rem 0; position: sticky; top: 0; z-index: 1030;
}
/* The beam below parks past the right edge for most of its ten-second cycle,
   invisible and 150px wide, and a box positioned past the edge still widens
   the page: measured 190px wider than a 390px screen and than a 1440px one.
   The old responsive check always measured mid-sweep and never saw it.
   Clipping the bar horizontally ends that and nothing else — the menus drop
   DOWN out of it, and `clip`, unlike `hidden`, leaves the vertical axis visible
   and makes no scroll container, so `sticky` still holds. */
.proq-nav { overflow-x: clip; }
/* glossy sheen across the top half + soft accent line at the bottom */
.proq-nav::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 52%;
  background: linear-gradient(180deg, rgba(255, 255, 255, .12), rgba(255, 255, 255, 0));
  pointer-events: none;
}
.proq-nav::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
  background: linear-gradient(90deg, rgba(56, 189, 248, 0), rgba(96, 165, 250, .65), rgba(56, 189, 248, 0));
  pointer-events: none;
}
.proq-nav .container-fluid { position: relative; z-index: 1; padding-left: 22px; padding-right: 22px; }
/* A light beam that sweeps left→right once every 10s for a subtle live feel.
   (Disabled automatically under prefers-reduced-motion via the global reset.) */
.proq-nav-beam { /* rest-hidden: decoration that only exists mid-sweep */
  position: absolute; top: 0; bottom: 0; left: 0; width: 150px; z-index: 2;
  pointer-events: none; mix-blend-mode: screen; filter: blur(2px); opacity: 0;
  background: linear-gradient(90deg,
    rgba(255,255,255,0) 0%, rgba(255,255,255,.16) 42%,
    rgba(173,216,255,.42) 50%, rgba(255,255,255,.16) 58%, rgba(255,255,255,0) 100%);
  transform: translateX(-180px);
  animation: proqNavBeam 10s ease-in-out infinite;
  will-change: transform, opacity;
}
@keyframes proqNavBeam {
  0%   { transform: translateX(-180px); opacity: 0; }
  3%   { opacity: 1; }
  22%  { transform: translateX(calc(100vw + 40px)); opacity: 1; }
  26%  { opacity: 0; }
  100% { transform: translateX(calc(100vw + 40px)); opacity: 0; }
}

/* ---- Brand ---- */
.proq-nav .navbar-brand { font-weight: 800; color: #fff; padding-top: 0; padding-bottom: 0; }
.brand-badge {
  width: 38px; height: 38px; border-radius: 11px;
  background: linear-gradient(135deg, #38bdf8 0%, #2563eb 55%, #14b8a6 100%);
  display: inline-flex; align-items: center; justify-content: center;
  color: #fff; font-weight: 800; font-size: 0.9rem; letter-spacing: .5px;
  box-shadow: 0 6px 16px rgba(37, 99, 235, .5), inset 0 1px 0 rgba(255, 255, 255, .4);
}
.brand-word {
  display: inline-flex; flex-direction: column; line-height: 1;
  font-size: 1.22rem; font-weight: 800; letter-spacing: .3px;
  text-shadow: 0 1px 3px rgba(0, 0, 0, .3);
}
.brand-tag { font-size: .5rem; font-weight: 700; letter-spacing: .22em; color: rgba(255, 255, 255, .62); margin-top: 3px; }

/* ---- Text nav links: pill hover with glow ---- */
.proq-nav .navbar-nav > .nav-item > .nav-link {
  color: rgba(255, 255, 255, .84) !important; font-weight: 600; font-size: .86rem;
  letter-spacing: .1px; padding: .46rem .8rem; margin: 0 .06rem; border-radius: 10px;
  transition: background .18s ease, color .18s ease, box-shadow .18s ease, transform .12s ease;
}
.proq-nav .navbar-nav > .nav-item > .nav-link:hover,
.proq-nav .navbar-nav > .nav-item.show > .nav-link,
.proq-nav .navbar-nav > .nav-item > .nav-link.active {
  color: #fff !important; background: rgba(255, 255, 255, .14);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .18), 0 3px 10px rgba(0, 0, 0, .16);
}
.proq-nav .nav-link i { filter: drop-shadow(0 1px 1px rgba(0, 0, 0, .22)); }
.proq-nav .dropdown-toggle::after { opacity: .65; margin-left: .4rem; }

/* ---- Quick-access icons: 3D glass buttons ---- */
.nav-quick-icon {
  width: 40px; height: 40px; border-radius: 11px; padding: 0 !important;
  display: inline-flex; align-items: center; justify-content: center; font-size: 1.05rem;
  color: rgba(255, 255, 255, .92) !important;
  background: linear-gradient(160deg, rgba(255, 255, 255, .18), rgba(255, 255, 255, .045));
  border: 1px solid rgba(255, 255, 255, .12);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), inset 0 -1px 0 rgba(0, 0, 0, .12), 0 2px 6px rgba(0, 0, 0, .2);
  transition: transform .14s ease, box-shadow .18s ease, background .18s ease;
}
.nav-quick-icon:hover {
  color: #fff !important; transform: translateY(-2px);
  background: linear-gradient(160deg, rgba(255, 255, 255, .3), rgba(255, 255, 255, .12));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .35), 0 7px 16px rgba(0, 0, 0, .3);
}
.nav-quick-icon:active { transform: translateY(0); }
.nav-quick-icon.active {
  color: #fff !important;
  background: linear-gradient(160deg, rgba(56, 189, 248, .55), rgba(37, 99, 235, .35));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .35), 0 5px 16px rgba(37, 99, 235, .55);
}
.nav-quick-icon i { filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .25)); }

/* ---- User chip + avatar ---- */
.user-chip {
  border-radius: 12px; padding: .28rem .5rem !important; color: #fff !important;
  background: rgba(255, 255, 255, .1); border: 1px solid rgba(255, 255, 255, .14);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .18);
}
.user-chip:hover { background: rgba(255, 255, 255, .2); }
.user-chip-name { font-weight: 600; font-size: .82rem; }
.avatar-badge {
  width: 32px; height: 32px; border-radius: 50%;
  background: linear-gradient(135deg, #38bdf8, #6366f1); color: #fff;
  font-weight: 700; font-size: 0.74rem; display: inline-flex; align-items: center;
  justify-content: center; box-shadow: 0 4px 12px rgba(37, 99, 235, .45), inset 0 1px 0 rgba(255, 255, 255, .35);
}

/* ---- Notification bell + badge ---- */
.notif-bell { border-radius: 10px; padding: .4rem .55rem !important; transition: background .18s ease; }
.notif-bell:hover { background: rgba(255, 255, 255, .14); }
.notif-badge {
  position: absolute; top: 1px; right: 1px; min-width: 17px; height: 17px; padding: 0 4px;
  border-radius: 9px; background: var(--danger); color: #fff; font-size: .62rem; font-weight: 700;
  display: inline-flex; align-items: center; justify-content: center;
  box-shadow: 0 2px 8px rgba(239, 68, 68, .55), 0 0 0 1.5px rgba(255, 255, 255, .9);
}

/* ---- Premium dropdown menus ---- */
.proq-nav .dropdown-menu {
  border: 1px solid rgba(15, 23, 42, .06); border-radius: 14px; padding: .4rem;
  margin-top: .55rem !important;
  box-shadow: 0 16px 40px rgba(8, 17, 45, .22), 0 2px 8px rgba(8, 17, 45, .1);
  animation: navDrop .16s ease;
}
@keyframes navDrop { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: translateY(0); } }
.proq-nav .dropdown-menu .dropdown-item {
  border-radius: 9px; font-weight: 500; font-size: .85rem; padding: .5rem .7rem;
  transition: background .14s ease, color .14s ease;
}
.proq-nav .dropdown-menu .dropdown-item:hover { background: linear-gradient(135deg, #eff4ff, #e6edff); color: #1d4ed8; }
.proq-nav .dropdown-menu .dropdown-item i { color: #2563eb; }

/* ---- Notification menu rows ---- */
.notif-menu .notif-item { border-radius: 9px; }
.notif-title { font-weight: 600; font-size: .82rem; display: flex; align-items: center; gap: 6px; color: var(--ink); }
.notif-udot { width: 7px; height: 7px; border-radius: 50%; flex: 0 0 7px; background: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.notif-msg { font-size: .74rem; color: var(--ink-soft); margin-top: 2px; }
.notif-menu .dropdown-item:hover .notif-msg { color: #475569; }

/* ============================================================
   Quality Tools mega-menu (per-module colored tiles + motion)
   ============================================================ */
.proq-nav .dropdown-menu.qt-menu {
  --qt-spring: cubic-bezier(.34, 1.56, .64, 1);
  --qt-ease: cubic-bezier(.22, .61, .36, 1);
  width: 328px; padding: .4rem .42rem .5rem;
  border: 1px solid rgba(15, 23, 42, .07); border-radius: 18px;
  background:
    radial-gradient(120% 100% at 0% 0%, rgba(37, 99, 235, .06), transparent 60%),
    linear-gradient(180deg, rgba(255, 255, 255, .97), rgba(248, 250, 255, .95));
  box-shadow: 0 24px 60px rgba(8, 17, 45, .26), 0 4px 14px rgba(8, 17, 45, .12), inset 0 1px 0 rgba(255, 255, 255, .9);
  -webkit-backdrop-filter: saturate(1.5) blur(14px); backdrop-filter: saturate(1.5) blur(14px);
}
.proq-nav .dropdown-menu.qt-menu .dropdown-item.qt-item:hover,
.proq-nav .dropdown-menu.qt-menu .dropdown-item.qt-item:focus { background: transparent; color: inherit; }
.proq-nav .dropdown-menu.qt-menu .dropdown-item.qt-item i { color: inherit; }

.qt-menu .qt-head {
  display: flex; align-items: center; gap: .45rem; font-size: .64rem; font-weight: 800;
  letter-spacing: .12em; text-transform: uppercase; color: #94a3b8;
  padding: .4rem .6rem .45rem; margin: 0 0 .25rem; border-bottom: 1px solid rgba(15, 23, 42, .07);
}
.qt-menu .qt-head-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: linear-gradient(135deg, #2f6bf6, #10b981); box-shadow: 0 0 0 3px rgba(47, 107, 246, .14);
}

.proq-nav .dropdown-menu.qt-menu .qt-item {
  position: relative; display: flex; align-items: center; gap: .68rem;
  padding: .5rem .55rem; border-radius: 12px; color: #0f172a; overflow: hidden; isolation: isolate;
  transition: transform .26s var(--qt-spring), background-color .2s ease, box-shadow .2s ease;
  opacity: 0; transform: translateX(-8px); animation: qtRowIn .42s var(--qt-spring) both;
}
.qt-menu li + li .qt-item::after {
  content: ""; position: absolute; left: 3rem; right: .55rem; top: -1px; height: 1px;
  background: rgba(15, 23, 42, .055); z-index: -1;
}
.qt-menu .qt-item::before {
  content: ""; position: absolute; left: 0; top: 50%; height: 0; width: 3px;
  border-radius: 0 3px 3px 0; background: linear-gradient(180deg, var(--qt-a), var(--qt-b));
  transform: translateY(-50%); transition: height .28s var(--qt-spring); z-index: 1;
}
.qt-menu .qt-tile {
  position: relative; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 10px; color: #fff; font-size: .98rem; overflow: hidden;
  background: linear-gradient(140deg, var(--qt-a), var(--qt-b));
  box-shadow: 0 3px 9px rgba(var(--qt-glow), .35), inset 0 1px 0 rgba(255, 255, 255, .28);
  transition: transform .3s var(--qt-spring), box-shadow .24s ease;
}
.qt-menu .qt-tile .bi { color: #fff; line-height: 1; transition: transform .3s var(--qt-spring); }
.qt-menu .qt-tile::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  background: linear-gradient(115deg, transparent 38%, rgba(255, 255, 255, .45) 50%, transparent 62%);
  transform: translateX(-130%); opacity: 0;
}
.qt-menu .qt-body { flex: 1 1 auto; min-width: 0; line-height: 1.18; }
.qt-menu .qt-title {
  display: block; font-weight: 650; font-size: .84rem; color: #0f172a;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.qt-menu .qt-sub {
  display: block; font-size: .695rem; font-weight: 500; color: #64748b;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; transition: color .2s ease;
}
.qt-menu .qt-pill {
  display: inline-block; margin-left: .3rem; padding: .03rem .34rem; font-size: .58rem; font-weight: 700;
  letter-spacing: .03em; color: #475569; background: #f1f5f9; border-radius: 999px; vertical-align: middle;
}
.qt-menu .qt-go {
  flex: 0 0 auto; font-size: .72rem; color: #cbd5e1; opacity: 0; transform: translateX(-4px);
  transition: opacity .2s ease, transform .26s var(--qt-spring), color .2s ease;
}
.proq-nav .dropdown-menu.qt-menu .qt-item:hover,
.proq-nav .dropdown-menu.qt-menu .qt-item:focus-visible {
  transform: translateX(5px); background-color: rgba(var(--qt-glow), .07);
}
.qt-menu .qt-item:hover::before,
.qt-menu .qt-item:focus-visible::before,
.qt-menu .qt-item.is-active::before { height: 64%; }
.qt-menu .qt-item:hover .qt-tile,
.qt-menu .qt-item:focus-visible .qt-tile {
  transform: translateY(-2px) scale(1.06);
  box-shadow: 0 6px 16px rgba(var(--qt-glow), .5), inset 0 1px 0 rgba(255, 255, 255, .35);
}
.qt-menu .qt-item:hover .qt-tile .bi,
.qt-menu .qt-item:focus-visible .qt-tile .bi { transform: scale(1.04) rotate(-3deg); }
.qt-menu .qt-item:hover .qt-tile::before { animation: qtSheen .6s ease forwards; }
.qt-menu .qt-item:hover .qt-go,
.qt-menu .qt-item:focus-visible .qt-go,
.qt-menu .qt-item.is-active .qt-go { opacity: 1; transform: translateX(0); color: var(--qt-a); }
.qt-menu .qt-item.is-active { background-color: rgba(var(--qt-glow), .09); }
.qt-menu .qt-item:active { transform: translateX(5px) scale(.99); }
.proq-nav .dropdown-menu.qt-menu .qt-item:focus-visible { outline: 2px solid var(--qt-a); outline-offset: -2px; }
@keyframes qtRowIn { from { opacity: 0; transform: translateX(-8px); } to { opacity: 1; transform: translateX(0); } }
@keyframes qtSheen { from { transform: translateX(-130%); opacity: .9; } to { transform: translateX(130%); opacity: 0; } }
.qt-menu li:nth-child(2) .qt-item { animation-delay: .03s; }
.qt-menu li:nth-child(3) .qt-item { animation-delay: .06s; }
.qt-menu li:nth-child(4) .qt-item { animation-delay: .09s; }
.qt-menu li:nth-child(5) .qt-item { animation-delay: .12s; }
.qt-menu li:nth-child(6) .qt-item { animation-delay: .15s; }
.qt-menu li:nth-child(7) .qt-item { animation-delay: .18s; }
.qt-menu li:nth-child(8) .qt-item { animation-delay: .21s; }

/* ============================================================
   Context sub-bar (page title + page actions)
   ============================================================ */
.subbar { background: rgba(255, 255, 255, .9);
  -webkit-backdrop-filter: saturate(1.4) blur(10px); backdrop-filter: saturate(1.4) blur(10px);
  border-bottom: 1px solid var(--line); }
.subbar-inner {
  max-width: var(--app-max, none); margin: 0 auto; padding: 9px 24px; min-height: 46px;
  display: flex; align-items: center; gap: 14px;
}
.subbar .page-context { font-weight: 700; color: var(--ink); font-size: .95rem; }
/* The strip used to carry the company name, which is the same on every screen
   and so said nothing. Most pages now put nothing in it at all, and an empty
   46px band across the top of 115 screens is worse than the text was — so it
   collapses.

   It used to collapse on DESKTOP only, because below lg the strip held the one
   way into the navigation. That stopped being true: the navbar carries its own
   toggler for the same `#navMain`, and the phone now has a bottom bar as well,
   so the strip was left holding a second hamburger directly beneath the first
   — which is what a phone screenshot showed, two identical buttons stacked.
   The condition is the same at every width now, and the redundant button goes
   with it. A page that has something to say still fills the strip and keeps it. */
.subbar:not(:has(.page-context:not(:empty))):not(:has(.subbar-actions > *)) {
  display: none;
}
/* The duplicate. `#navMain` is reached from the navbar at every width. */
.subbar > .subbar-inner > .btn-icon.d-lg-none { display: none; }
.btn-icon {
  border: 1px solid var(--line); background: #fff; border-radius: 11px;
  width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center;
  color: var(--ink-soft); position: relative; transition: all .15s ease;
}
.btn-icon:hover { border-color: var(--accent); color: var(--accent); box-shadow: var(--shadow-xs); }

/* App width follows the monitor: fluid to the full display by default.
   Set --app-max (e.g. 1600px) on :root to re-cap the working area if desired. */
.content { padding: 24px; max-width: var(--app-max, none); width: 100%; margin: 0 auto; }
.content-plain { padding: 0; max-width: none; }
/* A touch more side breathing room on very wide displays */
@media (min-width: 1900px) { .content { padding: 26px 40px; } .subbar-inner { padding: 9px 40px; } }

/* ---------- Hero band ---------- */
.hero-band {
  border-radius: 22px; color: #fff; overflow: hidden; position: relative;
  margin-bottom: 22px;
  background:
    url("../img/hero-automotive.3133761112b9.svg") right -6px bottom -10px / auto 168% no-repeat,
    radial-gradient(120% 160% at 92% -20%, rgba(56,189,248,0.30) 0%, rgba(56,189,248,0) 55%),
    linear-gradient(118deg, #0a1020 0%, #122a52 44%, #1b46b0 78%, #2563eb 100%);
  box-shadow: var(--shadow-lg), inset 0 1px 0 rgba(255, 255, 255, 0.10);
  border: 1px solid rgba(255, 255, 255, 0.06);
}
.hero-band::before {
  content:""; position:absolute; inset:0;
  background-image: repeating-linear-gradient(116deg, rgba(255,255,255,.035) 0 1px, transparent 1px 11px);
  pointer-events:none;
}
.hero-band::after {
  content:""; position:absolute; inset:0;
  background:
    linear-gradient(180deg, rgba(255,255,255,.10), rgba(255,255,255,0) 42%),
    linear-gradient(90deg, rgba(56,189,248,0) 0%, rgba(96,165,250,.55) 50%, rgba(56,189,248,0) 100%) bottom / 100% 2px no-repeat;
  pointer-events:none;
}
.hero-inner { display:flex; justify-content:space-between; align-items:center; gap:20px;
  padding: 26px 32px; position:relative; z-index:1; flex-wrap: wrap; }
.hero-eyebrow { font-size:.7rem; font-weight:700; text-transform:uppercase; letter-spacing:2px;
  color:#93c5fd; margin-bottom:6px; text-shadow:0 1px 6px rgba(37,99,235,.45); }
.hero-title { font-size:1.9rem; font-weight:800; margin:0 0 6px; text-shadow:0 2px 10px rgba(0,0,0,.35); }
.hero-sub { font-size:.92rem; color:#d4def0; margin:0; }
.btn-hero { /* light-only: a white button on the navy hero, which is navy in both themes */
  border-radius:13px; font-weight:700; padding:11px 20px;
  background:linear-gradient(180deg,#fff,#eef2fb); border:1px solid rgba(255,255,255,.8); color:#15294f;
  box-shadow:0 8px 20px rgba(0,0,0,.24), inset 0 1px 0 rgba(255,255,255,.9);
  transition:transform .14s ease, box-shadow .18s ease;
}
.btn-hero:hover { transform:translateY(-2px); color:#0f2557;
  box-shadow:0 12px 26px rgba(0,0,0,.3), inset 0 1px 0 rgba(255,255,255,.9); }
.hero-stats { display:flex; gap:26px; flex-wrap:wrap; }
.hero-stat .hs-val { font-size:1.5rem; font-weight:800; line-height:1; }
.hero-stat .hs-lab { font-size:.68rem; text-transform:uppercase; letter-spacing:.08em; color:#9fb4dc; margin-top:3px; }

/* ---------- Cards, tables ---------- */
.card { border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow-sm);
  background: var(--card); }
.card-header { background: transparent; border-bottom: 1px solid var(--line); font-weight: 600;
  padding: 13px 18px; }
.table { --bs-table-hover-bg: #f6f9ff; margin-bottom: 0; }
.table thead th {
  font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--ink-soft); border-bottom: 1px solid var(--line);
  background: #fafbff; font-weight: 700; padding: 11px 12px;
}
.table td { vertical-align: middle; }
.table-responsive { border-radius: var(--radius); }

/* ---------- Status + phase badges ---------- */
.badge-soft { border-radius: 999px; font-weight: 600; padding: 0.36em 0.75em; font-size: 0.72rem;
  display: inline-flex; align-items: center; gap: 4px; }
.badge-soft.ok { background: var(--ok-soft); color: #047857; }
.badge-soft.warn { background: var(--warn-soft); color: #b45309; }  /* amber-800: AA on the pale warn tint */
.badge-soft.danger { background: var(--danger-soft); color: var(--danger); }
.badge-soft.info { background: var(--accent-soft); color: var(--accent-600); }
.badge-soft.muted { background: #eef1f6; color: var(--ink-soft); }
.badge-soft.purple { background: #f1e9fe; color: #7c3aed; }

/* ---------- Phase stepper ---------- */
.phase-stepper { display: flex; gap: 8px; flex-wrap: wrap; }
.phase-step {
  flex: 1; min-width: 128px; border-radius: 14px; padding: 12px 14px;
  border: 1px solid var(--line); background: #fff; position: relative;
  box-shadow: var(--shadow-xs); transition: transform .14s ease, box-shadow .16s ease;
}
.phase-step:hover { transform: translateY(-2px); box-shadow: var(--shadow-sm); }
.phase-step .ph-num {
  width: 28px; height: 28px; border-radius: 50%; font-size: 0.8rem; font-weight: 700;
  display: inline-flex; align-items: center; justify-content: center;
  background: #eef1f6; color: var(--ink-soft);
}
.phase-step.done { border-color: rgba(16, 185, 129, .35); background: linear-gradient(180deg,#f4fdf8,#fff); }
.phase-step.done .ph-num { background: linear-gradient(135deg,#34d399,#059669); color: #fff;
  box-shadow: 0 4px 10px rgba(16,185,129,.34); }
.phase-step.active { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.phase-step.active .ph-num { background: linear-gradient(135deg,#38bdf8,#2563eb); color: #fff;
  box-shadow: 0 4px 10px rgba(37,99,235,.34); }
.phase-step .ph-name { font-weight: 600; font-size: 0.8rem; margin-top: 6px; }
.phase-step .ph-meta { font-size: 0.72rem; color: var(--ink-soft); }
/* scoped-out (not applicable) phase — muted, hatched, dashed border */
.phase-step.na {
  border-style: dashed; opacity: .78;
  background: repeating-linear-gradient(45deg,#f8fafc,#f8fafc 6px,#f1f5f9 6px,#f1f5f9 12px);
}
.phase-step.na:hover { transform: none; box-shadow: var(--shadow-xs); }
.phase-step.na .ph-num { background: #e2e8f0; color: var(--ink-soft); box-shadow: none; }

/* ---------- KPI tiles (premium) ---------- */
.kpi-tile {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 17px 19px; height: 100%; box-shadow: var(--shadow-sm);
  transition: box-shadow .18s ease, transform .18s ease; position: relative; overflow: hidden;
}
.kpi-tile:hover { box-shadow: var(--shadow); transform: translateY(-2px); }
.kpi-tile .kpi-ic {
  width: 44px; height: 44px; border-radius: 13px; display: inline-grid; place-items: center;
  color: #fff; font-size: 1.25rem; margin-bottom: 12px;
  box-shadow: 0 6px 16px rgba(16,24,40,.16), inset 0 1px 0 rgba(255,255,255,.3);
}
.kpi-ic.g-blue { background: linear-gradient(135deg,#38bdf8,#2563eb); }
.kpi-ic.g-indigo { background: linear-gradient(135deg,#818cf8,#4f46e5); }
.kpi-ic.g-emerald { background: linear-gradient(135deg,#34d399,#059669); }
.kpi-ic.g-amber { background: linear-gradient(135deg,#fbbf24,#d97706); }
.kpi-ic.g-rose { background: linear-gradient(135deg,#fb7185,#e11d48); }
.kpi-ic.g-violet { background: linear-gradient(135deg,#a78bfa,#7c3aed); }
.kpi-ic.g-teal { background: linear-gradient(135deg,#2dd4bf,#0d9488); }
.kpi-tile .kpi-label { font-size: 0.7rem; color: var(--ink-soft); text-transform: uppercase;
  letter-spacing: .06em; font-weight: 700; }
.kpi-tile .kpi-value { font-size: 1.75rem; font-weight: 800; line-height: 1.1; }
.kpi-tile .kpi-sub { font-size: 0.74rem; color: var(--ink-soft); }
.kpi-tile.kpi-ok::after, .kpi-tile.kpi-warn::after, .kpi-tile.kpi-danger::after,
.kpi-tile.kpi-info::after { content:""; position:absolute; left:0; top:0; bottom:0; width:4px; }
.kpi-tile.kpi-ok::after { background: var(--ok); }
.kpi-tile.kpi-warn::after { background: var(--warn); }
.kpi-tile.kpi-danger::after { background: var(--danger); }
.kpi-tile.kpi-info::after { background: var(--accent); }

/* ---------- Progress ---------- */
.progress { height: 8px; border-radius: 6px; background: #eef1f6; }
.progress-bar { background: linear-gradient(90deg, #2563eb, #38bdf8); border-radius: 6px; }

/* ---------- Forms ---------- */
.form-label { font-weight: 600; font-size: 0.82rem; }
.form-control, .form-select { border-color: var(--line); border-radius: 10px; }
.form-control:focus, .form-select:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.form-control-sm, .form-select-sm { border-radius: 8px; }
.btn { border-radius: 11px; font-weight: 600; }
.btn-primary { background: linear-gradient(180deg,#2f6bf6,#2054d6); border-color: #2054d6;
  box-shadow: 0 6px 16px rgba(37,99,235,.28); }
.btn-primary:hover { background: linear-gradient(180deg,#2a61e6,#1b49c0); border-color: #1b49c0; }
.btn-sm { border-radius: 9px; }

/* ---------- Auth pages ---------- */
.auth-wrap {
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  background:
    radial-gradient(1100px 520px at 85% -10%, rgba(37, 99, 235, 0.16), transparent),
    radial-gradient(800px 420px at -10% 110%, rgba(20, 184, 166, 0.13), transparent),
    linear-gradient(180deg, #eef2fb, var(--bg));
  padding: 24px;
}
.auth-card { width: 100%; max-width: 440px; }
.auth-card .card { box-shadow: var(--shadow); border-radius: 20px; }
.auth-badge {
  width: 58px; height: 58px; border-radius: 17px; display: inline-flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, #38bdf8 0%, #2563eb 55%, #14b8a6 100%);
  color: #fff; font-weight: 800; font-size: 1.3rem; letter-spacing: .5px;
  box-shadow: 0 12px 28px rgba(37, 99, 235, .45), inset 0 1px 0 rgba(255, 255, 255, .45);
}

/* ---------- Editable grids ---------- */
.grid-table td, .grid-table th { font-size: 0.82rem; }
.grid-table .cell-input {
  border: 1px solid transparent; background: transparent; width: 100%;
  border-radius: 7px; padding: 3px 6px; font-size: 0.82rem;
}
.grid-table .cell-input:hover { border-color: var(--line); background: #fff; }
.grid-table .cell-input:focus { border-color: var(--accent); background: #fff; outline: none;
  box-shadow: 0 0 0 3px var(--accent-soft); }
/* Narrow S/O/D rating selects: drop the native dropdown arrow so the 1-2 digit
   value shows clean and centred (the arrow overlapped the number). */
.grid-table select.cell-input.text-center {
  -webkit-appearance: none; -moz-appearance: none; appearance: none;
  background-image: none; text-align: center; text-align-last: center;
  padding-left: 2px; padding-right: 2px; font-weight: 600;
}
.grid-table select.cell-input.text-center::-ms-expand { display: none; }
.sticky-col { position: sticky; left: 0; background: #fff; z-index: 2; }

/* ---------- Project risk assessment (APQP §1.17 / App. C) ---------- */
.risk-matrix { border-collapse: separate; border-spacing: 3px; width: 100%; max-width: 340px; }
.risk-matrix td, .risk-matrix th { text-align: center; font-variant-numeric: tabular-nums; }
.rm-cell { height: 34px; font-weight: 700; color: #1f2937; border-radius: 6px; font-size: .8rem; }
.rm-low { background: #d1fae5; } .rm-medium { background: #fde68a; }
.rm-high { background: #fecaca; } .rm-unrated { background: #eef1f6; }
.rm-axis { font-weight: 700; font-size: .72rem; color: var(--ink-soft); padding-right: 6px;
  white-space: nowrap; text-align: right; }
.rm-axis-lab { display: block; font-weight: 500; font-size: .55rem; color: var(--ink-soft); }
.rm-axis-b { font-size: .72rem; color: var(--ink-soft); font-weight: 700; }
.rm-key { display: inline-block; width: 10px; height: 10px; border-radius: 2px;
  margin: 0 3px 0 8px; vertical-align: middle; }
.rm-key.rm-low { background: #6ee7b7; } .rm-key.rm-medium { background: #fbbf24; }
.rm-key.rm-high { background: #f87171; }
.risk-table .cell-input { border: 1px solid var(--line, #e5e7eb); background: #fff;
  border-radius: 6px; padding: 2px 5px; font-size: .75rem; }
.risk-table .cell-input:focus { border-color: var(--accent); outline: none;
  box-shadow: 0 0 0 2px var(--accent-soft); }
.risk-table .cell-input.is-required { border-color: #dc2626; background: #fef2f2; }
.risk-row.risk-lvl-high > td:first-child { box-shadow: inset 3px 0 0 var(--danger, #dc2626); }
.risk-row.risk-lvl-medium > td:first-child { box-shadow: inset 3px 0 0 #d97706; }
.risk-guide th { font-size: .64rem; text-transform: uppercase; letter-spacing: .04em;
  color: var(--ink-soft); background: #f8fafc; font-weight: 700; vertical-align: middle; }
.risk-guide td { font-size: .72rem; vertical-align: top; line-height: 1.32; }

/* Project action plan — inline editable table; overdue rows tint red, the
   days-left badge blinks red (reuses .badge-blink / latepulse). */
.action-table .cell-input { border: 1px solid var(--line, #e5e7eb); background: #fff;
  border-radius: 6px; padding: 2px 6px; font-size: .78rem; width: 100%; }
.action-table .cell-input:focus { border-color: var(--accent); outline: none;
  box-shadow: 0 0 0 2px var(--accent-soft); }
.action-table tr.action-overdue > td { background: rgba(220,38,38,.05); }
.action-table tr.action-overdue > td:first-child { box-shadow: inset 3px 0 0 var(--danger, #dc2626); }
/* Date cell: keep the "CW" (Wnn) week badge to the RIGHT of the date, not beneath it */
.action-date { display: flex; align-items: center; gap: 6px; }
.action-date .cell-input { flex: 1 1 auto; min-width: 0; width: auto; }
.action-date .wk-badge { flex: 0 0 auto; margin-left: 0; }

/* Trial-readiness checklist — fixed 4M+ rows, editable date/status cells */
.readiness-table .cell-input { border: 1px solid var(--line, #e5e7eb); background: #fff;
  border-radius: 6px; padding: 2px 6px; font-size: .78rem; width: 100%; }
.readiness-table .cell-input:focus { border-color: var(--accent); outline: none;
  box-shadow: 0 0 0 2px var(--accent-soft); }
.readiness-table td:first-child { color: var(--ink); }
.readiness-status { font-weight: 600; }
.readiness-status.rs-ok     { color: #047857; border-color: rgba(4,120,87,.35); }
.readiness-status.rs-info   { color: var(--accent-600); border-color: rgba(37,99,235,.35); }
.readiness-status.rs-warn   { color: #b45309; border-color: rgba(180,83,9,.35); }
.readiness-status.rs-danger { color: var(--danger); border-color: rgba(225,29,72,.35); }
.readiness-status.rs-muted  { color: var(--ink-soft); }

/* Escalation ladder — configurable "after N weeks → position → responsible" */
.escalation-table .cell-input { border: 1px solid var(--line, #e5e7eb); background: #fff;
  border-radius: 6px; padding: 2px 6px; font-size: .78rem; }
.escalation-table .cell-input:focus { border-color: var(--accent); outline: none;
  box-shadow: 0 0 0 2px var(--accent-soft); }
.escalation-table select.cell-input { width: 100%; }

/* Core Team phase cell — RASIC select + per-person task-load badge */
.ctm-cell { display: inline-flex; flex-direction: column; align-items: center; gap: 3px; }
.ctm-load { display: inline-flex; align-items: center; gap: 3px; font-size: .62rem;
  font-weight: 700; line-height: 1; padding: 2px 6px; border-radius: 999px;
  color: var(--accent-600, #1d4ed8); background: var(--accent-soft, #eaf1fe);
  border: 1px solid rgba(37,99,235,.22); font-variant-numeric: tabular-nums; }
.ctm-load i { font-size: .6rem; opacity: .8; }

/* ============ Core Team — premium compact sheet ============ */
/* Slim legend strip */
.ctm-legend { display: flex; flex-wrap: wrap; align-items: center; gap: 7px 16px;
  padding: 8px 14px; font-size: .74rem; color: var(--ink-soft);
  border: 1px solid var(--line); border-radius: 13px; background: var(--card);
  box-shadow: var(--shadow-xs); }
.ctm-legend .lg-item { display: inline-flex; align-items: center; gap: 6px; }
.ctm-legend .sep { width: 1px; height: 15px; background: var(--line); }
.rasic-pill { display: inline-flex; align-items: center; justify-content: center;
  min-width: 21px; height: 21px; padding: 0 6px; border-radius: 999px;
  font-weight: 800; font-size: .66rem; line-height: 1; }
.rp-R { background: var(--accent-soft); color: var(--accent-600); }
.rp-A { background: var(--danger-soft); color: #dc2626; }
.rp-S { background: #d9f2ef; color: #0d9488; }
.rp-I { background: #eef1f6; color: #64748b; }
.rp-C { background: #f1e9fe; color: #7c3aed; }

/* Collapsible "add position" */
.ctm-add { border: 1px solid var(--line); border-radius: 13px; background: var(--card);
  box-shadow: var(--shadow-xs); overflow: hidden; }
.ctm-add > summary { cursor: pointer; list-style: none; padding: 10px 14px;
  font-weight: 600; font-size: .82rem; color: var(--ink);
  display: flex; align-items: center; gap: 8px; user-select: none; }
.ctm-add > summary::-webkit-details-marker { display: none; }
.ctm-add > summary:hover { color: var(--accent); }
.ctm-add > summary .chev { margin-left: auto; color: var(--ink-soft); transition: transform .2s ease; }
.ctm-add[open] > summary { border-bottom: 1px solid var(--line); }
.ctm-add[open] > summary .chev { transform: rotate(180deg); }
.ctm-add .ctm-add-body { padding: 13px 14px; }

/* The sheet: one continuous premium table with grouped sections */
.ctm-sheet { overflow: hidden; }
.ctm-table { border-collapse: separate; border-spacing: 0; }
.ctm-table thead th { text-transform: uppercase; letter-spacing: .045em;
  font-size: .62rem; font-weight: 700; color: var(--ink-soft);
  background: #fbfcfe; padding: 9px 13px; border-bottom: 1px solid var(--line); }
.ctm-table tbody td { padding: 6px 13px; border-bottom: 1px solid var(--line);
  vertical-align: middle; }
.ctm-table tbody tr:not(.ctm-group):hover td { background: #f7f9fd; }
.ctm-table tbody tr:last-child td { border-bottom: 0; }
.ctm-table tbody td:first-child { font-weight: 600; color: var(--ink); }

/* Section group header row */
.ctm-group td { padding: 8px 13px !important; background: #f2f5fb;
  font-weight: 700; font-size: .68rem; text-transform: uppercase; letter-spacing: .06em;
  color: var(--ink); border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.ctm-group:first-child td { border-top: 0; }
.ctm-group-dot { display: inline-block; width: 8px; height: 8px; border-radius: 3px;
  margin-right: 9px; vertical-align: middle; background: var(--accent);
  box-shadow: 0 0 0 3px rgba(37,99,235,.12); }
.ctm-group-core .ctm-group-dot { background: #2563eb; box-shadow: 0 0 0 3px rgba(37,99,235,.14); }
.ctm-group-daci .ctm-group-dot { background: #7c3aed; box-shadow: 0 0 0 3px rgba(124,58,237,.14); }
.ctm-group-other .ctm-group-dot { background: #64748b; box-shadow: 0 0 0 3px rgba(100,116,139,.14); }
.ctm-group-count { margin-left: 9px; color: var(--ink-soft); font-weight: 600;
  background: var(--card); border: 1px solid var(--line); border-radius: 999px;
  padding: 1px 9px; font-size: .62rem; letter-spacing: 0; }

/* Responsible person — avatar chip + inline select */
.ctm-person { display: flex; align-items: center; gap: 9px; }
.ctm-avatar { flex: 0 0 27px; width: 27px; height: 27px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center; color: #fff;
  font-weight: 700; font-size: .64rem; letter-spacing: .3px; background: var(--a, #94a3b8);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.28), 0 1px 3px rgba(16,24,40,.14); }
.ctm-avatar.is-empty { background: #eef1f6; color: #94a3b8; box-shadow: inset 0 0 0 1px var(--line); }
.ctm-avatar.is-empty i { font-size: .72rem; }
.ctm-person select.cell-input { font-weight: 600; }

/* RASIC cells rendered as filled pills (still editable selects) */
.ctm-table .ctm-cell { gap: 5px; }
.ctm-table select.cell-input.rasic { min-width: 44px; border-radius: 999px;
  padding: 4px 8px; font-weight: 800; font-size: .74rem;
  border: 1px solid transparent; background: transparent; color: #cbd5e1;
  transition: background .12s ease, color .12s ease, box-shadow .12s ease; }
.ctm-table select.cell-input.rasic:hover { box-shadow: inset 0 0 0 1px var(--line); }
.ctm-table select.cell-input.rasic.rasic-R { background: var(--accent-soft); color: var(--accent-600); }
.ctm-table select.cell-input.rasic.rasic-A { background: var(--danger-soft); color: #dc2626; }
.ctm-table select.cell-input.rasic.rasic-S { background: #d9f2ef; color: #0d9488; }
.ctm-table select.cell-input.rasic.rasic-I { background: #eef1f6; color: #64748b; }
.ctm-table select.cell-input.rasic.rasic-C { background: #f1e9fe; color: #7c3aed; }
.ctm-table select.cell-input.rasic:focus { box-shadow: 0 0 0 3px var(--accent-soft); }

@media (max-width: 640px) {
  .ctm-table thead th, .ctm-table tbody td { padding-left: 9px; padding-right: 9px; }
  .ctm-avatar { flex-basis: 24px; width: 24px; height: 24px; }
}

/* ============ Phase deliverables board — premium compact sheet ============ */
/* Reuses grid-table (.cell-input), .ctm-avatar/.ctm-person, .ctm-add. Everything
   net-new is scoped under .del-* so it never leaks to other tables. */
.del-sheet { overflow: hidden; }
.del-table { border-collapse: separate; border-spacing: 0; }
.del-table thead th {
  text-transform: uppercase; letter-spacing: .045em; font-size: .62rem; font-weight: 700;
  color: var(--ink-soft); background: #fbfcfe; padding: 9px 13px;
  border-bottom: 1px solid var(--line); white-space: nowrap; text-align: left;
}
.del-table tbody td {
  padding: 6px 13px; border-bottom: 1px solid var(--line);
  vertical-align: middle; font-size: .8rem;
}
.del-table tbody tr:hover td { background: #f7f9fd; }
.del-table tbody tr:last-child td { border-bottom: 0; }
.del-table td .badge-soft { white-space: nowrap; }

/* Overdue → single 3px danger left rail on the code cell */
.del-row.is-overdue > td:first-child { box-shadow: inset 3px 0 0 var(--danger); }
.del-row.is-overdue .del-due input { color: var(--danger); font-weight: 700; }
/* NA → recessed & muted */
.del-row.is-na > td { background: #fbfcfd; color: #94a3b8; }
.del-row.is-na:hover > td { background: #f6f8fb; }
.del-row.is-na .ctm-avatar { opacity: .6; }

.del-code { font-variant-numeric: tabular-nums; font-weight: 700; font-size: .74rem; color: var(--ink-soft); }
.del-name { font-weight: 600; color: var(--ink); font-size: .82rem; }
.del-name + .badge-soft, .del-code .badge-soft { font-size: .55rem; }

/* Secondary/destructive controls: reveal on hover, reachable on focus & touch */
.del-reveal { opacity: 0; transition: opacity .12s ease; }
.del-row:hover .del-reveal,
.del-reveal:focus-visible,
.del-reveal:focus-within { opacity: 1; }
@media (hover: none) { .del-reveal { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .del-reveal { transition: none; } }

.del-status-cell { display: flex; align-items: center; gap: 6px; min-height: 27px; }

/* Status as a filled pill-select: leading currentColor state-dot + faint caret */
.del-table select.del-status {
  -webkit-appearance: none; -moz-appearance: none; appearance: none;
  border: 1px solid transparent; border-radius: 999px;
  padding: 4px 22px; font-weight: 700; font-size: .72rem; line-height: 1;
  cursor: pointer; min-width: 112px; max-width: 138px; font-variant-numeric: tabular-nums;
  background-repeat: no-repeat, no-repeat;
  background-position: left 8px center, right 7px center;
  background-size: 7px 7px, 9px 6px;
  background-image:
    radial-gradient(circle at center, currentColor 0 3px, transparent 3.5px),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='9' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%2394a3b8' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  transition: box-shadow .12s ease, background-color .12s ease, color .12s ease;
}
.del-table select.del-status::-ms-expand { display: none; }
.del-table select.del-status:hover { box-shadow: inset 0 0 0 1px var(--line); }
.del-table select.del-status:focus,
.del-table select.del-status:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--accent-soft); }
.del-table select.del-status:disabled {
  cursor: default; opacity: .9; padding-right: 12px;
  background-image: radial-gradient(circle at center, currentColor 0 3px, transparent 3.5px);
  background-position: left 8px center;
}
.del-status.st-not_started { background-color: #eef1f6;           color: #64748b; }
.del-status.st-in_progress { background-color: var(--warn-soft);   color: #b45309; }
.del-status.st-in_review   { background-color: var(--accent-soft); color: var(--accent-600); }
.del-status.st-released    { background-color: var(--ok-soft);     color: #047857; }
.del-status.st-na          { background-color: #eef1f6;            color: #94a3b8; }

/* Icon-only submit (send for approval) — always visible */
.del-submit {
  flex: 0 0 26px; width: 26px; height: 26px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 8px; border: 1px solid rgba(37,99,235,.22);
  background: var(--accent-soft); color: var(--accent-600);
  font-size: .8rem; line-height: 1; cursor: pointer;
  transition: background .14s ease, color .14s ease, border-color .14s ease, box-shadow .14s ease, transform .1s ease;
}
.del-submit:hover { background: var(--accent); border-color: var(--accent); color: #fff;
  transform: translateY(-1px); box-shadow: 0 2px 8px rgba(37,99,235,.28); }
.del-submit:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--accent-soft); }

/* Awaiting chip */
.del-await {
  display: inline-flex; align-items: center; gap: 5px; padding: 3px 9px 3px 8px;
  border-radius: 999px; font-size: .68rem; font-weight: 700; white-space: nowrap;
  background: var(--warn-soft); color: #b45309; border: 1px solid rgba(217,119,6,.18);
}
.del-await i { font-size: .72rem; }

/* Primary Approve keeps its label; reject is a coin */
.del-approve {
  display: inline-flex; align-items: center; gap: 5px; height: 26px; padding: 0 11px;
  border-radius: 999px; border: 1px solid var(--ok); background: var(--ok); color: #fff;
  font-size: .7rem; font-weight: 700; cursor: pointer; white-space: nowrap;
  transition: filter .14s ease, box-shadow .14s ease;
}
.del-approve:hover { filter: brightness(.96); box-shadow: 0 2px 8px rgba(16,185,129,.3); }
.del-approve:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--ok-soft); }

/* Shared coin button for reject / evidence-remove / custom-delete */
.del-icon {
  flex: 0 0 26px; width: 26px; height: 26px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 8px; border: 1px solid var(--line); background: var(--card);
  color: var(--ink-soft); font-size: .8rem; line-height: 1; cursor: pointer;
  transition: background .14s ease, color .14s ease, border-color .14s ease, box-shadow .14s ease;
}
.del-icon:hover { box-shadow: var(--shadow-xs); }
.del-icon:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--accent-soft); }
.del-icon.reject { color: var(--danger); border-color: rgba(225,29,72,.22); background: var(--danger-soft); }
.del-icon.reject:hover { background: var(--danger); border-color: var(--danger); color: #fff; }

@media (prefers-reduced-motion: reduce) {
  .del-submit, .del-icon, .del-approve { transition: none; }
  .del-submit:hover { transform: none; }
}

.del-unassigned { display: inline-flex; align-items: center; gap: 3px; margin-top: 2px;
  font-size: .64rem; font-weight: 600; color: #b45309; text-decoration: none; }
.del-unassigned:hover { text-decoration: underline; }
.del-due input { font-variant-numeric: tabular-nums; }

/* Legend strip (flush inside the card) */
.del-legend { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 15px;
  padding: 7px 14px; font-size: .7rem; color: var(--ink-soft);
  border-bottom: 1px solid var(--line); background: var(--card); }
.del-legend .k { display: inline-flex; align-items: center; gap: 6px; }
.del-legend .dot { width: 8px; height: 8px; border-radius: 50%; }

/* ============ Gate Reviews cockpit ============ */
.gr-sheet { overflow: hidden; }
/* Sheet table (mirrors .del-table / .ctm-table) */
.gr-table thead th { text-transform: uppercase; letter-spacing: .045em; font-size: .62rem;
  font-weight: 700; color: var(--ink-soft); background: #fbfcfe; padding: 9px 13px;
  border-bottom: 1px solid var(--line); white-space: nowrap; }
.gr-table tbody td { padding: 8px 13px; border-bottom: 1px solid var(--line); vertical-align: middle; font-size: .8rem; }
.gr-table tbody tr:hover td { background: #f7f9fd; }
.gr-table tbody tr:last-child td { border-bottom: 0; }
.gr-row.is-overdue > td:first-child { box-shadow: inset 3px 0 0 var(--danger); }
.gr-row.is-mine > td:first-child { box-shadow: inset 3px 0 0 var(--warn); }
.gr-row.is-mine > td { background: rgba(217,119,6,.045); }
.gr-row.is-mine:hover > td { background: rgba(217,119,6,.08); }

/* Highlighted focus gate — the one gate to approve next in each project */
.gr-focus { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px;
  border-radius: 8px; background: var(--accent-soft); border: 1px solid rgba(37,99,235,.28);
  color: var(--accent-600); font-weight: 700; font-size: .78rem; text-decoration: none;
  transition: background .12s ease, box-shadow .12s ease; }
.gr-focus:hover { background: #dbe6fe; box-shadow: var(--shadow-xs); }
.gr-focus > i { font-size: .72rem; }
.gr-focus .gr-focus-code { font-size: .56rem; font-weight: 700; background: #fff;
  border: 1px solid var(--line); border-radius: 5px; padding: 1px 5px; color: var(--ink-soft); }
.gr-focus.is-mine { background: var(--warn-soft); border-color: rgba(217,119,6,.45); color: #92400e; }
.gr-focus.is-mine:hover { background: #fbe2c9; }
.gr-focus.is-overdue { background: var(--danger-soft); border-color: rgba(225,29,72,.4); color: #dc2626; }
.gr-focus.is-overdue:hover { background: #fbd5de; }

/* Awaiting-your-signature card accent */
.gr-mine { border-color: rgba(217,119,6,.4); }
.gr-mine > .card-header { background: var(--warn-soft); color: #92400e; }

/* Portfolio matrix */
.gr-matrix thead th { text-transform: uppercase; letter-spacing: .04em; font-size: .6rem;
  font-weight: 700; color: var(--ink-soft); background: #fbfcfe; padding: 8px 10px;
  border-bottom: 1px solid var(--line); }
.gr-matrix tbody td { padding: 7px 10px; border-bottom: 1px solid var(--line); }
.gr-matrix tbody tr:last-child td { border-bottom: 0; }
.gr-matrix tbody tr:hover td { background: #f9fbfe; }

.gr-cell { position: relative; display: inline-flex; align-items: center; justify-content: center;
  width: 46px; height: 34px; border-radius: 9px; font-weight: 800; font-size: .82rem;
  text-decoration: none; color: #1f2937; border: 1px solid transparent;
  transition: transform .1s ease, box-shadow .12s ease; }
a.gr-cell:hover { transform: translateY(-1px); box-shadow: var(--shadow-xs); }
.gr-cell.is-current { outline: 2px solid rgba(37,99,235,.55); outline-offset: 1px; }
.rag-green { background: var(--ok-soft); color: #047857; }
.rag-amber { background: #f1e9fe; color: #7c3aed; }        /* conditional = purple/violet */
.rag-red   { background: var(--danger-soft); color: #dc2626; }
.rag-open  { background: var(--accent-soft); color: var(--accent-600); box-shadow: inset 0 0 0 1px rgba(37,99,235,.14); }
.rag-grey  { background: #eef1f6; color: #94a3b8; }
.rag-na    { background: repeating-linear-gradient(45deg,#f5f7fa,#f5f7fa 4px,#eef1f6 4px,#eef1f6 8px); color: #cbd5e1; cursor: default; }

.gr-missing { position: absolute; top: -5px; right: -5px; min-width: 16px; height: 16px;
  border-radius: 9px; background: var(--danger); color: #fff; font-size: .6rem; font-weight: 700;
  display: inline-flex; align-items: center; justify-content: center; padding: 0 3px; box-shadow: 0 0 0 2px #fff; }
.gr-dot { position: absolute; left: 4px; bottom: 4px; width: 7px; height: 7px; border-radius: 50%;
  box-shadow: 0 0 0 2px rgba(255,255,255,.9); }
.gr-dot.ok { background: var(--ok); } .gr-dot.warn { background: var(--warn); } .gr-dot.danger { background: var(--danger); }

/* Approver avatar stack + signature status rings */
.gr-stack { display: inline-flex; align-items: center; }
.gr-stack .gr-sig { width: 24px; height: 24px; font-size: .58rem; margin-left: -6px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.28), 0 0 0 2px #fff; }
.gr-stack .gr-sig:first-child { margin-left: 0; }
.gr-sig--approved { box-shadow: inset 0 1px 0 rgba(255,255,255,.28), 0 0 0 2px var(--ok) !important; }
.gr-sig--rejected { box-shadow: inset 0 1px 0 rgba(255,255,255,.28), 0 0 0 2px var(--danger) !important; }
.gr-sig--pending  { box-shadow: inset 0 1px 0 rgba(255,255,255,.28), 0 0 0 2px var(--warn) !important; }

/* Deliverables progress bar */
.gr-prog { height: 6px; border-radius: 999px; background: #eef1f6; overflow: hidden; }
.gr-prog > span { display: block; height: 100%; border-radius: 999px; background: var(--accent); }
.gr-prog > span.full { background: var(--ok); }

/* Legend */
.gr-legend { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; font-size: .66rem; color: var(--ink-soft); }
.gr-legend > span { display: inline-flex; align-items: center; gap: 5px; }
.gr-key { width: 13px; height: 13px; border-radius: 4px; display: inline-block; }

/* Inline sign buttons (reuse the board's coin language) */
.gr-approve, .gr-reject { width: 28px; height: 28px; padding: 0; border-radius: 8px; border: 1px solid;
  display: inline-flex; align-items: center; justify-content: center; font-size: .82rem; cursor: pointer;
  transition: filter .12s ease, box-shadow .12s ease; }
.gr-approve { background: var(--ok); border-color: var(--ok); color: #fff; }
.gr-approve:hover { filter: brightness(.96); box-shadow: 0 2px 8px rgba(16,185,129,.3); }
.gr-reject { background: var(--danger-soft); border-color: rgba(225,29,72,.22); color: var(--danger); }
.gr-reject:hover { background: var(--danger); border-color: var(--danger); color: #fff; }
.gr-approve:focus-visible, .gr-reject:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--accent-soft); }

@media (prefers-reduced-motion: reduce) { a.gr-cell, .gr-approve, .gr-reject { transition: none; } }

/* Charter "Needs attention" — pulse red while there are critical items. Falls
   back to a static red tint when the viewer prefers reduced motion. */
@keyframes attnbg {
  0%, 100% { background: rgba(220,38,38,.07); }
  50%      { background: rgba(220,38,38,.18); }
}
.cc-head-alert { color: #b02a37; background: rgba(220,38,38,.08);
  animation: attnbg 1.4s ease-in-out infinite; }
.cc-head-alert i { color: var(--danger, #dc2626); }
.cc-head-alert .cc-attn-ic { display: inline-block; transform-origin: center;
  animation: alertpulse 1.15s ease-in-out infinite; }

/* ---------- Drag & drop evidence upload ---------- */
.evidence-drop {
  display: inline-flex; align-items: center; gap: 6px; margin: 0;
  padding: 5px 10px; border-radius: 9px; cursor: pointer;
  border: 1px dashed var(--line); background: #fbfcff; color: var(--ink-soft);
  font-size: .76rem; font-weight: 600; white-space: nowrap;
  transition: border-color .14s ease, background .14s ease, color .14s ease, box-shadow .14s ease;
}
.evidence-drop:hover, .evidence-drop:focus-visible {
  border-color: var(--accent); color: var(--accent); background: var(--accent-soft); outline: none;
}
.evidence-drop i { font-size: .95rem; }
.evidence-drop.dragging {
  border-style: solid; border-color: var(--accent); color: var(--accent-600);
  background: var(--accent-soft); box-shadow: 0 0 0 3px var(--accent-soft);
  transform: translateY(-1px);
}

/* ---------- ISO week badge next to date fields + flatpickr theming ---------- */
.wk-badge {
  display: inline-block; margin-left: 6px; padding: 1px 6px; border-radius: 6px;
  font-size: 0.62rem; font-weight: 700; letter-spacing: 0.03em; white-space: nowrap;
  vertical-align: middle; color: var(--accent-600); background: var(--accent-soft);
}
/* In a table cell the date and its week share one line (app.js wraps the two
   in .wk-field). The field keeps room for a whole date — "2026-09-08" is ten
   characters no wider than a zero, plus padding and border — so the badge never
   takes its place by clipping the date: a column too narrow for both grows. */
.wk-field { display: flex; align-items: center; gap: 6px; min-width: 0; }
.wk-field > input { flex: 0 1 auto; min-width: calc(10ch + 1.65rem); }
.wk-field > .wk-badge { flex: none; margin-left: 0; }
.flatpickr-day.selected, .flatpickr-day.selected:hover,
.flatpickr-day.startRange, .flatpickr-day.endRange { background: var(--accent); border-color: var(--accent); }
.flatpickr-day.today { border-color: var(--accent); }
.flatpickr-weekwrapper .flatpickr-weekday { color: var(--accent-600); }
.flatpickr-weekwrapper span.flatpickr-day { color: var(--ink-soft); font-weight: 700; }
.flatpickr-calendar { box-shadow: var(--shadow); border-radius: 12px; }

/* ---------- Requirement help "?" icon + popover ---------- */
.help-q { color: var(--ink-faint, #9aa6bd); cursor: pointer; font-size: .92rem; vertical-align: -1px;
  transition: color .14s ease, transform .12s ease; }
.help-q:hover, .help-q:focus-visible { color: var(--accent); transform: scale(1.12); outline: none; }
.popover.help-popover { max-width: 340px; border: 1px solid var(--line); border-radius: 12px;
  box-shadow: var(--shadow); }
.popover.help-popover .popover-header { background: var(--accent-soft); color: var(--accent-600);
  font-weight: 700; font-size: .8rem; border-bottom: 1px solid var(--line); border-radius: 12px 12px 0 0; }
.popover.help-popover .popover-body { font-size: .82rem; color: var(--ink); line-height: 1.5; }

/* ---------- Project Charter (premium cockpit) ---------- */
.ch-hero { position:relative; overflow:hidden; border-radius:20px; color:#eef3ff; padding:20px 24px; margin-bottom:14px;
  background:
    radial-gradient(120% 130% at 100% 0%, rgba(56,189,248,.20), transparent 55%),
    radial-gradient(120% 130% at 0% 100%, rgba(139,92,246,.18), transparent 55%),
    linear-gradient(120deg,#0a1020 0%,#122a52 55%,#1a3a78 100%);
  border:1px solid rgba(139,92,246,.22); box-shadow: var(--shadow-lg), inset 0 1px 0 rgba(255,255,255,.07); }
.ch-hero-top { display:flex; align-items:flex-start; justify-content:space-between; gap:16px; flex-wrap:wrap;
  position:relative; z-index:1; }
.ch-hero h1 { font-size:1.5rem; font-weight:800; letter-spacing:-.015em; margin:0; color:#fff; }
.ch-hero .ch-sub { color:#9fb0da; font-size:.78rem; margin-top:3px; }
.ch-hero .ch-tag { font-size:.6rem; font-weight:800; letter-spacing:.1em; text-transform:uppercase;
  background:rgba(255,255,255,.12); color:#dfe7fb; padding:3px 8px; border-radius:6px; }
.ch-hero .ch-tag.ok{ background:rgba(52,211,153,.2); color:#6ee7b7; } .ch-hero .ch-tag.warn{ background:rgba(251,191,36,.2); color:#fcd34d; }
.btn-ghost { background:rgba(255,255,255,.09); border:1px solid rgba(255,255,255,.16); color:#dfe7fb; }
.btn-ghost:hover { background:rgba(255,255,255,.18); color:#fff; border-color:rgba(255,255,255,.28); }
.ch-hero-divider { height:1px; margin:16px 0 14px; position:relative; z-index:1;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.14) 15%,rgba(255,255,255,.14) 85%,transparent); }
.ch-metrics { display:flex; flex-wrap:wrap; gap:14px 0; position:relative; z-index:1; }
.ch-metric { flex:1 1 150px; min-width:130px; padding:0 20px; border-left:1px solid rgba(255,255,255,.1); }
.ch-metric:first-child { border-left:none; padding-left:0; }
.cm-label { font-size:.58rem; font-weight:800; letter-spacing:.12em; text-transform:uppercase; color:#8fa0c8; }
.cm-value { font-size:1.4rem; font-weight:800; line-height:1.1; color:#fff; margin-top:3px; letter-spacing:-.01em; }
.cm-sub { font-size:.68rem; color:#9fb0da; margin-top:2px; }
.cm-ok{ color:#6ee7b7!important; } .cm-warn{ color:#fcd34d!important; } .cm-danger{ color:#fda4af!important; }
.cm-bar { height:4px; border-radius:3px; background:rgba(255,255,255,.14); margin-top:8px; overflow:hidden; }
.cm-bar > span { display:block; height:100%; border-radius:3px; background:linear-gradient(90deg,#38bdf8,#818cf8); }

/* ============================================================
   PROJECT CHARTER — premium card system
   Base: "Refined Enterprise" instrument-panel shell (one card
   language) + grafts: phase-number qt-medallions, gradient
   progress bars, budget mini-bar, segmented risk strip,
   severity left-rails, and a single hero-tuned top line on the
   full-width feature card.

   DROP-IN: paste this whole block REPLACING the current
   "compact charter cards" section in static/css/app.css
   (lines ~598–675, i.e. `.charter-card` … `.cc-row .k`).
   The qt-* rules are reproduced VERBATIM inside so nothing is
   lost. Leave the `.cc-head-alert` rules (~519–527) untouched.
   All 9 header icons are styled IN PLACE via
   `.cc-head > .bi:first-child` — no span-wrapping required.
   ============================================================ */

/* ---- shared shell: raised, quietly premium "instrument panel" ---- */
.charter-card{
  --cc:var(--accent); --cc-soft:var(--accent-soft);
  position:relative;
  background:linear-gradient(180deg,#ffffff 0%, #fbfcfe 100%);
  border:1px solid var(--line);
  border-radius:var(--radius);                 /* 16px, up from flat 14 */
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.9),        /* 1px top highlight */
    0 1px 2px rgba(16,24,40,.04),              /* contact shadow */
    0 8px 20px -12px rgba(16,24,40,.16);       /* soft ambient lift */
  margin-bottom:14px; overflow:hidden;
  transition:box-shadow .18s ease, border-color .18s ease;
}
.charter-card:hover{
  border-color:#e0e6f1;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.9),
    0 1px 2px rgba(16,24,40,.05),
    0 14px 30px -14px rgba(16,24,40,.22);
}

/* full-width Phase-timeline anchor: one elevation step higher + a
   single restrained top-accent line tuned to the hero's sky->blue glow */
.charter-card--feature{
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.9),
    0 1px 2px rgba(16,24,40,.05),
    0 16px 34px -16px rgba(16,24,40,.22);
}
.charter-card--feature::before{
  content:""; position:absolute; inset:0 0 auto 0; height:3px;
  background:linear-gradient(90deg,var(--sky),var(--accent));
}

/* ---- per-card accent (chip hue + hover wash). Darker hues chosen so
   the small chip icon holds AA contrast on its pale tint ---- */
.cc-accent-blue    { --cc:#2563eb; --cc-soft:#eaf1fe; }
.cc-accent-sky     { --cc:#0284c7; --cc-soft:#e5f4fd; }
.cc-accent-indigo  { --cc:#6366f1; --cc-soft:#ecedfd; }
.cc-accent-violet  { --cc:#8b5cf6; --cc-soft:#f1ecfe; }
.cc-accent-amber   { --cc:#d97706; --cc-soft:#fbeed3; }
.cc-accent-emerald { --cc:#059669; --cc-soft:#e2f5ed; }
.cc-accent-teal    { --cc:#0d9488; --cc-soft:#e0f4f1; }
.cc-accent-rose    { --cc:#e11d48; --cc-soft:#fce7ec; }
.cc-accent-slate   { --cc:#5b6b8c; --cc-soft:#edf0f6; }

/* ---- header + soft-tinted icon chip (styled in place, no HTML wrap) ---- */
.cc-head{ display:flex; align-items:center; gap:9px; padding:10px 14px;
  border-bottom:1px solid var(--line);
  font-size:.64rem; font-weight:800; letter-spacing:.09em;
  text-transform:uppercase; color:var(--ink-soft); }
.cc-head:not(.cc-head-alert){
  background:linear-gradient(180deg, rgba(248,250,253,.6), rgba(255,255,255,0)); }
/* leading icon -> soft chip; (0,3,0) beats legacy `.cc-head-alert i` (0,1,1)
   and `.cc-attn-ic` display (0,2,0), so the chip wins while the pulse keeps */
.cc-head > .bi:first-child{
  width:26px; height:26px; flex:none; border-radius:8px;
  display:inline-grid; place-items:center;
  font-size:.9rem; line-height:1;
  color:var(--cc); background:var(--cc-soft);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.7),
    inset 0 0 0 1px rgba(15,23,42,.04),
    0 1px 2px rgba(16,24,40,.06);
  transition:transform .18s cubic-bezier(.2,.75,.3,1.2), box-shadow .18s ease;
}
.charter-card:hover .cc-head > .bi:first-child{
  transform:translateY(-1px);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.8),
    inset 0 0 0 1px rgba(15,23,42,.05),
    0 3px 7px -1px rgba(16,24,40,.12);
}
.cc-head .cc-link{ margin-left:auto; font-size:.68rem; text-transform:none;
  letter-spacing:0; font-weight:600; text-decoration:none; color:var(--cc); }
.cc-head .cc-count{ margin-left:auto; }
.cc-body{ padding:10px 12px; }
/* Notice board — frozen height, scrolls once full (like the project chat) */
.cc-body.notice-scroll{ max-height:360px; overflow-y:auto; }
.cc-body.notice-scroll::-webkit-scrollbar{ width:8px; }
.cc-body.notice-scroll::-webkit-scrollbar-thumb{ background:rgba(15,23,42,.18); border-radius:8px; }

/* ============ Project team chat — WhatsApp-style, near-real-time ============ */
.chat-card .cc-head{ }
.chat-live{ display:inline-flex; align-items:center; gap:6px; margin-left:auto;
  font-size:.6rem; font-weight:700; letter-spacing:.06em; text-transform:uppercase;
  color:#0d9488; }
.chat-live-dot{ width:7px; height:7px; border-radius:50%; background:#22c55e;
  box-shadow:0 0 0 3px rgba(34,197,94,.18); animation:chatLive 1.8s ease-in-out infinite; }
@keyframes chatLive{ 0%,100%{ opacity:1; } 50%{ opacity:.35; } }

.chat-scroll{ height:340px; overflow-y:auto;   /* frozen size — always scrolls when full */
  padding:12px 12px 8px; display:flex; flex-direction:column; gap:6px;
  background:#ece5dd;                         /* messenger wallpaper */
  background-image:
    radial-gradient(rgba(255,255,255,.55) 1px, transparent 1px),
    radial-gradient(rgba(15,23,42,.028) 1px, transparent 1px);
  background-size:22px 22px, 22px 22px; background-position:0 0, 11px 11px;
  scroll-behavior:smooth; }
/* Pin the thread to the bottom (newest visible) while keeping the top fully
   scrollable — auto margin collapses to 0 once messages overflow the box. */
.chat-scroll > :first-child{ margin-top:auto; }
.chat-scroll::-webkit-scrollbar{ width:8px; }
.chat-scroll::-webkit-scrollbar-thumb{ background:rgba(15,23,42,.18); border-radius:8px; }

.chat-msg{ display:flex; gap:7px; max-width:90%; align-items:flex-end; }
.chat-msg:not(.me){ align-self:flex-start; }
.chat-msg.me{ align-self:flex-end; flex-direction:row-reverse; }
.chat-avatar{ flex:0 0 26px; width:26px; height:26px; border-radius:50%;
  display:inline-flex; align-items:center; justify-content:center; color:#fff;
  font-weight:700; font-size:.6rem; letter-spacing:.3px; background:var(--a,#94a3b8);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.28), 0 1px 3px rgba(16,24,40,.18); }
.chat-bubble{ position:relative; padding:5px 9px 4px; border-radius:11px;
  background:#fff; box-shadow:0 1px 1.5px rgba(16,24,40,.14); font-size:.8rem;
  line-height:1.34; color:var(--ink); min-width:58px; max-width:100%; }
.chat-msg:not(.me) .chat-bubble{ border-top-left-radius:3px; }       /* tail notch */
.chat-msg.me .chat-bubble{ background:#d9fdd3; border-top-right-radius:3px; }
.chat-sender{ font-weight:700; font-size:.66rem; margin-bottom:1px; line-height:1.1; }
.chat-text{ white-space:pre-wrap; overflow-wrap:anywhere; }
.chat-text a{ color:var(--accent-600); }
.chat-time{ font-size:.58rem; color:rgba(15,23,42,.45); text-align:right;
  margin-top:1px; font-variant-numeric:tabular-nums; user-select:none; }

.chat-empty{ margin:auto; text-align:center; color:var(--ink-soft); font-size:.76rem;
  line-height:1.4; padding:26px 10px; }
.chat-empty i{ font-size:1.7rem; display:block; margin-bottom:8px; opacity:.5; }

.chat-input{ display:flex; align-items:center; gap:9px; padding:9px 11px;
  border-top:1px solid var(--line); background:#fff; }
.chat-field{ flex:1 1 auto; min-width:0; border:1px solid var(--line);
  border-radius:999px; padding:7px 14px; font-size:.82rem; background:#f5f7fb;
  color:var(--ink); outline:none; transition:border-color .14s ease, box-shadow .14s ease, background .14s ease; }
.chat-field::placeholder{ color:var(--ink-soft); }
.chat-field:focus{ border-color:var(--accent); background:#fff; box-shadow:0 0 0 3px var(--accent-soft); }
.chat-send{ flex:0 0 34px; width:34px; height:34px; border-radius:50%; border:none;
  display:inline-grid; place-items:center; color:#fff; font-size:.92rem; cursor:pointer;
  background:linear-gradient(135deg,#25d366,#128c7e);   /* WhatsApp green */
  box-shadow:0 3px 9px rgba(18,140,126,.38), inset 0 1px 0 rgba(255,255,255,.25);
  transition:transform .12s ease, filter .12s ease; }
.chat-send:hover{ transform:translateY(-1px); filter:brightness(1.06); }
.chat-send:active{ transform:translateY(0); }
.chat-send:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; }

/* critical state: chip follows the red alert header (rule placed AFTER the
   base chip so it wins on equal specificity); pulse animation still applies */
.cc-head-alert > .bi:first-child{
  color:var(--danger); background:var(--danger-soft);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.6),
    inset 0 0 0 1px rgba(225,29,72,.18),
    0 1px 2px rgba(225,29,72,.14); }

/* ---- Needs attention: severity left-rail + ringed icon squares ---- */
.charter-attn{ position:relative; display:flex; align-items:center; gap:10px;
  padding:8px 10px 8px 14px; border-radius:10px; text-decoration:none;
  transition:background .12s ease, transform .12s ease; }
.charter-attn::before{ content:""; position:absolute; left:4px; top:8px; bottom:8px;
  width:3px; border-radius:2px; background:#cbd3e1; }
.charter-attn.danger::before{ background:var(--danger); }
.charter-attn.warn::before  { background:var(--warn); }
.charter-attn.info::before  { background:var(--accent); }
.charter-attn:hover{ background:var(--cc-soft); transform:translateX(2px); }
.charter-attn .a-txt{ flex:1 1 auto; color:var(--ink); font-size:.86rem; font-weight:500; }
.charter-ico{ width:26px; height:26px; flex:none; border-radius:8px; display:grid;
  place-items:center; font-size:.8rem; }
.charter-ico.danger{ background:var(--danger-soft); color:var(--danger);
  box-shadow:inset 0 0 0 1px rgba(225,29,72,.18); }
.charter-ico.warn{ background:var(--warn-soft); color:var(--warn);
  box-shadow:inset 0 0 0 1px rgba(217,119,6,.18); }
.charter-ico.info{ background:var(--accent-soft); color:var(--accent);
  box-shadow:inset 0 0 0 1px rgba(37,99,235,.16); }

/* ---- Phase progress: qt-echo medallion number chips + gradient bars ---- */
.charter-phase{ display:flex; align-items:center; gap:10px; padding:5px 6px;
  border-radius:9px; text-decoration:none; transition:background .12s ease; }
.charter-phase:hover{ background:var(--cc-soft); }
.charter-phase-current{ background:var(--cc-soft); }
.charter-phase-n{ width:24px; height:24px; flex:none; border-radius:8px;
  display:grid; place-items:center; font-weight:800; font-size:.72rem;
  color:#64748b; background:linear-gradient(155deg,#f2f5fa,#dde4ee);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.9),
    inset 0 -2px 3px rgba(16,24,40,.09),
    0 1px 1px rgba(16,24,40,.05); }
.charter-phase-n.current{ color:#fff;
  background:linear-gradient(155deg,var(--sky) 8%, var(--accent-600) 92%);
  box-shadow:
    inset 0 1.5px 0 rgba(255,255,255,.5),
    inset 0 -3px 5px rgba(0,0,0,.22),
    0 4px 9px -3px rgba(37,99,235,.55); }
.charter-phase-n.done{ color:#fff;
  background:linear-gradient(155deg,#34d399 8%, #059669 92%);
  box-shadow:
    inset 0 1.5px 0 rgba(255,255,255,.5),
    inset 0 -3px 5px rgba(0,0,0,.22),
    0 4px 9px -3px rgba(5,150,105,.5); }
.charter-phase .progress{ border-radius:99px; background:#eef1f7;
  box-shadow:inset 0 1px 1px rgba(16,24,40,.06); overflow:hidden; }
.charter-phase .progress-bar{ border-radius:99px; }
.charter-phase .progress-bar.bg-primary{ background:linear-gradient(90deg,var(--sky),var(--accent))!important; }
.charter-phase .progress-bar.bg-success{ background:linear-gradient(90deg,#34d399,var(--emerald))!important; }
.charter-phase .progress-bar.bg-secondary{ background:linear-gradient(90deg,#d3dae6,#aab4c6)!important; }

/* ---- Premium Quality-tools tiles — glossy 3D medallions (VERBATIM, kept) ---- */
.qt-tool { display:flex; flex-direction:column; align-items:center; gap:5px;
  padding:13px 4px 10px; border-radius:15px; text-decoration:none;
  border:1px solid transparent; transition:background .2s ease, border-color .2s ease; }
.qt-tool:hover { background:linear-gradient(180deg, rgba(148,163,184,.10), rgba(148,163,184,0));
  border-color:var(--line); }
.qt-ico {
  width:48px; height:48px; border-radius:14px; display:grid; place-items:center;
  color:#fff; font-size:1.4rem; line-height:1;
  background:linear-gradient(155deg, var(--qt-c1) 8%, var(--qt-c2) 92%);
  box-shadow:
    0 7px 15px -4px var(--qt-shadow),
    0 2px 4px rgba(16,24,40,.14),
    inset 0 1.5px 0 rgba(255,255,255,.6),
    inset 0 -4px 7px rgba(0,0,0,.22);
  transition:transform .22s cubic-bezier(.2,.75,.3,1.45), box-shadow .22s ease;
  will-change:transform; }
.qt-ico i { filter:drop-shadow(0 1.5px 1.5px rgba(0,0,0,.3)); }
.qt-tool:hover .qt-ico {
  transform:translateY(-4px) scale(1.22) rotate(-4deg);
  box-shadow:
    0 16px 26px -7px var(--qt-shadow),
    0 4px 8px rgba(16,24,40,.18),
    inset 0 2px 0 rgba(255,255,255,.7),
    inset 0 -4px 8px rgba(0,0,0,.25); }
.qt-tool:active .qt-ico { transform:translateY(-1px) scale(1.1); }
.qt-count { font-weight:800; font-size:1.15rem; line-height:1; color:var(--ink);
  font-variant-numeric:tabular-nums; }
.qt-label { font-size:.64rem; color:var(--ink-soft); text-align:center; line-height:1.2; }
.qt-tool:hover .qt-count { color:var(--qt-c2); }
.qt-fmea  { --qt-c1:#fbbf24; --qt-c2:#f59e0b; --qt-shadow:rgba(245,158,11,.55); }
.qt-cplan { --qt-c1:#34d399; --qt-c2:#059669; --qt-shadow:rgba(5,150,105,.5); }
.qt-ppap  { --qt-c1:#60a5fa; --qt-c2:#2563eb; --qt-shadow:rgba(37,99,235,.5); }
.qt-msa   { --qt-c1:#c084fc; --qt-c2:#7c3aed; --qt-shadow:rgba(124,58,237,.5); }
.qt-spc   { --qt-c1:#22d3ee; --qt-c2:#0891b2; --qt-shadow:rgba(8,145,178,.5); }
@media (prefers-reduced-motion: reduce) {
  .qt-tool:hover .qt-ico { transform:scale(1.08); }
}

/* ---- Notice board: accent hover wash + haloed semantic dots ---- */
.charter-notice{ display:flex; gap:10px; text-decoration:none; padding:7px 8px;
  border-radius:9px; transition:background .12s ease; }
.charter-notice:hover{ background:var(--cc-soft); }
.charter-notice:hover .cn-title{ color:var(--cc); }
.charter-dot{ width:7px; height:7px; border-radius:50%; margin-top:5px; flex:none;
  background:#94a3b8; box-shadow:0 0 0 3px rgba(148,163,184,.14); }
.charter-dot-warning{ background:var(--warn); box-shadow:0 0 0 3px rgba(217,119,6,.14); }
.charter-dot-success{ background:var(--emerald); box-shadow:0 0 0 3px rgba(16,185,129,.14); }
.charter-dot-danger { background:var(--danger); box-shadow:0 0 0 3px rgba(225,29,72,.14); }
.charter-dot-info   { background:var(--accent); box-shadow:0 0 0 3px rgba(37,99,235,.14); }
.charter-unread::after{ content:""; display:inline-block; width:6px; height:6px;
  border-radius:50%; background:var(--cc); margin-left:6px; vertical-align:middle; }

/* ---- Budget mini spend-bar (actual of approved) ---- */
.cc-minibar{ height:7px; border-radius:99px; margin-top:10px; background:#eef1f7;
  overflow:hidden; box-shadow:inset 0 1px 1px rgba(16,24,40,.06); }
.cc-minibar > span{ display:block; height:100%; max-width:100%; border-radius:99px;
  background:linear-gradient(90deg,#34d399,var(--emerald)); }
.cc-minibar.high > span{ background:linear-gradient(90deg,#fbbf24,var(--amber)); }  /* ≥90% consumed: caution, not a "good" green */
.cc-minibar.over > span{ background:linear-gradient(90deg,var(--amber),var(--danger)); }

/* Amber value text lifted off the white-on-gold ~1.6:1 floor (auditor figures) */
.charter-card .text-warning{ color:#b45309 !important; }

/* ---- Risk assessment segmented profile strip (H / M / L) ---- */
.cc-riskbar{ display:flex; gap:2px; height:8px; margin:6px 0 2px; border-radius:99px;
  overflow:hidden; background:#eef1f7; box-shadow:inset 0 1px 1px rgba(16,24,40,.06); }
.cc-riskbar > span{ display:block; min-width:0; }
.cc-riskbar .rs-h{ background:linear-gradient(90deg,#fb7185,var(--danger)); }
.cc-riskbar .rs-m{ background:linear-gradient(90deg,#fbbf24,var(--amber)); }
.cc-riskbar .rs-l{ background:linear-gradient(90deg,#34d399,var(--emerald)); }

/* ---- key/value rows + opt-in hairline list (Budget, Key info, Core team) ---- */
.cc-row{ display:flex; justify-content:space-between; align-items:center;
  font-size:.8rem; padding:3px 0; }
.cc-row .k{ color:var(--ink-soft); }
.cc-rows .cc-row{ padding:6px 0; border-top:1px solid var(--line); }
.cc-rows .cc-row:first-child{ border-top:0; padding-top:2px; }
.cc-rows .cc-row .v{ font-weight:600; color:var(--ink); }

/* ---- shared focus-visible rings (adopt the card accent) ---- */
.charter-attn:focus-visible,
.charter-phase:focus-visible,
.charter-notice:focus-visible,
.qt-tool:focus-visible{
  outline:2px solid var(--cc); outline-offset:2px; border-radius:10px; }

/* ---- reduced motion: keep all depth, drop movement ---- */
@media (prefers-reduced-motion: reduce){
  .charter-card, .cc-head > .bi:first-child,
  .charter-attn, .charter-phase, .charter-notice{ transition:none; }
  .charter-card:hover .cc-head > .bi:first-child{ transform:none; }
  .charter-attn:hover{ transform:none; }
}

/* ---------- FMEA AIAG-VDA banded worksheet (premium · frozen header + columns) ---------- */
/* Fixed-viewport grid so the header AND the Op/Step columns stay put through the
   long horizontal scroll — the single biggest UX win for hours-long editing. */
.fmea-scroll { max-height: calc(100vh - 250px); overflow: auto;
  border-radius: 0 0 var(--radius) var(--radius); }
.fmea-scroll::-webkit-scrollbar { width: 12px; height: 12px; }
.fmea-scroll::-webkit-scrollbar-thumb { background: rgba(100,116,139,.4); border-radius: 8px;
  border: 3px solid transparent; background-clip: content-box; }
.fmea-scroll::-webkit-scrollbar-thumb:hover { background: rgba(100,116,139,.6); background-clip: content-box; }

.fmea-grid { border-collapse: separate; border-spacing: 0; }
.fmea-grid > * > tr > td, .fmea-grid > * > tr > th {
  border: 0; border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); }

/* frozen header (two rows) */
.fmea-grid thead th { position: sticky; z-index: 3; }
.fmea-groups th { top: 0; height: 30px; color: #fff; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; font-size: .62rem; text-align: center; padding: .42rem .5rem; }
.fmea-cols th { top: 30px; font-weight: 700; vertical-align: bottom; line-height: 1.18;
  font-size: .6rem; padding: .42rem .5rem; text-transform: uppercase; letter-spacing: .02em; }

/* band palette — CSS-var driven so Midnight can retint it */
.fmea-grp-structure { background: var(--fm-struct, #475569); }
.fmea-grp-function  { background: var(--fm-func,   #2563eb); }
.fmea-grp-failure   { background: var(--fm-fail,   #be123c); }
.fmea-grp-risk      { background: var(--fm-risk,   #b45309); }
.fmea-grp-opt       { background: var(--fm-opt,    #047857); }
.fmea-cols th.fmea-grp-structure { background: var(--fm-struct-s, #eef2f7); color: #334155; }
.fmea-cols th.fmea-grp-function  { background: var(--fm-func-s,   #eaf1fe); color: #1d4ed8; }
.fmea-cols th.fmea-grp-failure   { background: var(--fm-fail-s,   #fdeaef); color: #be123c; }
.fmea-cols th.fmea-grp-risk      { background: var(--fm-risk-s,   #fdf3e3); color: #92400e; }
.fmea-cols th.fmea-grp-opt       { background: var(--fm-opt-s,    #e7f7ef); color: #047857; }
.fmea-op-h { background: #1e293b; color: #fff; }

/* frozen first columns: Op (52px) + Process Step */
.fmea-sticky-op   { position: sticky; left: 0;    z-index: 2; background: var(--card); }
.fmea-sticky-step { position: sticky; left: 52px; z-index: 2; background: var(--card);
  box-shadow: 6px 0 8px -6px rgba(16,24,40,.28); }
.fmea-grid thead th.fmea-sticky-op, .fmea-grid thead th.fmea-sticky-step { z-index: 6; }

/* active row: light up the whole wide line so you never lose your place */
.fmea-grid tbody tr:hover > td { background: var(--fm-hover, #f4f8ff); }
.fmea-grid tbody tr:hover > .fmea-sticky-op,
.fmea-grid tbody tr:hover > .fmea-sticky-step { background: #ecf2fe; }
.fmea-grid tbody tr:focus-within > td { background: var(--fm-hover, #f4f8ff); }
.fmea-grid tbody tr:focus-within > .fmea-sticky-op,
.fmea-grid tbody tr:focus-within > .fmea-sticky-step { background: #ecf2fe; }
.fmea-grid .cell-input { min-height: 26px; }

/* Midnight retint */
:root[data-theme="midnight"]{
  --fm-struct:#3a4a68; --fm-func:#1e4fb0; --fm-fail:#8f2540; --fm-risk:#7a4a12; --fm-opt:#0f6b4a;
  --fm-struct-s:#1c2740; --fm-func-s:#152238; --fm-fail-s:#331821; --fm-risk-s:#33260c; --fm-opt-s:#0f2a20;
  --fm-hover:#1a2540;
}
[data-theme="midnight"] .fmea-cols th.fmea-grp-structure { color:#cbd6ea; }
[data-theme="midnight"] .fmea-cols th.fmea-grp-function  { color:#8fb4ff; }
[data-theme="midnight"] .fmea-cols th.fmea-grp-failure   { color:#fb7185; }
[data-theme="midnight"] .fmea-cols th.fmea-grp-risk      { color:#fbbf24; }
[data-theme="midnight"] .fmea-cols th.fmea-grp-opt       { color:#34d399; }
[data-theme="midnight"] .fmea-grid tbody tr:hover > .fmea-sticky-op,
[data-theme="midnight"] .fmea-grid tbody tr:hover > .fmea-sticky-step { background:#1e2941; }

/* Auto-growing free-text cells: the row height follows the words entered */
.fmea-grid tbody td { vertical-align: top; }
textarea.cell-grow { resize: none; overflow: hidden; min-height: 26px; height: 26px;
  line-height: 1.34; white-space: pre-wrap; overflow-wrap: anywhere; font-family: inherit;
  display: block; }
/* Textarea knowledge-base autocomplete (datalist doesn't bind to <textarea>) */
.cell-ac { position: absolute; z-index: 1090; background: var(--card); border: 1px solid var(--line);
  border-radius: 9px; box-shadow: var(--shadow); max-height: 240px; overflow: auto; padding: 4px;
  font-size: .78rem; min-width: 170px; max-width: 380px; }
.cell-ac-item { padding: 5px 9px; border-radius: 6px; cursor: pointer; color: var(--ink);
  white-space: normal; line-height: 1.3; }
.cell-ac-item:hover, .cell-ac-item.active { background: var(--accent-soft); color: var(--accent-600); }

/* FMEA risk Pareto — three premium 3D charts (RPN · Occurrence · Detection) */
.fmea-pareto-box { position: relative; height: 330px; }
.pareto-panel { border: 1px solid var(--line); border-radius: 13px; padding: 11px 13px 6px;
  background: var(--card); height: 100%; box-shadow: var(--shadow-xs); }
.pareto-title { font-size: .82rem; font-weight: 700; margin-bottom: 4px; display: flex;
  align-items: center; gap: 7px; }
.pareto-title .text-muted-2 { font-weight: 500; font-size: .68rem; }
.pareto-dot { width: 11px; height: 11px; border-radius: 3px; display: inline-block; flex: none;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.4); }
.pareto-note { font-size: .68rem; color: var(--ink-soft); line-height: 1.35; padding: 5px 2px 4px; }

/* ---------- Control Plan: merged operation cells (rowspan) ---------- */
.cp-op-cell { vertical-align: top; background: color-mix(in srgb, var(--accent) 4%, var(--card));
  border-right: 1px solid var(--line-strong, #cbd5e1); }

/* ---------- FMEA list (premium rows + risk profile) ---------- */
.fmea-list td { vertical-align: middle; }
.fmea-list-row { cursor: pointer; transition: background .12s ease; }
.fmea-list-row td:first-child { border-left: 3px solid transparent; }
.fmea-list-row.risk-high td:first-child { border-left-color: var(--danger); }
.fmea-list-row.risk-med td:first-child { border-left-color: var(--warn); }
.fmea-list-row:hover { background: var(--accent-soft); }
.risk-bar { display: flex; height: 8px; border-radius: 5px; overflow: hidden; background: var(--line);
  gap: 1px; max-width: 180px; }
.risk-seg { display: block; }
.rs-high { background: var(--danger); }
.rs-med { background: var(--warn); }
.rs-low { background: var(--ok); }
.rs-none { background: var(--line-strong, #cbd5e1); }
.risk-legend { display: flex; gap: 9px; margin-top: 5px; }
.status-chip { display: inline-flex; align-items: center; gap: 6px; font-size: .74rem; font-weight: 600;
  padding: 3px 11px; border-radius: 999px; border: 1px solid var(--line); background: var(--card); }
.status-chip .dot { width: 7px; height: 7px; border-radius: 50%; }
.status-chip.ok { color: var(--ok); } .status-chip.ok .dot { background: var(--ok); }
.status-chip.warn { color: var(--warn); } .status-chip.warn .dot { background: var(--warn); }
.status-chip.muted { color: var(--ink-soft); } .status-chip.muted .dot { background: var(--ink-soft); }

/* ---------- FMEA detail hero (premium header + KPI chips) ---------- */
.fmea-hero { position: relative; overflow: hidden; background: var(--card);
  border: 1px solid var(--line); border-radius: 18px; box-shadow: var(--shadow-sm);
  padding: 16px 22px 18px; }
.fmea-hero::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 5px;
  background: linear-gradient(180deg, var(--accent), var(--accent-600)); }
.fmea-hero-draft::before { background: linear-gradient(180deg, #94a3b8, #64748b); }
.fmea-hero-in_review::before { background: linear-gradient(180deg, var(--warn), #c2820a); }
.fmea-hero-released::before { background: linear-gradient(180deg, var(--ok), #0f9d6e); }
.fmea-hero-top { display: flex; align-items: flex-start; gap: 14px; }
.fmea-hero-back { flex: none; }
.fmea-hero-id { min-width: 0; }
.fmea-hero-title { font-size: 1.42rem; font-weight: 800; letter-spacing: -.01em; }
.fmea-hero-sub { color: var(--ink-soft); font-size: .82rem; margin-top: 3px; }
.fmea-hero-actions { margin-left: auto; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }
.fmea-stepper { display: inline-flex; align-items: center; font-size: .68rem; font-weight: 600; }
.fs-step { padding: 4px 11px; color: var(--ink-soft); background: var(--bg); border: 1px solid var(--line);
  border-right-width: 0; white-space: nowrap; }
.fs-step:first-child { border-radius: 8px 0 0 8px; }
.fs-step:last-child { border-radius: 0 8px 8px 0; border-right-width: 1px; }
.fs-step.done { color: var(--ok); background: color-mix(in srgb, var(--ok) 12%, transparent); }
.fs-step.on { color: #fff; background: var(--accent); border-color: var(--accent); font-weight: 700; }
.fmea-hero-kpis { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 15px; }
.fmea-kpi { display: flex; align-items: center; gap: 11px; background: var(--bg); border: 1px solid var(--line);
  border-radius: 13px; padding: 9px 15px 9px 11px; min-width: 148px; transition: box-shadow .15s ease, transform .15s ease; }
.fmea-kpi:hover { box-shadow: var(--shadow-sm); transform: translateY(-1px); }
.fk-ic { width: 36px; height: 36px; border-radius: 10px; display: flex; align-items: center; justify-content: center;
  color: #fff; font-size: 1.05rem; flex: none; box-shadow: var(--shadow-xs); background: #64748b; }
.fk-ic.g-indigo { background: linear-gradient(135deg, #818cf8, #4f46e5); }
.fk-ic.g-rose { background: linear-gradient(135deg, #fb7185, #e11d48); }
.fk-ic.g-amber { background: linear-gradient(135deg, #fbbf24, #d97706); }
.fk-ic.g-emerald { background: linear-gradient(135deg, #34d399, #059669); }
.fk-val { font-size: 1.3rem; font-weight: 800; line-height: 1; }
.fk-lbl { font-size: .64rem; color: var(--ink-soft); text-transform: uppercase; letter-spacing: .4px; margin-top: 3px; font-weight: 600; }

/* ---------- Configurable risk colours (RPN cell) ----------
   The worksheet RPN cell is coloured from the company Risk-display preference
   (threshold + colour per band; --rc carries the chosen hex). The high band can
   blink ("intermittent") — a soft pulsing glow + fade that works in any colour. */
.rpn-badge { display: inline-block; min-width: 2.4em; padding: .32em .7em; border-radius: 999px;
  font-weight: 800; font-size: .74rem; line-height: 1; text-align: center; letter-spacing: .2px;
  color: var(--rc, #334155);
  background: color-mix(in srgb, var(--rc, #64748b) 15%, transparent);
  border: 1px solid color-mix(in srgb, var(--rc, #64748b) 34%, transparent); }
.rpn-blink { animation: riskBlink 1.05s ease-in-out infinite; will-change: box-shadow, opacity; }
@keyframes riskBlink {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--rc, #e11d48) 55%, transparent); opacity: 1; }
  50% { box-shadow: 0 0 0 5px color-mix(in srgb, var(--rc, #e11d48) 0%, transparent); opacity: .4; }
}
@media (prefers-reduced-motion: reduce) { .rpn-blink { animation: none; } }

/* ---------- Risk-display settings preview ---------- */
.risk-swatch { width: 100%; height: 46px; border-radius: 10px; display: flex; align-items: center;
  justify-content: center; font-weight: 800; color: #fff; box-shadow: var(--shadow-xs);
  text-shadow: 0 1px 2px rgba(0,0,0,.25); }
.risk-color-field { display: flex; align-items: center; gap: 10px; }
.risk-color-field input[type="color"] { width: 50px; height: 44px; padding: 2px; border: 1px solid var(--line);
  border-radius: 10px; background: var(--card); cursor: pointer; }
/* Three-band editor rows (red / yellow / green): colour + threshold in one line */
.band-row { display: flex; align-items: center; gap: 14px; padding: 13px 2px; border-bottom: 1px solid var(--line); }
.band-row:last-child { border-bottom: 0; }
.band-row-main { flex: 1 1 auto; min-width: 0; }
.band-row-title { font-weight: 700; font-size: .92rem; display: flex; align-items: center; gap: 8px; }
.band-dot { width: 14px; height: 14px; border-radius: 4px; display: inline-block; flex: none;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.45); }
.band-row-cond { font-size: .82rem; color: var(--ink-soft); margin-top: 4px; display: flex;
  align-items: center; gap: 7px; flex-wrap: wrap; }
.band-input { width: 88px; display: inline-block; font-weight: 800; text-align: center; }
.band-blink { flex: none; padding-left: 2px; }

/* ---------- RPN risk-action worklist ---------- */
.ap-table td { vertical-align: top; }
.ap-overdue { background: color-mix(in srgb, var(--danger) 7%, transparent); }
.ap-due-late { color: var(--danger); font-weight: 700; border-color: color-mix(in srgb, var(--danger) 45%, var(--line)); }
.ap-residual { display: inline-flex; gap: 4px; }
.ap-residual .cell-input { width: 46px; padding-left: 4px; padding-right: 4px; }
.ap-reduction { font-size: .68rem; color: var(--ink-soft); margin-top: 3px; font-weight: 700; }
.ap-reduction.down { color: var(--ok); }

/* ---------- Live consistency-check panel ---------- */
.checks-card.checks-clean { border-color: color-mix(in srgb, var(--ok) 40%, var(--line)); }
.check-tag { flex: none; min-width: 84px; text-align: center; font-size: .64rem; letter-spacing: .3px; text-transform: uppercase; }

/* ---------- Process risk tree (collapsible SVG mindmap) ---------- */
.tree-toolbar { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; }
.tree-scroll { overflow: auto; max-height: 560px; border: 1px solid var(--line); border-radius: 12px;
  background: var(--bg); background-image: radial-gradient(var(--line) .8px, transparent .8px);
  background-size: 22px 22px; }
#risk-tree-svg { display: block; }
.tree-link { fill: none; stroke: var(--line-strong, var(--line)); stroke-width: 1.4; }
.tree-rect { fill: var(--card); stroke: var(--line); stroke-width: 1.2; filter: drop-shadow(0 1px 1px rgba(0,0,0,.05)); }
.tree-root .tree-rect { fill: #1f2a44; stroke: #1f2a44; }
.tree-root .tree-label { fill: #fff; font-weight: 800; }
.tree-op .tree-rect { fill: var(--card-raised, var(--card)); stroke: var(--line-strong, var(--line)); }
.tree-op .tree-label { font-weight: 700; }
.tree-label { fill: var(--ink); font-size: 12px; font-family: Inter, system-ui, sans-serif; pointer-events: none; }
.tree-detail .tree-rect { fill: var(--bg); stroke: var(--line); stroke-dasharray: 3 2; }
.tree-detail .tree-label { fill: var(--ink-soft); font-size: 11px; }
.tree-badge-t { fill: #fff; font-size: 10px; font-weight: 800; font-family: Inter, sans-serif; pointer-events: none; }
.tree-count { fill: var(--ink-soft); font-size: 10.5px; font-weight: 700; font-family: Inter, sans-serif; pointer-events: none; }
.tree-tog-c { fill: var(--card); stroke: var(--accent); stroke-width: 1.4; }
.tree-toggle:hover .tree-tog-c { fill: var(--accent); }
.tree-tog-s { fill: var(--accent); font-size: 13px; font-weight: 800; font-family: monospace; pointer-events: none; }
.tree-toggle:hover .tree-tog-s { fill: #fff; }
.tree-toggle { cursor: pointer; }
.tree-node:hover .tree-rect { stroke-width: 2; }

/* ---------- Severity-evaluation (plant / ship-to / end-user) ---------- */
.fe-cell { position: relative; }
.sev-eval-btn { position: absolute; top: 2px; right: 2px; border: 0; background: transparent;
  color: var(--ink-soft); opacity: .35; cursor: pointer; font-size: .78rem; line-height: 1; padding: 2px;
  transition: opacity .12s ease, color .12s ease; }
.fe-cell:hover .sev-eval-btn { opacity: .8; }
.sev-eval-btn:hover { color: var(--accent); opacity: 1; }
.sev-eval-btn.on { opacity: .95; color: var(--accent); }
.sev-area { border: 1px solid var(--line); border-radius: 11px; padding: 10px 12px; margin-bottom: 10px; background: var(--card); }
.sev-area-head { font-size: .9rem; margin-bottom: 6px; display: flex; align-items: center; gap: 6px; }
.sev-area-head .text-muted-2 { font-weight: 400; }
.sev-result { border: 1px dashed color-mix(in srgb, var(--danger) 45%, var(--line)); border-radius: 10px;
  background: color-mix(in srgb, var(--danger) 6%, transparent); font-size: .9rem; }
.sev-ref-table th { position: sticky; top: 0; background: var(--card-raised); font-size: .68rem; }
.sev-ref-table td { border-color: var(--line); }

/* ---------- FMEA worksheet focus/filter + bulk bar ---------- */
.fmea-focus { display: flex; align-items: center; flex-wrap: wrap; gap: 12px;
  padding: 8px 12px; border-top: 1px solid var(--line); background: var(--bg); }
.fmea-focus .ff-seg { display: flex; align-items: center; gap: 8px; }
.ff-chip { border: 1px solid var(--line); background: var(--card); color: var(--ink-soft);
  border-radius: 999px; padding: 3px 11px; font-size: .76rem; font-weight: 600; cursor: pointer;
  transition: all .12s ease; }
.ff-chip:hover { border-color: var(--accent); color: var(--accent); }
.ff-chip.on { background: var(--accent); border-color: var(--accent); color: #fff; box-shadow: var(--shadow-xs); }
.ff-count { font-weight: 700; }
.ff-bulk { padding-left: 12px; border-left: 1px solid var(--line); }
.fmea-row.row-dim { opacity: .32; transition: opacity .15s ease; }
.fmea-row.row-dim:hover { opacity: 1; }
.fmea-toast { position: fixed; bottom: 22px; left: 50%; transform: translateX(-50%) translateY(12px);
  background: var(--ink); color: var(--bg); padding: 9px 16px; border-radius: 10px; font-size: .82rem;
  font-weight: 600; box-shadow: var(--shadow-lg); opacity: 0; transition: all .28s ease; z-index: 1080; pointer-events: none; }
.fmea-toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* ---------- FMEA scoring reference legend ---------- */
.scoring-legend td { padding: 3px 6px; vertical-align: top; border-color: var(--line); }
.scoring-legend tr:hover { background: var(--surface-2, rgba(37,99,235,.04)); }
.ap-matrix th, .ap-matrix td { padding: 4px 8px; border-color: var(--line); }
.ap-matrix th { font-size: .68rem; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-soft); font-weight: 700; }

/* ---------- PFMEA knowledge base (auto-learning) ---------- */
.kb-table thead th { text-transform: uppercase; letter-spacing: .04em; font-size: .6rem; font-weight: 700;
  color: var(--ink-soft); background: #fbfcfe; padding: 8px 11px; border-bottom: 1px solid var(--line); white-space: nowrap; }
.kb-table tbody td { padding: 7px 11px; border-bottom: 1px solid var(--line); font-size: .78rem; vertical-align: middle; }
.kb-table tbody tr:hover td { background: #f7f9fd; }
.kb-table tbody tr:last-child td { border-bottom: 0; }
.kb-learned > td:first-child { box-shadow: inset 3px 0 0 var(--ok); }
.kb-learned > td { background: rgba(16,185,129,.035); }
.kb-learned:hover > td { background: rgba(16,185,129,.07); }
[data-theme="midnight"] .kb-table thead th { background: var(--card-raised); }
[data-theme="midnight"] .kb-table tbody tr:hover td { background: #1e2941; }
[data-theme="midnight"] .kb-learned > td { background: rgba(52,211,153,.06); }

/* ---------- Process Flow: graphical flowchart ---------- */
.pf-operation { --pf-c:#2563eb; } .pf-transport { --pf-c:#0d9488; }
.pf-inspection { --pf-c:#d97706; } .pf-storage { --pf-c:#7c3aed; } .pf-delay { --pf-c:#64748b; }
.pf-legend { display:flex; flex-wrap:wrap; gap:8px 16px; }
.pf-legend .lg { display:inline-flex; align-items:center; gap:7px; font-size:.78rem; color:var(--ink-soft); }
.pf-legend .lg .pf-mini { position:relative; width:18px; height:18px; }
.pf-flow { display:flex; flex-direction:column; align-items:center; }
.pf-node { display:flex; align-items:stretch; gap:14px; width:100%; max-width:640px; }
.pf-sym, .pf-mini { flex:none; display:grid; place-items:center; }
.pf-sym { position:relative; width:52px; height:52px; color:#fff; font-weight:800; font-size:.9rem; }
.pf-sym > span { position:relative; z-index:1; }
.pf-sym::before, .pf-mini::before { content:""; position:absolute; inset:0; background:var(--pf-c);
  box-shadow:0 4px 12px rgba(16,24,40,.16), inset 0 1px 0 rgba(255,255,255,.3); }
.pf-operation.pf-sym::before, .pf-operation.pf-mini::before { border-radius:50%; }
.pf-inspection.pf-sym::before, .pf-inspection.pf-mini::before { border-radius:10px; }
.pf-storage.pf-sym::before, .pf-storage.pf-mini::before { clip-path:polygon(50% 100%, 0 6%, 100% 6%); }
.pf-transport.pf-sym::before, .pf-transport.pf-mini::before { clip-path:polygon(0 30%, 58% 30%, 58% 10%, 100% 50%, 58% 90%, 58% 70%, 0 70%); }
.pf-delay.pf-sym::before, .pf-delay.pf-mini::before { clip-path:polygon(25% 0, 75% 0, 100% 50%, 75% 100%, 25% 100%, 0 50%); }
.pf-card { flex:1 1 auto; min-width:0; background:var(--card); border:1px solid var(--line);
  border-left:3px solid var(--pf-c); border-radius:12px; box-shadow:var(--shadow-xs); padding:11px 14px; }
.pf-card-top { display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.pf-name { font-weight:700; font-size:.95rem; }
.pf-tag { font-size:.6rem; font-weight:800; letter-spacing:.05em; text-transform:uppercase;
  padding:2px 7px; border-radius:6px; background:color-mix(in srgb, var(--pf-c) 14%, transparent); color:var(--pf-c); }
.pf-chars { display:flex; flex-wrap:wrap; gap:4px 12px; margin-top:6px; }
.pf-chars > span { font-size:.75rem; color:var(--ink-soft); }
.pf-chars .bi { color:var(--pf-c); margin-right:2px; }
.pf-arrow { color:var(--line); font-size:1.1rem; line-height:1; margin:2px 0; }
.pf-arrow .bi { color:#c7cede; }

/* Branched process flow — parallel component streams that converge into common ops */
.pf-comp-chip { display:inline-flex; align-items:center; gap:6px; padding:4px 10px; border-radius:99px;
  border:1px solid var(--line); background:var(--card); font-size:.8rem; font-weight:600; box-shadow:var(--shadow-xs); }
.pf-comp-dot { width:11px; height:11px; border-radius:3px; background:var(--pf-c); flex:none; }
.pf-comp-n { font-size:.62rem; font-weight:800; background:var(--pf-c); color:#fff; border-radius:99px; padding:0 6px; }

.pf-branch { display:flex; flex-direction:column; align-items:center; }
/* lanes stay on ONE row (scroll for many components) so "parallel then converge" always holds */
.pf-lanes { display:flex; gap:18px; align-items:stretch; justify-content:center;
  flex-wrap:nowrap; overflow-x:auto; width:100%; padding-bottom:2px; }
.pf-lane { flex:0 1 320px; max-width:360px; min-width:230px; display:flex; flex-direction:column; align-items:stretch;
  border:1px solid var(--line); border-top:3px solid var(--pf-lane); border-radius:14px;
  padding:10px 12px 12px; background:var(--card); box-shadow:var(--shadow-xs); }
.pf-lane-head { display:flex; align-items:center; gap:7px; font-weight:800; font-size:.78rem;
  color:var(--pf-lane); text-transform:uppercase; letter-spacing:.04em; margin-bottom:10px; }
.pf-lane-dot { width:11px; height:11px; border-radius:3px; background:var(--pf-lane); flex:none; }
.pf-lane-pn { margin-left:auto; font-size:.64rem; font-weight:600; color:var(--ink-soft); text-transform:none; letter-spacing:0; }
.pf-lane .pf-node { width:100%; }
/* a colored connector rail fills the shorter lanes down to the funnel (the stream "waits" for the merge) */
.pf-lane-tail { align-self:center; width:3px; flex:1 0 18px; border-radius:2px; background:var(--pf-lane); opacity:.45; margin-top:6px; }
/* down-arrows sit under the node symbol column (52px), not floating at centre */
.pf-lane .pf-arrow { align-self:flex-start; width:52px; text-align:center; }

/* convergence: a colour funnel that collects every stream into the centre */
.pf-funnel { width:min(94%, 760px); height:38px; margin-top:2px;
  clip-path: polygon(0 0, 100% 0, 62% 100%, 38% 100%); }
.pf-merge-label { margin-top:8px; font-size:.72rem; font-weight:700; color:var(--ink-soft);
  background:var(--card); border:1px solid var(--line); border-radius:99px; padding:3px 14px; }
.pf-arrow-lg { font-size:1.5rem; margin:4px 0; }

.pf-common { display:flex; flex-direction:column; align-items:center; width:100%; margin-top:2px; }
.pf-common .pf-node { max-width:560px; }
.pf-common-head { font-size:.66rem; font-weight:800; letter-spacing:.06em; text-transform:uppercase;
  color:var(--ink-soft); margin-bottom:10px; }

/* ---------- Budget: unplanned cost row ---------- */
.cost-unplanned { box-shadow: inset 3px 0 0 var(--warn, #d97706); }
.cost-unplanned td:first-child { position: relative; }

/* ---------- Misc ---------- */
.page-title { font-weight: 800; font-size: 1.35rem; }
.text-muted-2 { color: var(--ink-soft); }
.hover-raise { transition: box-shadow .12s ease, transform .12s ease; }
.hover-raise:hover { box-shadow: var(--shadow); transform: translateY(-1px); }
.empty-state { text-align: center; padding: 48px 20px; color: var(--ink-soft); }
.empty-state i { font-size: 2.4rem; color: #b9c3d4; }
.chart-box { position: relative; height: 260px; }
.list-group-item { border-color: var(--line); }
.card-eyebrow { font-size:.7rem; text-transform:uppercase; letter-spacing:1px; color:var(--ink-soft); font-weight:700; }

/* ============================================================
   Live / dynamic motion — tasteful micro-animations
   ============================================================ */
@keyframes floaty { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-3px); } }
@keyframes glowpulse {
  0%,100% { box-shadow: 0 6px 16px rgba(16,24,40,.16), inset 0 1px 0 rgba(255,255,255,.3); }
  50% { box-shadow: 0 8px 26px rgba(37,99,235,.45), inset 0 1px 0 rgba(255,255,255,.4); }
}
@keyframes livepulse {
  0% { box-shadow: 0 0 0 0 rgba(16,185,129,.55); }
  70% { box-shadow: 0 0 0 8px rgba(16,185,129,0); }
  100% { box-shadow: 0 0 0 0 rgba(16,185,129,0); }
}
@keyframes alertpulse {
  0%,100% { transform: scale(1); opacity: 1; }
  50% { transform: scale(1.18); opacity: .75; }
}
@keyframes shimmer { 0% { background-position: -400px 0; } 100% { background-position: 400px 0; } }
@keyframes fadeup { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@keyframes spin360 { to { transform: rotate(360deg); } }
@keyframes ringdash { to { stroke-dashoffset: 0; } }

/* Late-project alert — blinking "Late" badge + row highlight on the projects list */
@keyframes latepulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(220,38,38,.55); opacity: 1; }
  70%      { box-shadow: 0 0 0 7px rgba(220,38,38,0);   opacity: .55; }
}
.badge-blink { animation: latepulse 1.15s ease-out infinite; will-change: box-shadow, opacity; }
tr.row-late > td { background-color: rgba(220,38,38,.05); }
tr.row-late > td:first-child { box-shadow: inset 3px 0 0 var(--danger, #dc2626); }
tr.row-late:hover > td { background-color: rgba(220,38,38,.09); }

@media (prefers-reduced-motion: reduce) { * { animation: none !important; } }

/* Entrance: cards & tiles rise in, gently staggered */
.kpi-tile, .card { animation: fadeup .5s cubic-bezier(.22,.61,.36,1) both; }
.kpi-tile:nth-child(1) { animation-delay: .02s; }
.kpi-tile:nth-child(2) { animation-delay: .08s; }
.kpi-tile:nth-child(3) { animation-delay: .14s; }
.kpi-tile:nth-child(4) { animation-delay: .20s; }

/* Living gradient icon tiles — float + glow on hover, active quick-icon breathes */
.kpi-ic { transition: transform .25s cubic-bezier(.34,1.56,.64,1); }
.kpi-tile:hover .kpi-ic { animation: floaty 1.6s ease-in-out infinite; }
.nav-quick-icon.active { animation: glowpulse 2.8s ease-in-out infinite; }

/* Live status dots */
.live-dot {
  width: 8px; height: 8px; border-radius: 50%; display: inline-block;
  background: #10b981; animation: livepulse 1.8s infinite;
}
.live-badge {
  display: inline-flex; align-items: center; gap: 6px; font-size: .64rem;
  font-weight: 800; letter-spacing: .14em; text-transform: uppercase;
  color: #6ee7b7; padding: 3px 10px; border-radius: 999px;
  background: rgba(16,185,129,.14); border: 1px solid rgba(16,185,129,.3);
}

/* Alert / attention icons pulse to draw the eye */
.attn-danger i { animation: alertpulse 1.4s ease-in-out infinite; color: var(--danger); }
.attn-warn i { animation: alertpulse 2s ease-in-out infinite; color: var(--warn); }

/* Notification bell wiggles when there are unread items */
@keyframes bell { 0%,50%,100% { transform: rotate(0); } 10%,30% { transform: rotate(12deg); } 20%,40% { transform: rotate(-12deg); } }
.notif-bell.has-unread i { animation: bell 2.4s ease-in-out infinite; transform-origin: top center; }
.notif-badge { animation: alertpulse 1.6s ease-in-out infinite; }

/* Count-up numbers hold layout while animating */
.kpi-value[data-count], .hs-val[data-count] { font-variant-numeric: tabular-nums; }

/* Progress bars fill in on load */
.progress-bar { transition: width 1s cubic-bezier(.22,.61,.36,1); }

/* Shimmer skeleton (for any live-loading region) */
.shimmer {
  background: linear-gradient(90deg, #eef1f6 25%, #f7f9fc 37%, #eef1f6 63%);
  background-size: 800px 100%; animation: shimmer 1.4s infinite linear;
}

/* Button ripple-ish press + spring hover on primary actions */
.btn-primary, .btn-hero { transition: transform .14s cubic-bezier(.34,1.56,.64,1), box-shadow .18s ease, background .18s ease; }
.btn-primary:active, .btn-hero:active { transform: translateY(1px) scale(.98); }

/* Row hover lift on clickable table rows */
.table-hover tbody tr { transition: transform .12s ease, box-shadow .12s ease; }

/* Animated SVG capability ring */
.ring-track { stroke: #eef1f6; }
.ring-value { stroke-linecap: round; transition: stroke-dashoffset 1.1s cubic-bezier(.22,.61,.36,1); }

/* ============================================================
   Gantt (phase timeline) — frozen label column + scrolling track
   ============================================================ */
.gantt-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.gantt-inner { min-width: var(--track-min, 900px); }
.gantt-head, .gantt-row { display: flex; align-items: stretch; }
.gantt-label-col {
  flex: 0 0 200px; width: 200px; border-right: 2px solid var(--line);
  background: #fff; position: sticky; left: 0; z-index: 3;
  padding: 8px 12px; display: flex; align-items: stretch;
  /* column, so a lane can carry the project link and a "dates not agreed"
     prompt underneath it without the two fighting for the same line */
  flex-direction: column; justify-content: center;
}
.gantt-head .gantt-label-col { background: #fafbff; z-index: 4;
  align-items: stretch; justify-content: flex-end; padding-bottom: 4px; }
.gantt-track-col { flex: 1 1 auto; position: relative; min-width: 700px; }
.gantt-head-track { border-bottom: 1px solid var(--line); }
.gantt-months-row { display: flex; }
.gantt-month-cell {
  font-size: .68rem; font-weight: 700; color: var(--ink-soft);
  text-align: center; border-left: 1px solid var(--line);
  padding: 5px 0; white-space: nowrap; overflow: hidden;
}
.gantt-row { border-bottom: 1px solid var(--line); min-height: 50px; }
.gantt-row:hover { background: #f6f9ff; }
.gantt-row:hover .gantt-label-col { background: #f6f9ff; }
.gantt-track-col.gantt-body { padding: 7px 0; }
.gantt-bar {
  position: absolute; height: 22px; border-radius: 6px; top: 50%;
  transform: translateY(-50%); color: #fff; font-size: .68rem; font-weight: 600;
  display: flex; align-items: center; padding: 0 7px; overflow: hidden;
  white-space: nowrap; box-shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 3px rgba(16,24,40,.18);
  transition: filter .15s ease, transform .15s ease;
}
.gantt-bar:hover { filter: brightness(1.06); transform: translateY(-50%) scale(1.015); z-index: 2; }
.gantt-bar-current { outline: 2px solid rgba(37,99,235,.55); outline-offset: 1px; }
.gantt-bar-fill { position:absolute; left:0; top:0; bottom:0; background: rgba(255,255,255,.22); border-radius: 6px 0 0 6px; }
.gantt-today {
  position: absolute; top: 0; bottom: 0; width: 2px;
  background: linear-gradient(180deg, #e11d48, rgba(225,29,72,.35)); z-index: 1;
}
.gantt-today::before {
  content: "Today"; position: absolute; top: -1px; left: 3px; font-size: .58rem;
  font-weight: 800; color: #e11d48; background: #fff; padding: 0 3px; border-radius: 3px;
}
/* The line is drawn per row so it can sit under the bars; the caption only
   needs saying once, at the top, or an eight-row chart repeats it eight times. */
.gantt-row ~ .gantt-row .gantt-today::before { display: none; }
.gantt-actual { position: absolute; top: 50%; transform: translate(-50%,-50%); color: #7c3aed; font-size: .7rem; z-index: 2; }
.gantt-legend-box { display:inline-block; width:12px; height:12px; border-radius:3px; margin-right:4px; vertical-align:-1px; }
.gantt-empty { padding: 40px; text-align: center; color: var(--ink-soft); }

/* ============================================================
   The shell: navigation down the left, not across the top

   A top bar runs out of width as modules are added — twenty of them ended up
   behind three dropdowns, so you had to know which menu a tool was in before
   you could reach it. Standing the bar on its end shows every module at once,
   keeps the one you are on visibly marked, and leaves room for the second line
   that says what each tool is for.

   The DOM is the navbar's, unchanged: the command palette harvests from
   `.proq-nav`, and a test reads base.html to prove every module has a link
   there. Only the layout moved.

   Below `lg` this all switches off and the bar goes back across the top — a
   264px column on a 375px phone is not a sidebar, it is the whole screen.
   ============================================================ */
@media (min-width: 992px) {
  :root { --pqs-w: 268px; }
  body.pqs-rail { --pqs-w: 76px; }

  .pq-side.proq-nav {
    position: fixed; left: 0; top: 0; bottom: 0; width: var(--pqs-w);
    z-index: 1035; padding: 0; display: block;
    border-radius: 0; border: 0;
    background: linear-gradient(178deg, #12336e 0%, #0f2a5c 42%, #0c2148 100%);
    box-shadow: 1px 0 0 rgba(255, 255, 255, .07), 6px 0 26px -16px rgba(8, 20, 45, .55);
    transition: width .16s ease;
  }
  /* In the top bar the beam sweeps across a 60px strip, driven by a
     translateX of the whole window width. Stood on its end here it becomes a
     2px line the full height of the screen — and it kept the sweep, so every
     ten seconds a blue line crossed the entire page, through the content, a
     long way outside the column it belongs to. Measured mid-sweep at x=650
     with the column ending at 268. In the side layout it is the lit edge it
     was drawn as, and it stays there. */
  .pq-side .proq-nav-beam { inset: 0 auto 0 0; width: 2px; height: auto;
    background: linear-gradient(180deg, #38bdf8, #2563eb 46%, transparent);
    animation: none; transform: none; opacity: 1; filter: none; }
  /* The beam does not move in the side column, so the top bar's clip has no
     work here, and the column's rail toggle sits across its edge. */
  .proq-nav.pq-side { overflow-x: visible; }
  .pq-side .container-fluid {
    height: 100%; display: flex; flex-direction: column; align-items: stretch;
    flex-wrap: nowrap; padding: 0;
  }

  /* brand ------------------------------------------------------------- */
  .pq-side .navbar-brand { flex: 0 0 auto; padding: 15px 16px 12px; margin: 0; }
  .pq-side .brand-word { font-size: 1.02rem; }
  .pq-side .co-brand { flex: 0 0 auto; padding: 0 16px 8px; }
  .pq-side .co-brand-divider { display: none; }
  .pq-side .nav-quick { display: none; }        /* labelled links replace it */
  .pq-side .navbar-toggler { display: none; }

  .pq-side .nav-search-slot { flex: 0 0 auto; padding: 0 12px 10px; }
  .pq-side .cmdk-hint {
    display: flex !important; width: 100%; justify-content: flex-start;
    gap: 8px; padding: 7px 10px; border-radius: 9px;
    background: rgba(255, 255, 255, .09); border: 1px solid rgba(255, 255, 255, .13);
    color: #b9cdec; font-size: .8rem;
  }
  .pq-side .cmdk-hint kbd { margin-left: auto; }

  /* the scrolling body of the column ----------------------------------- */
  .pq-side #navMain {
    display: flex !important; flex-direction: column; flex: 1 1 auto;
    min-height: 0; height: auto; overflow: visible;
  }
  .pq-side #navMain > .navbar-nav:first-child {
    flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden;
    margin: 0; padding-bottom: 6px; scrollbar-width: thin;
  }
  .pq-side #navMain > .navbar-nav:first-child::-webkit-scrollbar { width: 6px; }
  .pq-side #navMain > .navbar-nav:first-child::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, .16); border-radius: 3px; }
  .pq-side .navbar-nav { flex-direction: column; align-items: stretch; }

  /* a section heading, and the mega-menu toggle demoted into one -------- */
  .pq-side .qt-sec, .pq-side .qt-sec-head {
    padding: 13px 16px 5px; font-size: .58rem; font-weight: 800;
    letter-spacing: 1.7px; text-transform: uppercase; color: #7e9dcc;
    background: none; border: 0; cursor: default; pointer-events: none;
  }
  .pq-side .qt-sec-head::after { display: none; }        /* the caret */
  /* `.proq-nav .navbar-nav > .nav-item > .nav-link` is four classes deep and
     paints the active state; a demoted heading must out-specify it or the
     section title gets highlighted as if it were the page you are on. */
  .pq-side .navbar-nav > .nav-item > .nav-link.qt-sec-head,
  .pq-side .navbar-nav > .nav-item > .nav-link.qt-sec-head.active {
    background: none; box-shadow: none; }
  .pq-side .navbar-nav > .nav-item > .nav-link.qt-sec-head.active::before { display: none; }
  .pq-side .qt-sec-head.active { color: #9fc2f2; }
  .pq-side .qt-sec-head i { display: none; }

  /* every mega-menu is simply open ------------------------------------- */
  .pq-side .dropdown-menu.qt-menu {
    position: static !important; display: block; float: none; inset: auto !important;
    transform: none !important; width: auto; min-width: 0; max-height: none;
    margin: 0; padding: 0; border: 0; border-radius: 0; box-shadow: none;
    background: none; backdrop-filter: none;
  }
  .pq-side .qt-menu .qt-head { display: none; }          /* the section says it */
  .pq-side .qt-item {
    display: flex; align-items: center; gap: 11px; padding: 7px 16px;
    color: #d3e2f7; border-radius: 0; background: none; position: relative;
  }
  .pq-side .qt-item:hover, .pq-side .qt-item:focus {
    background: rgba(255, 255, 255, .08); color: #fff; }
  .pq-side .qt-item.is-active { background: rgba(56, 189, 248, .16); color: #fff; }
  .pq-side .qt-item.is-active::before {
    content: ""; position: absolute; left: 0; top: 5px; bottom: 5px; width: 3px;
    border-radius: 0 3px 3px 0; background: #38bdf8; }
  .pq-side .qt-tile { width: 26px; height: 26px; border-radius: 7px; font-size: .8rem; flex: 0 0 auto; }
  .pq-side .qt-body { min-width: 0; }
  /* The mega-menu was written for a light popover: `.qt-title` sets its own
     #0f172a, which measured 1.28:1 against the navy column — the words were
     there and unreadable. Both lines are restated for a dark ground. */
  .pq-side .qt-title { font-size: .82rem; color: #e6eefc;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .pq-side .qt-item:hover .qt-title,
  .pq-side .qt-item.is-active .qt-title { color: #fff; }
  .pq-side .qt-sub { font-size: .63rem; color: #93b0d8; white-space: nowrap;
    overflow: hidden; text-overflow: ellipsis; }
  .pq-side .qt-go, .pq-side .qt-pill { display: none; }

  /* the plain links in the top section --------------------------------- */
  .pq-side #navMain > .navbar-nav:first-child > .nav-item > .nav-link {
    display: flex; align-items: center; gap: 11px; padding: 8px 16px;
    border-radius: 0; font-size: .84rem; color: #d3e2f7; position: relative;
  }
  .pq-side #navMain > .navbar-nav:first-child > .nav-item > .nav-link i { font-size: .95rem; width: 26px; text-align: center; }
  .pq-side #navMain > .navbar-nav:first-child > .nav-item > .nav-link:hover { background: rgba(255,255,255,.08); color: #fff; }
  .pq-side #navMain > .navbar-nav:first-child > .nav-item > .nav-link.active { background: rgba(56,189,248,.16); color: #fff; }
  .pq-side #navMain > .navbar-nav:first-child > .nav-item > .nav-link.active::before {
    content: ""; position: absolute; left: 0; top: 5px; bottom: 5px; width: 3px;
    border-radius: 0 3px 3px 0; background: #38bdf8; }

  /* the foot: alerts, approvals, the person ---------------------------- */
  .pq-side .nav-foot {
    flex: 0 0 auto; margin-top: auto; flex-direction: row; flex-wrap: wrap;
    align-items: center; gap: 2px; padding: 8px 10px 10px;
    border-top: 1px solid rgba(255, 255, 255, .11);
  }
  .pq-side .nav-foot > .nav-item { flex: 0 0 auto; }
  .pq-side .nav-foot > .nav-item:first-child { flex: 1 1 100%; }   /* Team keeps its row */
  .pq-side .nav-foot .nav-link { padding: 6px 8px; font-size: .8rem; }
  /* the sidebar foot has room for words: un-hide the drawer labels and keep
     each count pinned to its own link instead of its neighbour */
  .pq-side .nav-foot .nav-foot-label { display: inline !important; }
  .pq-side .nav-foot { gap: 4px 10px; }
  .pq-side .nav-foot .notif-badge { position: static; margin-left: .35rem; }
  .pq-side .user-chip { width: 100%; padding: 7px 8px !important; }
  .pq-side .user-chip-name { font-size: .8rem; }
  .pq-side .nav-foot .dropdown-menu { max-height: 70vh; overflow-y: auto; }

  /* the rail ----------------------------------------------------------- */
  /* The base rules above are anchored on #navMain, so an id outranks anything
     written with classes alone: the first attempt collapsed the plain <li>
     headings and left every .nav-link heading standing, half in and half out of
     a 76px rail. These mirror the same depth rather than reaching for
     !important. */
  body.pqs-rail .pq-side .qt-body,
  body.pqs-rail .pq-side .qt-sec,
  body.pqs-rail .pq-side .brand-word,
  body.pqs-rail .pq-side .user-chip-name,
  body.pqs-rail .pq-side .nav-label,
  body.pqs-rail .pq-side .cmdk-hint span,
  body.pqs-rail .pq-side .cmdk-hint kbd,
  body.pqs-rail .pq-side .co-brand,
  body.pqs-rail .pq-side #navMain > .navbar-nav > .nav-item > .nav-link.qt-sec-head,
  body.pqs-rail .pq-side #navMain > .navbar-nav > .nav-item > .nav-link .nav-label { display: none; }
  body.pqs-rail .pq-side .qt-item,
  body.pqs-rail .pq-side .nav-foot .nav-link,
  body.pqs-rail .pq-side .user-chip,
  body.pqs-rail .pq-side .navbar-brand,
  body.pqs-rail .pq-side .cmdk-hint,
  body.pqs-rail .pq-side #navMain > .navbar-nav:first-child > .nav-item > .nav-link { justify-content: center; padding-left: 0; padding-right: 0; }
  body.pqs-rail .pq-side .nav-foot { flex-direction: column; }
  body.pqs-rail .pq-side .nav-foot > .nav-item:first-child { flex: 0 0 auto; }

  /* the collapse control ------------------------------------------------ */
  .pqs-toggle {
    position: fixed; left: calc(var(--pqs-w) - 13px); top: 22px; z-index: 1036;
    width: 26px; height: 26px; border-radius: 50%; border: 1px solid var(--line);
    background: var(--card); color: var(--ink-soft); display: flex;
    align-items: center; justify-content: center; font-size: .7rem; padding: 0;
    box-shadow: 0 2px 8px rgba(15, 28, 51, .18); transition: left .16s ease;
  }
  .pqs-toggle:hover { color: var(--accent); border-color: var(--accent); }

  /* the page moves over — only for whoever chose the sidebar -------------- */
  :root[data-nav="side"] .subbar,
  :root[data-nav="side"] main.content {
    margin-left: var(--pqs-w);
    width: calc(100% - var(--pqs-w));   /* .content is width:100%; a margin alone
                                           would push it past the right edge */
    transition: margin-left .16s ease, width .16s ease;
  }

  /* what the two shells hide from each other ----------------------------- */
  .pq-side .nav-item.d-lg-none { display: block !important; }
  /* The span carries d-none/d-xl-inline for the top bar, so un-hiding it needs
     !important — which would then beat the rail's hide. Scoped, so it does not. */
  body:not(.pqs-rail) .pq-side .user-chip-name { display: inline !important; }
  .proq-nav:not(.pq-side) .qt-sec,
  .proq-nav:not(.pq-side) .nav-search-slot { display: none; }
}
@media (max-width: 991.98px) {
  .pqs-toggle { display: none; }
  /* In the drawer every nav row is full width, so an absolutely-anchored count
     flies to the far edge, detached from the icon it belongs to. Inline, it
     reads as what it is: a count after its label. */
  .navbar-collapse .notif-badge { position: static; margin-left: .4rem; }
}

/* The section heading is markup both shells carry, so it needs a look wherever
   it shows — the top bar hides it, the mobile drawer does not. */
.qt-sec {
  list-style: none; padding: 12px 16px 5px; font-size: .58rem; font-weight: 800;
  letter-spacing: 1.7px; text-transform: uppercase; color: #7e9dcc;
}


/* --- Customer milestones on the phase Gantt -------------------------------
   The committed date is a filled diamond, the forecast a hollow one joined to
   it by a dashed run, so a slip reads as a distance rather than as a number
   somebody has to convert. `--msc` is resolved here from the two colours the
   builder emits: setting it inline instead would beat every theme rule and
   leave Midnight with swatches chosen for a white card. */
.gantt-ms, .gantt-ms-line, .gantt-ms-fc,
.gantt-ms-slip, .gantt-ms-edge { --msc: var(--ms-light); }
:root[data-theme="midnight"] .gantt-ms,
:root[data-theme="midnight"] .gantt-ms-line,
:root[data-theme="midnight"] .gantt-ms-fc,
:root[data-theme="midnight"] .gantt-ms-slip,
:root[data-theme="midnight"] .gantt-ms-edge { --msc: var(--ms-dark); }

.gantt-ms-rail { min-height: 40px; background: var(--bg); }
.gantt-ms-rail .gantt-label-col { background: var(--bg); }
.gantt-ms-rail:hover, .gantt-ms-rail:hover .gantt-label-col { background: var(--bg); }

/* The diamond sits ON the bar line — a committed date is a wall the bar has to
   finish behind, and drawing it beside the bar loses that. Its label drops to
   the foot of the row instead, because stacked under the diamond it landed on
   top of whichever phase bar the date falls in. */
.gantt-ms {
  position: absolute; top: 0; bottom: 0; width: 0;
  transform: translateX(-50%); z-index: 4; line-height: 1;
}
.gantt-ms .dia {
  position: absolute; top: 50%; left: 50%; width: 10px; height: 10px;
  transform: translate(-50%, -50%) rotate(45deg);
  background: var(--msc); border-radius: 2px; box-shadow: 0 0 0 2px var(--card);
}
.gantt-ms .code {
  position: absolute; bottom: 1px; left: 50%; transform: translateX(-50%);
  font-size: .55rem; font-weight: 800; letter-spacing: .3px; color: var(--msc);
  background: var(--card); padding: 0 3px; border-radius: 3px;
  box-shadow: 0 0 0 1px var(--line); white-space: nowrap;
}
/* On a phase row the diamond sits on the bar itself, so it carries no label. */
.gantt-ms--bare .dia { width: 9px; height: 9px; }

.gantt-ms-line {
  position: absolute; top: 0; bottom: 0; width: 0; z-index: 0;
  border-left: 2px dashed var(--msc); opacity: .40;
}
.gantt-ms-fc {
  position: absolute; top: 50%; z-index: 4; width: 9px; height: 9px;
  transform: translate(-50%, -50%) rotate(45deg);
  border: 2px solid var(--msc); border-radius: 2px; background: var(--card);
}
.gantt-ms-slip {
  position: absolute; top: 50%; height: 2px; transform: translateY(-50%); z-index: 3;
  background: repeating-linear-gradient(90deg, var(--msc) 0 4px, transparent 4px 8px);
  opacity: .8;
}
.gantt-ms-edge {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 4;
  font-size: .55rem; font-weight: 800; letter-spacing: .3px; color: var(--msc);
  background: var(--card); border: 1px solid var(--msc); border-radius: 4px;
  padding: 1px 4px; white-space: nowrap; display: inline-flex; align-items: center; gap: 2px;
}
.gantt-ms-edge--before { left: 3px; }
.gantt-ms-edge--after { right: 3px; }

/* A date nobody has agreed is named rather than left out: an absent diamond
   looks exactly like an absent feature, and this one is a link to fixing it. */
.gantt-ms-todo {
  display: inline-block; margin-top: 3px; font-size: .66rem; font-weight: 700;
  color: #b45309; text-decoration: none; line-height: 1.25;
}
.gantt-ms-todo:hover { text-decoration: underline; }
:root[data-theme="midnight"] .gantt-ms-todo { color: #fbbf24; }

.gantt-legend-sep {
  width: 1px; height: 14px; background: var(--line); display: inline-block;
}
.gantt-legend-dia {
  display: inline-block; width: 10px; height: 10px; margin-right: 5px;
  background: #4338ca; border-radius: 2px; transform: rotate(45deg);
  vertical-align: -1px;
}
.gantt-legend-dia--fc { background: var(--card); border: 2px solid #4338ca; }
:root[data-theme="midnight"] .gantt-legend-dia { background: #a5b4fc; }
:root[data-theme="midnight"] .gantt-legend-dia--fc { background: var(--card); border-color: #a5b4fc; }

/* ============================================================
   Smart dashboard — insights strip, radial gauges, premium charts
   ============================================================ */
.insight-strip { display: flex; gap: 12px; overflow-x: auto; padding-bottom: 4px; }
.insight-chip {
  flex: 0 0 auto; display: flex; align-items: center; gap: 10px;
  padding: 12px 16px; border-radius: 14px; background: var(--card);
  border: 1px solid var(--line); box-shadow: var(--shadow-sm);
  min-width: 230px; position: relative; overflow: hidden;
  animation: fadeup .5s cubic-bezier(.22,.61,.36,1) both;
}
.insight-chip::before { content:""; position:absolute; left:0; top:0; bottom:0; width:4px; }
.insight-chip.tone-ok::before { background: linear-gradient(180deg,#34d399,#059669); }
.insight-chip.tone-warn::before { background: linear-gradient(180deg,#fbbf24,#d97706); }
.insight-chip.tone-danger::before { background: linear-gradient(180deg,#fb7185,#e11d48); }
.insight-chip .ic {
  width: 36px; height: 36px; border-radius: 10px; display: grid; place-items: center;
  color: #fff; font-size: 1.05rem; flex: 0 0 36px;
}
.insight-chip.tone-ok .ic { background: linear-gradient(135deg,#34d399,#059669); }
.insight-chip.tone-warn .ic { background: linear-gradient(135deg,#fbbf24,#d97706); }
.insight-chip.tone-danger .ic { background: linear-gradient(135deg,#fb7185,#e11d48); }
.insight-chip .txt { font-size: .82rem; font-weight: 600; line-height: 1.2; }
.insight-chip .delta { font-size: .72rem; font-weight: 800; }
.insight-chip .delta.up { color: var(--ok); }
.insight-chip .delta.down { color: var(--danger); }

/* Radial gauges */
.gauge-card {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 16px; box-shadow: var(--shadow-sm); height: 100%;
  display: flex; flex-direction: column; align-items: center;
  transition: box-shadow .18s ease, transform .18s ease;
  animation: fadeup .5s cubic-bezier(.22,.61,.36,1) both;
}
.gauge-card:hover { box-shadow: var(--shadow); transform: translateY(-2px); }
.gauge-wrap { position: relative; width: 132px; height: 132px; }
.gauge-wrap canvas { position: relative; z-index: 1; }
.gauge-center {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; pointer-events: none;
}
.gauge-center .g-val { font-size: 1.6rem; font-weight: 800; line-height: 1; font-variant-numeric: tabular-nums; }
.gauge-center .g-unit { font-size: .8rem; font-weight: 700; }
.gauge-label { margin-top: 8px; font-size: .74rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .05em; color: var(--ink-soft); text-align: center; }
.gauge-sub { font-size: .72rem; color: var(--ink-soft); }

/* Premium chart cards */
.chart-card { border-radius: var(--radius); overflow: hidden; }
.chart-card .card-header {
  background: linear-gradient(180deg, #fbfcff, #f4f7fd);
}
.chart-card .metric-big { font-size: 1.9rem; font-weight: 800; line-height: 1; }
.donut-center {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; pointer-events: none;
}
.donut-center .d-val { font-size: 1.7rem; font-weight: 800; line-height: 1; }
.donut-center .d-cap { font-size: .66rem; text-transform: uppercase; letter-spacing: .06em; color: var(--ink-soft); font-weight: 700; }

/* ============================================================
   ProQ Intelligence (AI copilot) + premium dashboard widgets
   ============================================================ */
.command-hero {
  position: relative; overflow: hidden; border-radius: 22px; color: #eef3ff; padding: 24px 26px;
  background:
    url("../img/hero-automotive.3133761112b9.svg") right -6px bottom -14px / auto 150% no-repeat,
    radial-gradient(120% 110% at 100% 0%, rgba(139,92,246,.26) 0%, transparent 52%),
    radial-gradient(110% 120% at 0% 100%, rgba(56,189,248,.22) 0%, transparent 55%),
    linear-gradient(120deg, #0a1020 0%, #122a52 46%, #1a3a78 76%, #24489e 100%);
  border: 1px solid rgba(139,92,246,.24);
  box-shadow: var(--shadow-lg), inset 0 1px 0 rgba(255,255,255,.08);
}
.ch-head { display:flex; align-items:flex-start; justify-content:space-between; gap:20px;
  flex-wrap:wrap; position:relative; z-index:1; }
.ch-divider { height:1px; margin:18px 0; position:relative; z-index:1;
  background: linear-gradient(90deg, rgba(255,255,255,0), rgba(255,255,255,.14) 30%, rgba(255,255,255,.14) 70%, rgba(255,255,255,0)); }

.ai-panel {
  position: relative; overflow: hidden; border-radius: 22px; color: #eef3ff; padding: 22px 24px;
  background:
    radial-gradient(130% 120% at 100% 0%, rgba(139,92,246,.32) 0%, transparent 55%),
    radial-gradient(120% 130% at 0% 100%, rgba(56,189,248,.26) 0%, transparent 55%),
    linear-gradient(125deg, #0b1130 0%, #14204d 48%, #1a2a63 100%);
  border: 1px solid rgba(139,92,246,.28);
  box-shadow: var(--shadow-lg), inset 0 1px 0 rgba(255,255,255,.08);
}
.ai-panel-glow { position:absolute; inset:-40% -10% auto auto; width:60%; height:180%;
  background: radial-gradient(closest-side, rgba(129,140,248,.35), transparent);
  filter: blur(30px); pointer-events:none; animation: aiglow 8s ease-in-out infinite; }
@keyframes aiglow { 0%,100%{opacity:.5; transform:translateX(0);} 50%{opacity:.9; transform:translateX(-8%);} }
.ai-head { display:flex; align-items:center; gap:12px; position:relative; z-index:1; margin-bottom:16px; }
.ai-orb { width:44px; height:44px; border-radius:14px; display:grid; place-items:center; font-size:1.3rem; color:#fff;
  background: linear-gradient(135deg,#8b5cf6,#6366f1 45%,#38bdf8);
  box-shadow: 0 8px 22px rgba(139,92,246,.55), inset 0 1px 0 rgba(255,255,255,.4); animation: aiorb 3.4s ease-in-out infinite; }
@keyframes aiorb { 0%,100%{box-shadow:0 8px 22px rgba(139,92,246,.55), inset 0 1px 0 rgba(255,255,255,.4);}
  50%{box-shadow:0 10px 30px rgba(56,189,248,.6), inset 0 1px 0 rgba(255,255,255,.5);} }
.ai-title { font-weight:800; font-size:1.05rem; letter-spacing:-.01em; display:flex; align-items:center; gap:8px; }
.ai-badge { font-size:.56rem; font-weight:800; letter-spacing:.14em; padding:2px 7px; border-radius:6px;
  background: linear-gradient(135deg,#8b5cf6,#38bdf8); color:#fff; }
.ai-caption { font-size:.72rem; color:#9fb0da; }
.ai-live { display:inline-flex; align-items:center; gap:6px; font-size:.62rem; font-weight:800; letter-spacing:.12em; text-transform:uppercase; color:#6ee7b7; }
.ai-grid { display:grid; grid-template-columns: 1fr 1.25fr; gap:18px; position:relative; z-index:1; }
@media (max-width: 991.98px){ .ai-grid{ grid-template-columns:1fr; } }
.ai-summary { border-left:3px solid; padding-left:14px; }
.ai-summary.tone-ok{ border-color:#34d399; } .ai-summary.tone-warn{ border-color:#fbbf24; }
.ai-summary.tone-danger{ border-color:#fb7185; } .ai-summary.tone-muted{ border-color:#64748b; }
.ai-summary-head { font-size:1.15rem; font-weight:800; line-height:1.25; margin-bottom:6px; }
.ai-summary-body { font-size:.9rem; color:#cdd8f2; margin:0; }
.ai-forecast { margin-top:16px; }
.ai-forecast-label, .ai-recs-label { font-size:.64rem; font-weight:800; letter-spacing:.1em; text-transform:uppercase; color:#9fb0da; margin-bottom:8px; }
.ai-forecast-chip { display:inline-flex; align-items:center; gap:7px; margin:0 6px 6px 0; padding:5px 10px; border-radius:10px;
  background: rgba(255,255,255,.06); border:1px solid rgba(255,255,255,.12); color:#eef3ff; text-decoration:none; font-size:.76rem; transition:.15s; }
.ai-forecast-chip:hover{ background:rgba(255,255,255,.12); color:#fff; transform:translateY(-1px); }
.ai-forecast-chip.crit{ border-color: rgba(251,113,133,.5); }
.ai-forecast-chip .fc-code{ font-weight:700; }
.ai-forecast-chip .fc-risk{ font-size:.6rem; font-weight:800; text-transform:uppercase; letter-spacing:.06em; color:#fda4af; }
.ai-forecast-chip .fc-days{ color:#9fb0da; }
.ai-rec { display:flex; align-items:center; gap:12px; padding:10px 12px; border-radius:13px; text-decoration:none; color:#eef3ff;
  background: rgba(255,255,255,.05); border:1px solid rgba(255,255,255,.09); margin-bottom:8px;
  transition: transform .16s cubic-bezier(.34,1.56,.64,1), background .16s ease, border-color .16s ease; animation: fadeup .5s both; }
.ai-rec:hover { background: rgba(255,255,255,.1); border-color: rgba(139,92,246,.4); transform: translateX(3px); color:#fff; }
.ai-rec-ic { width:36px; height:36px; flex:0 0 36px; border-radius:10px; display:grid; place-items:center; font-size:1.05rem; color:#fff;
  background: linear-gradient(135deg, rgba(139,92,246,.55), rgba(56,189,248,.5)); box-shadow: inset 0 1px 0 rgba(255,255,255,.25); }
.ai-rec.impact-high .ai-rec-ic { background: linear-gradient(135deg,#fb7185,#e11d48); }
.ai-rec.impact-medium .ai-rec-ic { background: linear-gradient(135deg,#fbbf24,#d97706); }
.ai-rec.impact-low .ai-rec-ic { background: linear-gradient(135deg,#34d399,#059669); }
.ai-rec-body { flex:1 1 auto; min-width:0; line-height:1.25; }
.ai-rec-title { display:block; font-weight:650; font-size:.86rem; }
.ai-rec-detail { display:block; font-size:.74rem; color:#a9b7dc; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.ai-rec-impact { flex:0 0 auto; font-size:.56rem; font-weight:800; text-transform:uppercase; letter-spacing:.06em; padding:2px 7px; border-radius:6px; }
.imp-high{ background:rgba(251,113,133,.2); color:#fda4af; } .imp-medium{ background:rgba(251,191,36,.2); color:#fcd34d; } .imp-low{ background:rgba(52,211,153,.2); color:#6ee7b7; }
.ai-rec-go { color:#7f8fc0; flex:0 0 auto; }
.ai-rec:hover .ai-rec-go { color:#c4b5fd; }

/* Premium KPI stat cards */
.stat-card { background:var(--card); border:1px solid var(--line); border-radius:var(--radius); padding:16px 18px 12px;
  box-shadow:var(--shadow-sm); height:100%; position:relative; overflow:hidden; transition:box-shadow .18s, transform .18s; animation: fadeup .5s both; }
.stat-card:hover{ box-shadow:var(--shadow); transform:translateY(-2px); }
.stat-card::after{ content:""; position:absolute; left:0; top:0; bottom:0; width:4px; opacity:0; }
.stat-card.is-ok::after{ background:var(--ok); opacity:1; } .stat-card.is-warn::after{ background:var(--warn); opacity:1; }
.stat-top{ display:flex; align-items:center; justify-content:space-between; margin-bottom:10px; }
.stat-ic{ width:40px; height:40px; border-radius:12px; display:grid; place-items:center; color:#fff; font-size:1.1rem;
  box-shadow:0 6px 16px rgba(16,24,40,.16), inset 0 1px 0 rgba(255,255,255,.3); }
.stat-ic.g-blue{ background:linear-gradient(135deg,#38bdf8,#2563eb); }
.stat-ic.g-indigo{ background:linear-gradient(135deg,#818cf8,#4f46e5); }
.stat-ic.g-teal{ background:linear-gradient(135deg,#2dd4bf,#0d9488); }
.stat-ic.g-emerald{ background:linear-gradient(135deg,#34d399,#059669); }
.stat-ic.g-amber{ background:linear-gradient(135deg,#fbbf24,#d97706); }
.stat-ic.g-rose{ background:linear-gradient(135deg,#fb7185,#e11d48); }
.stat-target{ font-size:.64rem; font-weight:700; color:var(--ink-soft); background:#f1f5f9; padding:2px 8px; border-radius:999px; }
.stat-val{ font-size:2rem; font-weight:800; line-height:1; letter-spacing:-.02em; font-variant-numeric:tabular-nums; }
.stat-label{ font-size:.76rem; color:var(--ink-soft); font-weight:600; margin-top:2px; }
.stat-foot{ margin-top:10px; height:26px; display:flex; align-items:flex-end; }
.spark{ width:100%; height:26px; }
.spark polyline{ fill:none; stroke:var(--accent); stroke-width:2; stroke-linecap:round; stroke-linejoin:round; }
.spark.up polyline{ stroke:var(--ok); } .spark.down polyline{ stroke:var(--danger); }

/* Program risk heatmap */
.heatmap{ display:flex; flex-direction:column; gap:5px; min-width:520px; }
.heatmap-row{ display:grid; grid-template-columns: minmax(120px, 1.4fr) repeat(6, 1fr); gap:5px; align-items:center; }
.heatmap-head .heatmap-h{ font-size:.64rem; font-weight:700; text-transform:uppercase; letter-spacing:.04em; color:var(--ink-soft); text-align:center; }
.heatmap-name{ font-size:.8rem; text-decoration:none; color:var(--ink); display:flex; gap:6px; align-items:center; overflow:hidden; white-space:nowrap; }
.heatmap-name:hover{ color:var(--accent); }
.heatmap-cell{ display:block; height:30px; border-radius:7px; cursor:pointer;
  transition:transform .12s ease, box-shadow .12s ease, filter .12s ease; }
.heatmap-cell:hover{ transform:scale(1.08); filter:brightness(1.05);
  box-shadow:0 4px 12px rgba(16,24,40,.22), inset 0 0 0 2px rgba(255,255,255,.6); }
.rag-green{ background:linear-gradient(135deg,#34d399,#059669); }
.rag-amber{ background:linear-gradient(135deg,#fbbf24,#d97706); }
.rag-red{ background:linear-gradient(135deg,#fb7185,#e11d48); }
.rag-grey{ background:#e6eaf1; }
.rag-na{ background:repeating-linear-gradient(45deg,#f1f5f9,#f1f5f9 5px,#e6eaf1 5px,#e6eaf1 10px); }
.heatmap-legend{ display:flex; gap:12px; flex-wrap:wrap; }
.heatmap-legend span{ display:inline-flex; align-items:center; gap:5px; }
.hm-key{ width:12px; height:12px; border-radius:4px; display:inline-block; }

/* RASIC code chips */
.rasic { font-weight: 800; font-size: .72rem; }
.rasic-R { color: #2563eb; } .rasic-A { color: #dc2626; }
.rasic-S { color: #0d9488; } .rasic-I { color: #64748b; } .rasic-C { color: #7c3aed; }

@media (max-width: 991.98px) {
  .content { padding: 14px; }
  .hero-title { font-size: 1.5rem; }
  .subbar-inner { padding: 8px 14px; }
  .proq-nav .container-fluid { padding-left: 14px; padding-right: 14px; }
  .proq-nav .navbar-collapse {
    background: rgba(10, 16, 32, .38); border: 1px solid rgba(255, 255, 255, .1);
    border-radius: 14px; margin-top: 10px; padding: 8px;
  }
  .proq-nav .navbar-nav > .nav-item > .nav-link { color: #fff !important; }
  .proq-nav .dropdown-menu.qt-menu { width: 100%; }
  .brand-tag { display: none; }
}

@media print {
  .proq-nav, .subbar, .no-print { display: none !important; }
  .content { padding: 0; max-width: none; }
  body { background: #fff; }
}

/* ============================================================
   APQP PROJECTS LIST — "Isometric Quality World"  (.pl-* scope)
   Camera (perspective) on .pl-stage; preserve-3d on .pl-world &
   each solid — so .ch-hero's overflow:hidden CLIPS without
   FLATTENING (never put overflow/filter on .pl-world/.pl-slab).
   ============================================================ */
.pl-hero { position: relative; padding-bottom: 18px; }
.pl-hero .ch-hero-top { min-height: 172px; }            /* room beside the ziggurat */

/* --- decorative 3D stage (right side of the hero) --- */
.pl-stage {
  position: absolute; inset: 0 0 0 auto;
  width: min(46%, 500px); z-index: 0;                   /* text/stats are z-index:1 */
  pointer-events: none;                                  /* never steals button clicks */
  perspective: 1400px; perspective-origin: 58% 36%;
  overflow: hidden;                                      /* soft-clip orbs to the panel */
  border-radius: 20px;
}
/* atmosphere orbs (static blurred glow — NO animation) */
.pl-orb { position: absolute; border-radius: 50%; filter: blur(42px); pointer-events: none; }
.pl-orb.a { width: 240px; height: 240px; top: -60px; right: -30px; opacity: .5;
  background: radial-gradient(circle at 42% 40%, rgba(56,189,248,.65), transparent 70%); }
.pl-orb.b { width: 210px; height: 210px; bottom: -66px; right: 34%; opacity: .45;
  background: radial-gradient(circle at 50% 50%, rgba(139,92,246,.55), transparent 70%); }

/* --- the ziggurat world (sways as one rigid body) --- */
.pl-world {
  position: absolute; left: 50%; top: 52%; width: 0; height: 0;   /* pure anchor */
  transform-style: preserve-3d;
  transform: rotateX(58deg) rotateZ(-45deg);            /* resting isometric pose */
  will-change: transform;
  animation: plWorldSway 17s ease-in-out infinite;
}
@keyframes plWorldSway {                                /* enterprise yaw, not a spin */
  0%,100% { transform: rotateX(58deg) rotateZ(-45deg); }
  50%     { transform: rotateX(56deg) rotateZ(-51deg); }
}

/* parametric phase slab: lit top cap + 4 walls (centered-cube convention) */
.pl-slab { position: absolute; left: 0; top: 0; width: var(--sz); height: var(--sz);
  transform-style: preserve-3d; transform: translate(-50%,-50%) translateZ(var(--lift)); }
.pl-slab .fc { position: absolute; left: 50%; top: 50%; }
.pl-slab .top { width: var(--sz); height: var(--sz);
  transform: translate(-50%,-50%) translateZ(calc(var(--th)/2));
  background: var(--f-top); box-shadow: inset 0 0 0 1px rgba(224,242,254,.30); }
.pl-slab .nS, .pl-slab .nN { width: var(--sz); height: var(--th); }
.pl-slab .nE, .pl-slab .nW { width: var(--th); height: var(--sz); }
.pl-slab .nS { transform: translate(-50%,-50%) rotateX(-90deg) translateZ(calc(var(--sz)/2)); background: var(--f-south); }
.pl-slab .nN { transform: translate(-50%,-50%) rotateX(90deg)  translateZ(calc(var(--sz)/2)); background: var(--f-south); }
.pl-slab .nE { transform: translate(-50%,-50%) rotateY(90deg)  translateZ(calc(var(--sz)/2)); background: var(--f-east); }
.pl-slab .nW { transform: translate(-50%,-50%) rotateY(-90deg) translateZ(calc(var(--sz)/2)); background: var(--f-east); }
/* engraved Pn glyph on the cap (counter-rotated so it reads upright in iso) */
.pl-slab .top b { position: absolute; right: 8px; bottom: 6px; transform: rotate(45deg);
  font: 800 .6rem/1 Inter, sans-serif; letter-spacing: .05em;
  color: rgba(255,255,255,.88); text-shadow: 0 1px 1px rgba(2,6,23,.4); }
/* GOTCHA: if any wall renders inside-out, flip that wall's translateZ sign — visual tune only. */

/* gate rings (flat circles in XY → read as isometric ellipses) */
.pl-gate { position: absolute; left: 50%; top: 50%; border-radius: 50%;
  border: 2px solid rgba(56,189,248,.5);                /* --sky blueprint cyan */
  transform: translate(-50%,-50%) translateZ(var(--gz)); }
.pl-gate--base { width: 210px; height: 210px; --gz: 3px; }
.pl-gate--apex { width: 84px; height: 84px; --gz: 121px;
  border-color: rgba(52,211,153,.75);                   /* --ok launch gate = the goal */
  box-shadow: 0 0 12px rgba(52,211,153,.45), inset 0 0 8px rgba(52,211,153,.30);
  animation: plGateGlow 4.5s ease-in-out infinite; }
@keyframes plGateGlow {
  0%,100% { box-shadow: 0 0 12px rgba(52,211,153,.45), inset 0 0 8px rgba(52,211,153,.30); }
  50%     { box-shadow: 0 0 22px rgba(52,211,153,.75), inset 0 0 12px rgba(52,211,153,.50); }
}

/* blueprint floor grid + soft contact shadow */
.pl-floor { position: absolute; left: 50%; top: 50%; width: 320px; height: 320px;
  transform: translate(-50%,-50%) translateZ(0);
  background:
    repeating-linear-gradient(0deg,  rgba(148,197,253,.13) 0 1px, transparent 1px 26px),
    repeating-linear-gradient(90deg, rgba(148,197,253,.13) 0 1px, transparent 1px 26px);
  -webkit-mask-image: radial-gradient(50% 50% at 50% 50%, #000 42%, transparent 78%);
          mask-image: radial-gradient(50% 50% at 50% 50%, #000 42%, transparent 78%); }
.pl-shadow { position: absolute; left: 50%; top: 50%; width: 250px; height: 250px;
  transform: translate(-50%,-50%) translateZ(-1px);
  background: radial-gradient(50% 50% at 50% 50%, rgba(2,6,23,.55), rgba(2,6,23,0) 70%); }

/* --- KPI dark-glass stats (inside hero, below divider) --- */
.pl-stats { display: grid; grid-template-columns: repeat(4,1fr); gap: 12px;
  position: relative; z-index: 1; }
.pl-stat { position: relative; display: flex; align-items: center; gap: 12px;
  padding: 13px 15px; border-radius: 14px; border: 1px solid rgba(255,255,255,.12);
  background: rgba(10,16,32,.44);                        /* dark glass → text stays AA over shapes */
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.06); overflow: hidden; }
.pl-stat .kpi-ic { width: 38px; height: 38px; flex: 0 0 38px; border-radius: 11px;
  display: inline-flex; align-items: center; justify-content: center; color: #fff; font-size: 1rem; }
.pl-stat-lbl { font-size: .58rem; font-weight: 800; letter-spacing: .12em;
  text-transform: uppercase; color: #a9b8dc; }
.pl-stat-val { font-size: 1.5rem; font-weight: 800; line-height: 1.1; color: #fff; letter-spacing: -.01em; }
.pl-stat-val.cm-ok   { color: #6ee7b7; }
.pl-stat-val.cm-warn { color: #fcd34d; }

/* static iso-cube accent, one per stat (3 visible faces) */
.pl-cube { position: absolute; top: 12px; right: 13px; width: 28px; height: 28px;
  opacity: .9; pointer-events: none; transform-style: preserve-3d;
  transform: rotateX(58deg) rotateZ(-45deg); }
.pl-cube .cf { position: absolute; left: 50%; top: 50%; width: 20px; height: 20px; }
.pl-cube .t { transform: translate(-50%,-50%) translateZ(10px); background: var(--cb-top);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.4); }
.pl-cube .s { transform: translate(-50%,-50%) rotateX(-90deg) translateZ(10px); background: var(--cb-s); }
.pl-cube .e { transform: translate(-50%,-50%) rotateY(90deg)  translateZ(10px); background: var(--cb-e); }

/* --- refined premium sheet --- */
.pl-sheet { --pl-code-c: var(--accent-600); }
.pl-sheet thead th {
  background: linear-gradient(180deg,#132c56,#0f2145); color: #c7d4f2;
  border-bottom: 1px solid rgba(139,92,246,.28);
  font-size: .62rem; letter-spacing: .08em; text-transform: uppercase;
  font-weight: 700; padding: 11px 12px; }
.pl-sheet thead th:first-child { border-top-left-radius: var(--radius); }
.pl-sheet thead th:last-child  { border-top-right-radius: var(--radius); }
.pl-sheet tbody td { padding: 9px 12px; border-bottom: 1px solid var(--line); font-size: 13px; vertical-align: middle; }
.pl-sheet tbody tr { transition: background .12s ease; }
.pl-row { cursor: pointer; }
.pl-code { font-family: ui-monospace,SFMono-Regular,Menlo,monospace; font-weight: 700;
  font-size: .78rem; color: var(--pl-code-c);
  background: var(--accent-soft); padding: 2px 7px; border-radius: 6px; }
/* 5-pip isometric phase stepper (static, cheap, safe at hundreds of rows) */
.pl-pips { display: inline-flex; gap: 3px; vertical-align: middle; margin-right: 6px; }
.pl-pip  { width: 7px; height: 11px; border-radius: 2px; background: var(--line); transform: skewX(-12deg); }
.pl-pip.on { background: linear-gradient(135deg,#38bdf8,#2563eb); box-shadow: 0 0 6px rgba(37,99,235,.45); }
.pl-prog { height: 7px; background: #eef1f6; border-radius: 999px; }
.pl-prog .progress-bar { background: linear-gradient(90deg,#38bdf8,#4f46e5); border-radius: 999px; }
.pl-pm { display: inline-flex; align-items: center; gap: 7px; }
.pl-av { flex: 0 0 24px; width: 24px; height: 24px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: .66rem; font-weight: 800; color: #fff;
  background: linear-gradient(135deg,#818cf8,#4f46e5);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.25); }

/* clickable-row keyboard reach: real stretched-link, delete cell lifted above it */
.pl-link::after { content: ""; position: absolute; inset: 0; }   /* stretched hit-area */
.pl-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.pl-actions { position: relative; z-index: 2; }                  /* delete stays clickable/focusable */
tr.pl-row:focus-within > td { background-color: var(--accent-soft); }
.btn-ghost:focus-visible { outline: 2px solid #93c5fd; outline-offset: 2px; }

/* --- responsive + reduced motion --- */
@media (max-width: 991.98px){ .pl-stats { grid-template-columns: repeat(2,1fr); } }
@media (max-width: 767.98px){
  .pl-stage { display: none; }               /* decorative; frees hero to stack on phones */
  .pl-hero .ch-hero-top { min-height: auto; }
}
/* The global reset @ app.css:1416 (*{animation:none!important}) freezes plWorldSway
   & plGateGlow at their base (resting, fully-lit isometric) poses — still dimensional. */

/* ============================================================
   THEME SYSTEM — per-user 'Classic' (light, default) / 'Midnight'
   The switcher control (account dropdown). The Midnight palette
   override block is appended below this at file end.
   ============================================================ */
.theme-switch { display: flex; gap: 6px; }
.theme-switch .theme-form { flex: 1; }
.theme-opt { width: 100%; display: inline-flex; align-items: center; justify-content: center;
  gap: 5px; padding: 6px 8px; border: 1px solid var(--line); border-radius: 9px;
  background: var(--card); color: var(--ink-soft); font-size: .74rem; font-weight: 700;
  cursor: pointer; transition: border-color .12s ease, color .12s ease, background .12s ease; }
.theme-opt:hover { border-color: var(--accent); color: var(--accent-600); }
.theme-opt.is-on { border-color: var(--accent); color: var(--accent-600); background: var(--accent-soft); }
.theme-opt.is-on { box-shadow: 0 0 0 2px var(--accent-soft); }


/* ============================================================
   THEME: ProQ Midnight  (data-theme="midnight")
   Researched premium cool-navy soft-dark. Classic (light) stays the
   default (no override). Token block (AA-verified) + targeted sweeps of
   hard-coded light surfaces. Navbar + .ch-hero keep their brand navy.
   ============================================================ */
:root[data-theme="midnight"]{
  --bg:#0b1220; --card:#141d31; --card-raised:#1e2941;
  --surface-1:#141d31; --surface-2:#1b2438;
  --ink:#e6ecf6; --ink-soft:#93a2ba; --ink-faint:#6b7a94;
  --line:#2b3852; --line-strong:#3a4a68;
  --accent:#4c8dff; --accent-600:#7dabff; --accent-soft:#172740;
  --focus-ring:rgba(76,141,255,.40);
  --sky:#38bdf8; --indigo:#818cf8; --violet:#a78bfa; --amber:#fbbf24;
  --emerald:#34d399; --teal:#2dd4bf; --rose:#fb7185;
  --ok:#34d399; --ok-soft:#0f2a20;
  --warn:#fbbf24; --warn-soft:#332707;
  --danger:#fb7185; --danger-soft:#3a1621;
  --shadow-xs:0 1px 2px rgba(0,0,0,.45);
  --shadow-sm:0 4px 18px rgba(0,0,0,.50), inset 0 1px 0 rgba(255,255,255,.04);
  --shadow:0 12px 30px rgba(0,0,0,.55), inset 0 1px 0 rgba(255,255,255,.05);
  --shadow-lg:0 22px 50px rgba(0,0,0,.62), inset 0 1px 0 rgba(255,255,255,.06);
  color-scheme: dark;
}

/* ---- Bootstrap base surfaces & controls ---- */
[data-theme="midnight"] body,
[data-theme="midnight"] .proq-body{ background:var(--bg); color:var(--ink); }
[data-theme="midnight"] .card,
[data-theme="midnight"] .modal-content,
[data-theme="midnight"] .list-group-item,
[data-theme="midnight"] .offcanvas{ background:var(--card); color:var(--ink); border-color:var(--line); }
[data-theme="midnight"] .dropdown-menu{ background:var(--card-raised); color:var(--ink); border-color:var(--line); }
[data-theme="midnight"] .dropdown-item{ color:var(--ink); }
[data-theme="midnight"] .dropdown-item:hover,[data-theme="midnight"] .dropdown-item:focus{ background:var(--card); color:var(--ink); }
[data-theme="midnight"] .dropdown-header{ color:var(--ink-soft); }
[data-theme="midnight"] .dropdown-divider,[data-theme="midnight"] hr{ border-color:var(--line); }
[data-theme="midnight"] .card-header,[data-theme="midnight"] .card-footer{ border-color:var(--line); color:var(--ink); }
/* Bootstrap's .bg-white is !important, so it beats the card sweep above and
   leaves a WHITE header carrying light-on-dark text — measured at ~1.1:1 on
   the complaints pages, and the same pattern sits in 26 templates across 7
   modules. Neutralised once here rather than 26 times there. The navbar's
   co-brand chip is deliberately white in both themes and is not a card. */
[data-theme="midnight"] .card-header.bg-white,
[data-theme="midnight"] .card-footer.bg-white,
[data-theme="midnight"] .card > .bg-white{ background-color:var(--card)!important; }
[data-theme="midnight"] .form-control,[data-theme="midnight"] .form-select{ background-color:var(--card); color:var(--ink); border-color:var(--line-strong); }
[data-theme="midnight"] .form-control::placeholder{ color:var(--ink-faint); }
[data-theme="midnight"] .form-control:focus,[data-theme="midnight"] .form-select:focus{ background-color:var(--card); color:var(--ink); border-color:var(--accent); box-shadow:0 0 0 3px var(--focus-ring); }
[data-theme="midnight"] .form-select{ background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%2393a2ba' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3E%3C/svg%3E"); }
[data-theme="midnight"] .text-muted,[data-theme="midnight"] .text-muted-2{ color:var(--ink-soft) !important; }
[data-theme="midnight"] .table{ color:var(--ink); --bs-table-color:var(--ink); }
[data-theme="midnight"] .table > :not(caption) > * > *{ background-color:transparent; color:inherit; }
/* Bootstrap's contextual rows (.table-danger & co.) hard-code LIGHT-theme
   values on their own CSS vars — --bs-table-color:#000 among them — so the
   sweep above emptied their background and left black text on a dark card:
   measured rgb(0,0,0) on the complaints register's late rows. Restated here
   as translucent tints that keep the meaning and the ink readable. 150
   contextual rows across the app ride on this one block. */
[data-theme="midnight"] .table-danger{ --bs-table-color:var(--ink); --bs-table-bg:rgba(220,38,38,.16); }
[data-theme="midnight"] .table-warning{ --bs-table-color:var(--ink); --bs-table-bg:rgba(217,119,6,.15); }
[data-theme="midnight"] .table-success{ --bs-table-color:var(--ink); --bs-table-bg:rgba(22,163,74,.14); }
[data-theme="midnight"] .table-info{ --bs-table-color:var(--ink); --bs-table-bg:rgba(14,165,233,.14); }
[data-theme="midnight"] .table-primary{ --bs-table-color:var(--ink); --bs-table-bg:rgba(37,99,235,.16); }
[data-theme="midnight"] .table-light{ --bs-table-color:var(--ink); --bs-table-bg:var(--card-raised); }
/* `> * > *` is for the class on a SECTION — thead.table-light > tr > th. On a
   ROW it also reaches tr > td > span, and the tints above are translucent, so
   a nested span was painted twice: .15 over .15 is .28, and every badge and
   muted line inside a flagged row sat in a visibly darker box than the cell
   around it. `:not(tr)` keeps the section case and leaves the row to the
   `tr.table-*  > *` rules below, which paint the cell once. Measured in
   Chrome on a flagged andon row, not inferred. */
[data-theme="midnight"] :not(tr).table-danger > * > *,
[data-theme="midnight"] :not(tr).table-warning > * > *,
[data-theme="midnight"] :not(tr).table-success > * > *,
[data-theme="midnight"] :not(tr).table-info > * > *,
[data-theme="midnight"] :not(tr).table-primary > * > *,
[data-theme="midnight"] :not(tr).table-light > * > *,
[data-theme="midnight"] tr.table-danger > *,
[data-theme="midnight"] tr.table-warning > *,
[data-theme="midnight"] tr.table-success > *,
[data-theme="midnight"] tr.table-info > *,
[data-theme="midnight"] tr.table-primary > *,
[data-theme="midnight"] tr.table-light > *{ background-color:var(--bs-table-bg); color:var(--ink); }
[data-theme="midnight"] .table-hover > tbody > tr:hover > *{ --bs-table-hover-bg:#1e2941; --bs-table-hover-color:var(--ink); }
[data-theme="midnight"] .btn-outline-secondary{ color:var(--ink-soft); border-color:var(--line-strong); }
[data-theme="midnight"] .btn-outline-secondary:hover{ background:var(--card-raised); color:var(--ink); }
/* The other outline variants never had a Midnight rule. As ANCHORS the blunt
   `a` rule above was repainting them the accent, which happened to be legible
   and hid the gap; as `<button>` elements — which most of them are — they kept
   Bootstrap's own `#0d6efd` / `#198754` and sat at about 2.9:1 on a dark card.
   So each takes its own brightened token, the way `-secondary` already did,
   and the hover fills with a dark tint of the same hue rather than the solid
   colour, which is the convention the soft chips follow. */
[data-theme="midnight"] .btn-outline-primary{ color:var(--accent); border-color:color-mix(in srgb,var(--accent) 42%,transparent); }
[data-theme="midnight"] .btn-outline-primary:hover,
[data-theme="midnight"] .btn-outline-primary:focus-visible{ background:color-mix(in srgb,var(--accent) 20%,var(--card)); color:var(--accent); border-color:var(--accent); }
[data-theme="midnight"] .btn-outline-success{ color:var(--ok); border-color:color-mix(in srgb,var(--ok) 42%,transparent); }
[data-theme="midnight"] .btn-outline-success:hover,
[data-theme="midnight"] .btn-outline-success:focus-visible{ background:color-mix(in srgb,var(--ok) 20%,var(--card)); color:var(--ok); border-color:var(--ok); }
[data-theme="midnight"] .btn-outline-danger{ color:var(--danger); border-color:color-mix(in srgb,var(--danger) 42%,transparent); }
[data-theme="midnight"] .btn-outline-danger:hover,
[data-theme="midnight"] .btn-outline-danger:focus-visible{ background:color-mix(in srgb,var(--danger) 20%,var(--card)); color:var(--danger); border-color:var(--danger); }
[data-theme="midnight"] .btn-outline-warning{ color:var(--warn); border-color:color-mix(in srgb,var(--warn) 42%,transparent); }
[data-theme="midnight"] .btn-outline-warning:hover,
[data-theme="midnight"] .btn-outline-warning:focus-visible{ background:color-mix(in srgb,var(--warn) 20%,var(--card)); color:var(--warn); border-color:var(--warn); }
[data-theme="midnight"] .btn-close{ filter:invert(1) grayscale(1) brightness(1.4); }
[data-theme="midnight"] .btn-link{ color:var(--accent); }
/* `[data-theme="midnight"] a` is 0-1-1, which outranks a component's own
   `.tile{color:#fff}` at 0-1-0 — so in Midnight every coloured anchor-object
   in the app was repainted the accent: the phone home's tiles rendered a
   mid-blue label on a bright blue tile, and the owed rows the same on red.
   Classic has no `a` colour rule of its own, so the component always won
   there, which is exactly why this only showed in the dark theme.
   `:where()` contributes nothing to specificity, so this now sits at 0-0-1
   — the same weight Bootstrap's own `a` carries, and later in the file, so
   a bare link still turns accent while anything that styles itself wins. */
:where([data-theme="midnight"]) a{ color:var(--accent); }
[data-theme="midnight"] .page-title,[data-theme="midnight"] h1,[data-theme="midnight"] h2,[data-theme="midnight"] h3,[data-theme="midnight"] h4,[data-theme="midnight"] h5,[data-theme="midnight"] strong{ color:var(--ink); }

/* ---- editable grids / cell-input ---- */
[data-theme="midnight"] .grid-table .cell-input:hover,
[data-theme="midnight"] .grid-table .cell-input:focus{ background:var(--card-raised); border-color:var(--accent); }
[data-theme="midnight"] .action-table .cell-input,
[data-theme="midnight"] .risk-table .cell-input,
[data-theme="midnight"] .readiness-table .cell-input,
[data-theme="midnight"] .escalation-table .cell-input{ background:var(--card); color:var(--ink); border-color:var(--line-strong); }
[data-theme="midnight"] .sticky-col{ background:var(--card); }

/* ---- sheet/table chrome ---- */
[data-theme="midnight"] .ctm-table thead th,
[data-theme="midnight"] .del-table thead th,
[data-theme="midnight"] .gr-table thead th,
[data-theme="midnight"] .gr-matrix thead th{ background:var(--card-raised); color:var(--ink-soft); border-color:var(--line); }
[data-theme="midnight"] .ctm-table tbody tr:not(.ctm-group):hover td,
[data-theme="midnight"] .del-table tbody tr:hover td,
[data-theme="midnight"] .gr-table tbody tr:hover td,
[data-theme="midnight"] .gr-matrix tbody tr:hover td{ background:#1e2941; }
[data-theme="midnight"] .ctm-group td{ background:#101a2e; }
[data-theme="midnight"] .del-row.is-na > td{ background:#101828; color:var(--ink-faint); }
[data-theme="midnight"] .del-table thead th, [data-theme="midnight"] .gr-table thead th{ }
[data-theme="midnight"] .del-legend,[data-theme="midnight"] .gr-legend{ background:var(--card); }
[data-theme="midnight"] .rag-grey{ background:#1a2540; color:var(--ink-faint); }
[data-theme="midnight"] .rag-na{ background:repeating-linear-gradient(45deg,#141d31,#141d31 4px,#0f1626 4px,#0f1626 8px); color:var(--ink-faint); }
[data-theme="midnight"] .gr-focus-code{ background:var(--card); color:var(--ink-soft); border-color:var(--line); }
[data-theme="midnight"] .gr-missing{ box-shadow:0 0 0 2px var(--card); }
[data-theme="midnight"] .gr-stack .gr-sig{ box-shadow:inset 0 1px 0 rgba(255,255,255,.15), 0 0 0 2px var(--card); }
[data-theme="midnight"] .gr-prog,[data-theme="midnight"] .pl-prog{ background:#0f1626; }
[data-theme="midnight"] .pl-pip{ background:#26324c; }

/* ---- badge-soft foregrounds + RASIC/status pill colors ---- */
[data-theme="midnight"] .badge-soft.ok{ color:var(--ok); }
[data-theme="midnight"] .badge-soft.warn{ color:var(--warn); }
[data-theme="midnight"] .badge-soft.muted{ background:var(--card-raised); color:var(--ink-soft); }
[data-theme="midnight"] .badge-soft.purple{ background:#241a3d; color:var(--violet); }
[data-theme="midnight"] .rasic-R{ color:var(--accent-600); } [data-theme="midnight"] .rasic-A{ color:var(--danger); }
[data-theme="midnight"] .rasic-S{ color:var(--teal); } [data-theme="midnight"] .rasic-I{ color:var(--ink-soft); } [data-theme="midnight"] .rasic-C{ color:var(--violet); }
[data-theme="midnight"] .ctm-table select.cell-input.rasic{ color:var(--ink-faint); }
[data-theme="midnight"] .ctm-table select.cell-input.rasic.rasic-A{ color:var(--danger); }
[data-theme="midnight"] .ctm-table select.cell-input.rasic.rasic-S{ color:var(--teal); }
[data-theme="midnight"] .ctm-table select.cell-input.rasic.rasic-I{ color:var(--ink-soft); }
[data-theme="midnight"] .ctm-table select.cell-input.rasic.rasic-C{ color:var(--violet); }
[data-theme="midnight"] .rp-A{ background:var(--danger-soft); color:var(--danger); }
[data-theme="midnight"] .rp-S{ background:#0f2a26; color:var(--teal); }
[data-theme="midnight"] .rp-I{ background:var(--card-raised); color:var(--ink-soft); }
[data-theme="midnight"] .rp-C{ background:#241a3d; color:var(--violet); }
[data-theme="midnight"] .del-status.st-not_started,[data-theme="midnight"] .del-status.st-na{ background:var(--card-raised); color:var(--ink-soft); }
[data-theme="midnight"] .del-icon{ background:var(--card); border-color:var(--line-strong); color:var(--ink-soft); }
[data-theme="midnight"] .del-submit{ background:var(--accent-soft); }

/* ---- gradient icon chips: pull back so they don't bloom on dark ---- */
[data-theme="midnight"] .kpi-ic,[data-theme="midnight"] .qt-ico,[data-theme="midnight"] .stat-ic,[data-theme="midnight"] .del-icon.gradient{ filter:saturate(.85) brightness(.92); }

/* ---- charter cards ---- */
[data-theme="midnight"] .charter-card{ background:linear-gradient(180deg,var(--card),#111a2c); border-color:var(--line);
  box-shadow:var(--shadow-sm); }
[data-theme="midnight"] .cc-head:not(.cc-head-alert){ background:linear-gradient(180deg,rgba(30,41,65,.5),transparent); }
[data-theme="midnight"] .cc-head{ border-color:var(--line); color:var(--ink-soft); }
[data-theme="midnight"] .charter-notice.border-bottom{ border-color:var(--line) !important; }
[data-theme="midnight"] .qt-tool{ background:var(--card-raised); border-color:var(--line); }

/* ---- chat panel (messenger look, all raw hex) ---- */
[data-theme="midnight"] .chat-scroll{ background:#0f1626;
  background-image:radial-gradient(rgba(255,255,255,.04) 1px,transparent 1px),radial-gradient(rgba(255,255,255,.02) 1px,transparent 1px); }
[data-theme="midnight"] .chat-bubble{ background:var(--card-raised); color:var(--ink); box-shadow:0 1px 1.5px rgba(0,0,0,.4); }
[data-theme="midnight"] .chat-msg.me .chat-bubble{ background:#13351f; color:var(--ink); }
[data-theme="midnight"] .chat-input{ background:var(--card); border-color:var(--line); }
[data-theme="midnight"] .chat-field{ background:#1e2941; color:var(--ink); border-color:var(--line-strong); }
[data-theme="midnight"] .chat-field:focus{ background:var(--card-raised); box-shadow:0 0 0 3px var(--focus-ring); }
[data-theme="midnight"] .chat-time{ color:rgba(230,236,246,.45); }

/* ---- scrollbars + flatpickr ---- */
[data-theme="midnight"] .chat-scroll::-webkit-scrollbar-thumb,
[data-theme="midnight"] .cc-body.notice-scroll::-webkit-scrollbar-thumb{ background:rgba(230,236,246,.20); }
[data-theme="midnight"] .flatpickr-calendar{ background:var(--card-raised); color:var(--ink); border-color:var(--line); box-shadow:var(--shadow); }
[data-theme="midnight"] .flatpickr-day{ color:var(--ink); }
[data-theme="midnight"] .flatpickr-day:hover{ background:var(--card); }
[data-theme="midnight"] .flatpickr-day.flatpickr-disabled,[data-theme="midnight"] .flatpickr-day.prevMonthDay,[data-theme="midnight"] .flatpickr-day.nextMonthDay{ color:var(--ink-faint); }
[data-theme="midnight"] .flatpickr-months .flatpickr-month,[data-theme="midnight"] .flatpickr-weekday,[data-theme="midnight"] .flatpickr-current-month input.cur-year{ color:var(--ink-soft); }
[data-theme="midnight"] .flatpickr-months .flatpickr-prev-month svg,[data-theme="midnight"] .flatpickr-months .flatpickr-next-month svg{ fill:var(--ink-soft); }

/* ---- subbar + separators so heroes/navbar don't merge with page ---- */
[data-theme="midnight"] .subbar{ background:var(--card); border-color:var(--line); }
[data-theme="midnight"] .ch-hero,[data-theme="midnight"] .proq-nav{ border:1px solid var(--line); }
[data-theme="midnight"] .proq-nav{ border-width:0 0 1px 0; }
[data-theme="midnight"] .btn-icon{ background:var(--card-raised); border-color:var(--line); color:var(--ink-soft); }
[data-theme="midnight"] .empty-state{ color:var(--ink-soft); }
[data-theme="midnight"] .progress{ background:#0f1626; }

/* ---- Midnight: extra sweeps found in visual QA ---- */
/* RASIC pill backgrounds (S/I/C had hard-coded light tints) */
[data-theme="midnight"] .ctm-table select.cell-input.rasic.rasic-S{ background:#0f2a26; }
[data-theme="midnight"] .ctm-table select.cell-input.rasic.rasic-I{ background:var(--card-raised); }
[data-theme="midnight"] .ctm-table select.cell-input.rasic.rasic-C{ background:#241a3d; }
/* charter notice titles + any hard body text */
[data-theme="midnight"] .text-body{ color:var(--ink) !important; }
[data-theme="midnight"] .charter-notice .cn-title{ color:var(--ink) !important; }
[data-theme="midnight"] .charter-notice{ border-color:var(--line) !important; }
[data-theme="midnight"] .charter-notice:hover{ background:var(--card-raised); }
/* phase progress island rows */
[data-theme="midnight"] .pp-row .pp-name,[data-theme="midnight"] .phase-prog-name{ color:var(--ink); }
[data-theme="midnight"] .progress{ background:#0f1626; }


/* ============================================================
   BOARD (single program) — "You are here" ziggurat + hero
   Extends the .pl-* Isometric Quality World for one project's
   working board. Presentation only; reuses the shipped solids,
   stats and tokens verbatim. Scope: .brd-*, .pl-slab.is-*,
   .pl-gate--base.is-current, .pl-stat text/prog extras, and
   ONE new @keyframes plHerePulse. The Timeline hero reuses the
   shipped .pl-* verbatim and needs no rules from this block.
   ============================================================ */

/* The board hero hosts in-panel dropdowns (Automate / Status) that must
   ESCAPE the panel — .ch-hero's own overflow:hidden would clip them. The
   3D world still self-clips via .pl-stage{overflow:hidden}, so opening the
   hero up is safe. Lift the head layer above the stats so open menus never
   paint behind them. */
.brd-hero { overflow: visible; }
.brd-hero .ch-hero-top { z-index: 3; align-items: flex-start; }

/* left column: identity + toolbar, capped so it never covers the ziggurat */
.brd-head { display: flex; flex-direction: column; gap: 12px; max-width: 60%; min-width: 0; }
.brd-id { display: flex; align-items: flex-start; gap: 12px; min-width: 0; }
.brd-back { flex: 0 0 auto; }
.brd-titles { min-width: 0; }
.brd-tags { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.brd-tags h1 { margin-right: 2px; }

/* the emerald "you are here" locator pill */
.brd-here { display: inline-flex; align-items: center; gap: 5px;
  font-size: .6rem; font-weight: 800; letter-spacing: .08em; text-transform: uppercase;
  color: #6ee7b7; background: rgba(52,211,153,.16);
  border: 1px solid rgba(52,211,153,.34); padding: 3px 9px; border-radius: 999px;
  box-shadow: inset 0 0 12px rgba(52,211,153,.14); white-space: nowrap; }
.brd-here i { font-size: .72rem; }

/* action toolbar — ghost buttons, wraps within the left column */
.brd-tools { position: relative; display: flex; gap: 8px; flex-wrap: wrap; align-items: flex-start; }

/* dark-glass stat extras: secondary line, rose value, inline progress bar.
   .pl-stat>div is a safe additive (min-width:0 only enables ellipsis) and
   does not regress the shipped index/timeline stats. */
.pl-stat > div { min-width: 0; }
.pl-stat-sub { font-size: .62rem; color: #93a4cc; margin-top: 3px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pl-stat-val.cm-danger { color: #fda4af; }                 /* rose-300 — AA on dark glass */
.pl-stat .pl-prog { margin-top: 8px; width: 100%;
  background: rgba(255,255,255,.14); }                     /* dark track; bar gradient inherited */

/* ---- ziggurat focus: light the project's CURRENT phase ---- */
/* non-current slabs recede so the live phase is unmistakably the subject */
.pl-slab.is-dim { opacity: .38; }
.pl-slab.is-dim .top { box-shadow: inset 0 0 0 1px rgba(224,242,254,.16); }

/* current slab: lifted higher on its own axis (centering convention intact),
   brighter engraved cap, emerald rim-glow that gently pulses */
.pl-slab.is-current { transform: translate(-50%,-50%) translateZ(calc(var(--lift) + 18px)); }
.pl-slab.is-current .top {
  box-shadow: inset 0 0 0 1px rgba(236,253,245,.60),
              inset 0 0 20px rgba(110,231,183,.35),
              0 0 26px rgba(52,211,153,.50);
  animation: plHerePulse 4.6s ease-in-out infinite; }
.pl-slab.is-current .top b { color: #ecfdf5;
  text-shadow: 0 0 10px rgba(52,211,153,.9), 0 1px 1px rgba(2,6,23,.55); }

/* phase 0 (Program Concept) has no slab — light the base gate ring instead */
.pl-gate--base.is-current { border-color: rgba(52,211,153,.85);
  box-shadow: 0 0 16px rgba(52,211,153,.50), inset 0 0 10px rgba(52,211,153,.35);
  animation: plGateGlow 4.6s ease-in-out infinite; }   /* reuse the shipped emerald pulse */

@keyframes plHerePulse {
  0%,100% { box-shadow: inset 0 0 0 1px rgba(236,253,245,.60),
                        inset 0 0 20px rgba(110,231,183,.35), 0 0 22px rgba(52,211,153,.40); }
  50%     { box-shadow: inset 0 0 0 1px rgba(236,253,245,.78),
                        inset 0 0 26px rgba(110,231,183,.52), 0 0 34px rgba(52,211,153,.72); }
}
/* The global reduced-motion reset (app.css:1416 *{animation:none!important})
   freezes plHerePulse + this base-gate plGateGlow at the fully-lit resting
   box-shadow declared above — the current phase still reads raised + glowing.
   Only ONE new animated element (the current slab); the apex "goal" gate keeps
   its shipped pulse. Board animated total = 3 (plWorldSway + apex plGateGlow +
   current-slab pulse); Timeline animated total = 2 (the shipped pair). */

/* responsive: the shipped @media(max-width:767.98px){.pl-stage{display:none}}
   already hides the world; open the head to full width so it stacks cleanly */
@media (max-width: 767.98px){ .brd-head { max-width: 100%; } }

/* Board ziggurat — fully framed within the hero (scaled down + re-centred).
   The scale is carried in the sway keyframes so the animation never drops it;
   reduced-motion freezes at the scaled resting pose. Board-scoped only. */
.brd-hero .pl-stage { width: min(44%, 480px); }
.brd-hero .pl-world { left: 43%; top: 58%;
  transform: scale(.7) rotateX(58deg) rotateZ(-45deg);
  animation: brdWorldSway 17s ease-in-out infinite; }
@keyframes brdWorldSway {
  0%,100% { transform: scale(.7) rotateX(58deg) rotateZ(-45deg); }
  50%     { transform: scale(.7) rotateX(56deg) rotateZ(-51deg); }
}

/* ── Control Plan premium touches ─────────────────────────────────────────
   Index list: a status colour-stripe on the Part cell + a monospace part no.
   column; the detail hero reuses the shared .fmea-hero premium pattern. */
.cp-accent { display:inline-block; width:3px; height:1.1em; border-radius:2px;
  margin-right:.5rem; vertical-align:-2px; background:var(--line); }
.cp-accent-released  { background:var(--ok); }
.cp-accent-in_review { background:var(--warn); }
.cp-accent-draft     { background:var(--line); }
.cp-row:hover .cp-accent { filter:brightness(1.08); }
.mono-num { font-variant-numeric:tabular-nums;
  font-family:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,monospace;
  font-size:.86em; letter-spacing:-.01em; }

/* ── Company co-branding (tenant logo beside the retained ProQ brand) ──────
   The navbar stays navy in both themes, so the company logo sits in a white
   rounded chip to guarantee legibility for any logo (light or dark artwork). */
.co-brand { display:inline-flex; align-items:center; gap:.55rem; }
.co-brand-divider { width:1px; height:34px; background:rgba(255,255,255,.28); border-radius:1px; }
.co-brand-logo { /* light-only: the white chip a company logo sits in, on the navy navbar */
  height:42px; max-width:200px; width:auto; object-fit:contain; display:block;
  background:#fff; border-radius:7px; padding:3px 8px;
  box-shadow:0 1px 2px rgba(2,6,23,.22); border:1px solid rgba(255,255,255,.55);
}
@media (max-width: 991.98px){ .co-brand-logo{ height:36px; max-width:150px; } }
@media (max-width: 575.98px){ .co-brand-logo{ height:30px; max-width:112px; } }

/* Branding settings preview surface */
.brand-preview {
  display:flex; align-items:center; justify-content:center; min-height:120px;
  background:var(--bg); border:1px dashed var(--line); border-radius:12px; padding:1rem;
}
.brand-preview img { max-height:96px; max-width:100%; object-fit:contain; }
.brand-preview-navy {
  display:inline-flex; align-items:center; gap:.6rem; padding:.5rem .8rem;
  border-radius:10px; background:#0b1220;
}
.brand-preview-navy img { /* light-only: the same chip, previewed on navy */ height:42px; max-width:200px; object-fit:contain; background:#fff; border-radius:7px; padding:3px 8px; border:1px solid rgba(255,255,255,.55); }

/* ── PPAP per-element comment thread ──────────────────────────────────────
   A collapsible discussion under each PPAP element row (what to upload, the
   reason for a rejection, follow-ups). Token-driven so it themes in Midnight. */
.ppap-cmt-toggle { color: var(--ink-3, #64748b); text-decoration: none; vertical-align: baseline; }
.ppap-cmt-toggle:hover { color: var(--accent); }
.ppap-cmt-count { font-size: .7rem; font-weight: 700; }
.ppap-cmt-count:not(:empty) {
  display: inline-block; min-width: 1.1em; padding: 0 .3em; margin-left: .2em;
  text-align: center; border-radius: 999px; color: #fff;
  background: var(--accent); line-height: 1.35;
}
.ppap-cmt-row > td { background: var(--bg); }
.ppap-comments {
  padding: .75rem 1rem; margin: 0 .5rem .35rem 2.2rem;
  border-left: 3px solid var(--accent); border-radius: 0 8px 8px 0;
  background: var(--card);
}
.ppap-cmt-head { font-size: .78rem; color: var(--ink-3, #64748b); margin-bottom: .5rem; }
.ppap-cmt-thread { display: flex; flex-direction: column; gap: .5rem; margin-bottom: .6rem; }
.ppap-cmt { padding: .45rem .65rem; border-radius: 8px; background: var(--bg); border: 1px solid var(--line); }
.ppap-cmt-meta { display: flex; gap: .5rem; align-items: baseline; margin-bottom: .15rem; }
.ppap-cmt-author { font-weight: 600; font-size: .82rem; color: var(--ink); }
.ppap-cmt-time { font-size: .72rem; color: var(--ink-3, #64748b); }
.ppap-cmt-body { font-size: .85rem; color: var(--ink); white-space: pre-wrap; }
.ppap-cmt-empty { font-size: .82rem; color: var(--ink-3, #64748b); font-style: italic; }
.ppap-cmt-form { display: flex; gap: .5rem; align-items: flex-start; }
.ppap-cmt-form textarea { resize: vertical; }

/* ── PPAP create: requirements-applicability checklist ────────────────────── */
.ppap-req-config { max-height: 300px; overflow-y: auto; padding: .25rem; background: var(--card); }
.ppap-req-item { display: flex; align-items: center; gap: .6rem; padding: .35rem .55rem;
  margin: 0; border-radius: 6px; cursor: pointer; }
.ppap-req-item:hover { background: var(--bg); }
.ppap-req-item input { margin: 0; flex: 0 0 auto; }
.ppap-req-item.req-off { opacity: .5; }
.ppap-req-code { font-variant-numeric: tabular-nums; font-weight: 600; font-size: .82rem;
  min-width: 46px; color: var(--ink); }
.ppap-req-name { flex: 1 1 auto; font-size: .85rem; color: var(--ink); }
.ppap-req-badge { flex: 0 0 auto; min-width: 82px; text-align: center; }

/* ══ SPC premium — 3D icons + capability visuals ═══════════════════════════ */
/* Genuinely dimensional icon chips: gradient face + glossy top + solid
   extrusion (stacked shadows) + floating drop shadow. Used across SPC KPIs. */
.ic3d { position: relative; width: 46px; height: 46px; border-radius: 13px;
  display: grid; place-items: center; color: #fff; font-size: 1.35rem; flex: 0 0 auto;
  background: linear-gradient(150deg, var(--i1), var(--i2));
  box-shadow: inset 0 1.5px 0 rgba(255,255,255,.55), inset 0 -7px 11px rgba(0,0,0,.20),
    0 2px 0 var(--is), 0 3px 0 var(--is), 0 4px 0 var(--is), 0 5px 0 var(--is),
    0 6px 0 var(--is), 0 13px 20px -5px rgba(2,6,23,.42);
  transition: transform .2s cubic-bezier(.2,.7,.3,1), box-shadow .2s ease; }
.ic3d::after { content:""; position:absolute; inset:3px 3px 52% 3px;
  border-radius: 10px 10px 42% 42%;
  background: linear-gradient(180deg, rgba(255,255,255,.45), rgba(255,255,255,0));
  pointer-events:none; }
.ic3d i { position: relative; z-index: 1; filter: drop-shadow(0 1px 1px rgba(0,0,0,.28)); }
.ic3d:hover { transform: translateY(-3px); }
.ic3d-indigo  { --i1:#818cf8; --i2:#4f46e5; --is:#3730a3; }
.ic3d-teal    { --i1:#2dd4bf; --i2:#0d9488; --is:#115e59; }
.ic3d-emerald { --i1:#34d399; --i2:#059669; --is:#065f46; }
.ic3d-amber   { --i1:#fbbf24; --i2:#d97706; --is:#92400e; }
.ic3d-rose    { --i1:#fb7185; --i2:#e11d48; --is:#9f1239; }
.ic3d-slate   { --i1:#94a3b8; --i2:#475569; --is:#334155; }
.ic3d-violet  { --i1:#a78bfa; --i2:#7c3aed; --is:#5b21b6; }
.ic3d-sm { width:40px; height:40px; font-size:1.15rem; border-radius:11px; }

/* SPC hero KPI stat (3D icon + value) */
.spc-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(148px, 1fr)); gap: 1rem 1.1rem; }
.spc-stat { display: flex; align-items: center; gap: .8rem; }
.spc-stat-body { min-width: 0; }
.spc-stat-val { font-size: 1.5rem; font-weight: 800; line-height: 1; color: var(--ink);
  font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
.spc-stat-val.sm { font-size: 1.15rem; }
.spc-stat-lbl { font-size: .68rem; text-transform: uppercase; letter-spacing: .05em;
  color: var(--ink-3,#64748b); margin-top: .28rem; font-weight: 600; }
.spc-stat-sub { font-size: .74rem; color: var(--ink-3,#64748b); margin-top: .1rem; }
.spc-stat-sub.ok { color: var(--ok); } .spc-stat-sub.warn { color: var(--warn); }
.spc-stat-sub.danger { color: var(--danger); }

/* Capability statistics table (Minitab-style) */
.cap-table { width: 100%; font-size: .85rem; border-collapse: collapse; }
.cap-table caption { text-align: left; font-size: .72rem; text-transform: uppercase;
  letter-spacing: .04em; color: var(--ink-3,#64748b); font-weight: 700; padding: .2rem 0 .3rem; }
.cap-table th { text-align: right; font-weight: 600; color: var(--ink-3,#64748b);
  font-size: .72rem; padding: .3rem .5rem; }
.cap-table th:first-child { text-align: left; }
.cap-table td { padding: .34rem .5rem; border-top: 1px solid var(--line);
  font-variant-numeric: tabular-nums; text-align: right; color: var(--ink); }
.cap-table td:first-child { text-align: left; font-weight: 600; }
.cap-table tr.cap-hi td { background: color-mix(in srgb, var(--accent) 7%, transparent); }

/* Capability plot — process spread vs spec, as positioned bars */
.cap-plot { display: flex; flex-direction: column; gap: .55rem; }
.cap-plot-row { display: grid; grid-template-columns: 68px 1fr; align-items: center; gap: .6rem; }
.cap-plot-lbl { font-size: .74rem; color: var(--ink-3,#64748b); text-align: right; }
.cap-plot-track { position: relative; height: 16px; border-radius: 8px; background: var(--bg);
  border: 1px solid var(--line); }
.cap-plot-fill { position: absolute; top: 2px; bottom: 2px; border-radius: 6px; }
.cap-plot-fill.spec { background: repeating-linear-gradient(90deg, color-mix(in srgb,var(--ink) 12%,transparent) 0 6px, transparent 6px 12px); border:1px dashed var(--ink-3,#94a3b8); }
.cap-plot-fill.overall { background: linear-gradient(90deg,#818cf8,#4f46e5); }
.cap-plot-fill.within  { background: linear-gradient(90deg,#2dd4bf,#0d9488); }
.cap-plot-mean { position: absolute; top: -3px; bottom: -3px; width: 2px; background: var(--danger); }

/* Quadrant chip */
.spc-quad { display:inline-flex; align-items:center; gap:.4rem; padding:.25rem .6rem;
  border-radius: 999px; font-size:.78rem; font-weight:600; }
.spc-quad .q-num { font-weight:800; font-variant-numeric: tabular-nums; }

/* Chart canvas sizing */
.spc-chart-box { position: relative; height: 260px; }
.spc-chart-box.tall { height: 320px; }

/* ── Spreadsheet data-grid (SPC / MSA measurement entry) ─────────────────── */
.dgrid { --dg-line: var(--line); }
.dgrid table { border-collapse: separate; border-spacing: 0; width: 100%;
  font-variant-numeric: tabular-nums; }
.dgrid thead th { position: sticky; top: 0; z-index: 2; background: var(--card);
  border-bottom: 2px solid var(--dg-line); font-size: .7rem; text-transform: uppercase;
  letter-spacing: .03em; color: var(--ink-3,#64748b); font-weight: 700;
  padding: .45rem .5rem; text-align: center; white-space: nowrap; }
.dgrid tbody td { padding: 0; border-bottom: 1px solid var(--dg-line);
  border-right: 1px solid color-mix(in srgb, var(--dg-line) 55%, transparent); }
.dgrid tbody td:last-child { border-right: 0; }
.dgrid .dgrid-rn, .dgrid thead th.dgrid-rn-h { width: 42px; min-width: 42px; text-align: center;
  color: var(--ink-3,#64748b); font-size: .76rem; background: var(--bg);
  border-right: 1px solid var(--dg-line); font-weight: 600; }
.dgrid-cell { width: 100%; min-width: 66px; border: 0; background: transparent;
  padding: .42rem .5rem; text-align: center; color: var(--ink);
  font-variant-numeric: tabular-nums; font-size: .9rem; }
.dgrid-cell:focus { outline: none; }
.dgrid tbody td:focus-within { background: color-mix(in srgb, var(--accent) 12%, transparent);
  box-shadow: inset 0 0 0 2px var(--accent); border-radius: 4px; }
.dgrid tbody tr:hover { background: var(--bg); }
.dgrid-del { border: 0; background: transparent; color: var(--danger); opacity: .35;
  width: 30px; height: 30px; border-radius: 6px; cursor: pointer; line-height: 1; }
.dgrid tbody tr:hover .dgrid-del { opacity: .8; }
.dgrid-del:hover { opacity: 1; background: color-mix(in srgb, var(--danger) 12%, transparent); }
.dgrid-hint { display: inline-flex; align-items: center; gap: .4rem; padding: .3rem .6rem;
  border-radius: 8px; background: color-mix(in srgb, var(--accent) 8%, transparent);
  color: var(--ink-soft); font-size: .78rem; }

/* The row label stays put while the parts scroll sideways. Past about the
   eighth column the header alone stops telling you where you are, and an
   attribute study is fifteen columns wide. */
.dgrid .dgrid-rn, .dgrid thead th.dgrid-rn-h {
  position: sticky; left: 0; z-index: 3;
  width: auto; min-width: 58px; white-space: nowrap; padding: 0 .5rem;
}
.dgrid thead th.dgrid-rn-h { z-index: 4; }
/* --bg is translucent in some themes; the cells would show through it. */
.dgrid .dgrid-rn { background: var(--card); box-shadow: 1px 0 0 0 var(--dg-line); }
.dgrid thead th.dgrid-rn-h { background: var(--card); }

/* The Gage R&R grid has TWO label columns and the appraiser one is a
   rowspan, so it cannot inherit the single-column rule above. Sticky `left`
   is measured from the scroll container, not from the previous sibling —
   which is what lets the trial cell sit at 46px whether or not the appraiser
   cell is present in that row. */
.dgrid-rowspan thead th:nth-child(1) { position: sticky; left: 0; z-index: 4;
  width: 46px; min-width: 46px; background: var(--card); }
.dgrid-rowspan thead th:nth-child(2) { position: sticky; left: 46px; z-index: 4;
  width: 44px; min-width: 44px; background: var(--card); }
.dgrid-rowspan td.dgrid-rn[rowspan] { position: sticky; left: 0; z-index: 3;
  width: 46px; min-width: 46px; font-weight: 800; color: var(--accent); }
.dgrid-rowspan td.dgrid-rn:not([rowspan]) { position: sticky; left: 46px; z-index: 3;
  width: 44px; min-width: 44px; }
.dgrid-rowspan td.dgrid-rn:not([rowspan]) { box-shadow: 1px 0 0 0 var(--dg-line); }

/* Crosshair — the column and row of the active cell, the way a spreadsheet
   does it. Cheaper to read than counting headers. */
.dgrid tbody tr.dg-rh > td { background: color-mix(in srgb, var(--accent) 6%, transparent); }
.dgrid tbody td.dg-ch { background: color-mix(in srgb, var(--accent) 6%, transparent); }
.dgrid tbody tr.dg-rh > td.dg-ch { background: color-mix(in srgb, var(--accent) 13%, transparent); }
.dgrid tbody tr.dg-rh > td.dgrid-rn { color: var(--accent); font-weight: 800; }

/* A blank the person asked to be shown. Not painted by default: every cell
   is blank before you start, and a grid that opens covered in warnings
   teaches you to ignore the colour. */
.dgrid-cell.is-blank { background: color-mix(in srgb, var(--warn) 22%, transparent);
  box-shadow: inset 0 0 0 1px var(--warn); border-radius: 4px; }

/* Status strip: how much is entered, and how far off the AIAG minimum. */
.dgrid-status { display: flex; align-items: center; flex-wrap: wrap; gap: .5rem;
  margin: .55rem 0 .1rem; font-size: .76rem; color: var(--ink-soft); }
.dgrid-bar { flex: 0 0 132px; height: 6px; border-radius: 999px; overflow: hidden;
  background: color-mix(in srgb, var(--line) 70%, transparent); }
.dgrid-bar > span { display: block; height: 100%; width: 0;
  background: var(--accent); transition: width .18s ease; }
.dgrid-status.is-done .dgrid-bar > span { background: var(--ok); }
.dgrid-status.is-partial .dgrid-bar > span { background: var(--warn); }
.dgrid-count { font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.dgrid-status.is-done .dgrid-count::after { content: " ✓"; color: var(--ok); }
.dgrid-advice { font-size: .72rem; color: var(--warn); }
.dgrid-advice.ok { color: var(--ok); }
.dgrid-find { border: 1px solid var(--line); background: var(--card); color: var(--ink-soft);
  font-size: .72rem; font-weight: 700; padding: .16rem .5rem; border-radius: 7px; cursor: pointer; }
.dgrid-find:hover { border-color: var(--warn); color: var(--warn); }
.dgrid-flash { opacity: 0; transform: translateY(-2px); transition: opacity .2s ease, transform .2s ease;
  font-size: .72rem; font-weight: 700; color: var(--ok); }
.dgrid-flash.show { opacity: 1; transform: none; }
.dgrid-flash.warn { color: var(--danger); }
@media (prefers-reduced-motion: reduce) {
  .dgrid-bar > span, .dgrid-flash { transition: none; }
}

/* ── Collapsible calculation-formula panel (SPC / MSA) ────────────────────── */
.formula-toggle { cursor: pointer; user-select: none; }
.formula-chev { transition: transform .2s ease; }
.formula-toggle[aria-expanded="true"] .formula-chev { transform: rotate(180deg); }
.fx-section { padding: .5rem 0; border-top: 1px solid var(--line); }
.fx-section:first-child { border-top: 0; padding-top: 0; }
.fx-title { font-size: .74rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  color: var(--ink-soft); margin-bottom: .35rem; display: flex; align-items: baseline; gap: .5rem; }
.fx-cite { font-size: .68rem; font-weight: 500; text-transform: none; letter-spacing: 0; color: var(--ink-3,#64748b); }
.fx-row { display: grid; grid-template-columns: 160px 1fr; gap: .5rem 1rem; align-items: baseline;
  padding: .2rem 0; }
.fx-label { font-size: .82rem; font-weight: 600; color: var(--ink); }
.fx-formula { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .84rem; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.fx-eq { color: var(--accent); font-weight: 600; margin-left: .5rem; }
@media (max-width: 575.98px){ .fx-row { grid-template-columns: 1fr; gap: .1rem; } }

/* ══ Premium polish layer — micro-interactions, toasts, command palette ═══ */
/* Elevation: subtle shadow bloom on all cards; lift reserved for KPI tiles. */
.card { transition: box-shadow .25s ease, transform .2s cubic-bezier(.2,.7,.3,1); }
.card:hover { box-shadow: var(--shadow-sm); }
.kpi-tile, .kpi-card { transition: box-shadow .25s ease, transform .2s cubic-bezier(.2,.7,.3,1); }
.kpi-tile:hover, .kpi-card:hover { transform: translateY(-3px); box-shadow: var(--shadow); }

/* Staggered entrance: content cards rise in softly on page load. */
@keyframes riseIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
main .card, .kpi-tile, .fmea-hero { animation: riseIn .45s cubic-bezier(.2,.7,.3,1) both; }
main .card:nth-child(2), .kpi-tile:nth-of-type(2) { animation-delay: .05s; }
main .card:nth-child(3), .kpi-tile:nth-of-type(3) { animation-delay: .1s; }
main .card:nth-child(4), .kpi-tile:nth-of-type(4) { animation-delay: .15s; }
main .card:nth-child(n+5) { animation-delay: .2s; }

/* Keyboard focus — a crisp, branded focus ring everywhere. */
:focus-visible { outline: none; box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 35%, transparent) !important; border-radius: 6px; }

/* Slim premium scrollbars. */
* { scrollbar-width: thin; scrollbar-color: color-mix(in srgb, var(--ink-3,#94a3b8) 45%, transparent) transparent; }
*::-webkit-scrollbar { width: 9px; height: 9px; }
*::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--ink-3,#94a3b8) 40%, transparent); border-radius: 8px; border: 2px solid transparent; background-clip: content-box; }
*::-webkit-scrollbar-thumb:hover { background: color-mix(in srgb, var(--ink-3,#94a3b8) 65%, transparent); background-clip: content-box; border: 2px solid transparent; }
*::-webkit-scrollbar-track { background: transparent; }

/* Buttons: tactile press. */
.btn:active { transform: scale(.97); }

/* ── Flash messages → floating glass toasts ── */
.toast-stack { position: fixed; top: 76px; right: 18px; z-index: 1085;
  display: flex; flex-direction: column; gap: .6rem; width: min(400px, calc(100vw - 36px)); }
.toast-stack .alert.toastified { position: relative; overflow: hidden; margin: 0;
  border: 1px solid var(--line); border-radius: 14px;
  background: color-mix(in srgb, var(--card) 88%, transparent);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  box-shadow: 0 18px 44px rgba(8,17,45,.28), inset 0 1px 0 rgba(255,255,255,.25);
  animation: toastIn .38s cubic-bezier(.2,.8,.25,1.1) both; }
@keyframes toastIn { from { opacity: 0; transform: translateX(24px) scale(.97); } to { opacity: 1; transform: none; } }
.toast-stack .alert.toast-out { transition: opacity .3s ease, transform .3s ease; opacity: 0; transform: translateX(24px); }
.toast-life { position: absolute; left: 0; bottom: 0; height: 3px; width: 100%;
  background: linear-gradient(90deg, var(--accent), color-mix(in srgb, var(--accent) 40%, transparent));
  transform-origin: left; animation: toastLife linear forwards; border-radius: 0 2px 2px 0; }
@keyframes toastLife { from { transform: scaleX(1); } to { transform: scaleX(0); } }

/* ── Command palette (⌘K / Ctrl+K) ── */
.cmdk-overlay { position: fixed; inset: 0; z-index: 1090; display: none;
  background: rgba(8, 13, 28, .45); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); }
.cmdk-overlay.open { display: flex; align-items: flex-start; justify-content: center;
  padding: min(14vh, 130px) 16px 16px; animation: cmdkFade .18s ease both; }
@keyframes cmdkFade { from { opacity: 0; } to { opacity: 1; } }
.cmdk { width: min(620px, 100%); border-radius: 18px; overflow: hidden;
  background: color-mix(in srgb, var(--card) 94%, transparent);
  border: 1px solid color-mix(in srgb, var(--line) 80%, transparent);
  box-shadow: 0 40px 90px rgba(4, 9, 24, .5), inset 0 1px 0 rgba(255,255,255,.2);
  animation: cmdkPop .22s cubic-bezier(.2,.8,.25,1.1) both; }
@keyframes cmdkPop { from { opacity: 0; transform: translateY(-14px) scale(.98); } to { opacity: 1; transform: none; } }
.cmdk-input { display: flex; align-items: center; gap: .7rem; padding: .95rem 1.1rem;
  border-bottom: 1px solid var(--line); }
.cmdk-input i { color: var(--ink-3,#64748b); font-size: 1.05rem; }
.cmdk-input input { flex: 1; border: 0; outline: none; background: transparent;
  color: var(--ink); font-size: 1.02rem; }
.cmdk-input input::placeholder { color: var(--ink-3,#94a3b8); }
.cmdk-input kbd { font-size: .68rem; color: var(--ink-3,#64748b); border: 1px solid var(--line);
  border-radius: 6px; padding: .15rem .45rem; background: var(--bg); }
.cmdk-list { max-height: 340px; overflow-y: auto; padding: .45rem; }
.cmdk-item { display: flex; align-items: center; gap: .7rem; padding: .6rem .75rem;
  border-radius: 10px; cursor: pointer; color: var(--ink); font-size: .93rem; }
.cmdk-item i { color: var(--ink-3,#64748b); width: 18px; text-align: center; }
.cmdk-item .cmdk-sec { margin-left: auto; flex: 0 0 auto; font-size: .7rem;
  color: var(--ink-3,#94a3b8); text-transform: uppercase; letter-spacing: .04em; }
/* A RECORD needs a second line and a navigation link does not: "Bracket" is
   three different documents in a real plant, and the part number, customer or
   state underneath is what tells them apart. The row stays one flex line; the
   text column is the part that carries two, and it truncates rather than
   wrapping so every row is the same height and the list stays scannable. */
.cmdk-item .cmdk-body { flex: 1; min-width: 0; display: flex;
  flex-direction: column; gap: .05rem; }
.cmdk-item .cmdk-body > span { overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
.cmdk-item .cmdk-sub { font-size: .76rem; color: var(--ink-3,#94a3b8); }
.cmdk-item.active .cmdk-sub { color: var(--ink-2,#475569); }
.cmdk-item.active { background: color-mix(in srgb, var(--accent) 12%, transparent); }
.cmdk-item.active i { color: var(--accent); }
.cmdk-empty { padding: 1.2rem; text-align: center; color: var(--ink-3,#64748b); font-size: .9rem; }
.cmdk-hint { display: inline-flex; align-items: center; gap: .3rem; margin-right: .5rem;
  padding: .28rem .6rem; border-radius: 8px; cursor: pointer; font-size: .72rem; font-weight: 600;
  color: rgba(255,255,255,.75); border: 1px solid rgba(255,255,255,.22); background: rgba(255,255,255,.08); }
.cmdk-hint:hover { background: rgba(255,255,255,.16); color: #fff; }

@media (prefers-reduced-motion: reduce) {
  main .card, .kpi-tile, .fmea-hero, .toast-stack .alert.toastified, .cmdk, .cmdk-overlay.open { animation: none !important; }
  .card, .kpi-tile, .kpi-card, .btn { transition: none !important; }
}


/* ==========================================================================
   Ported from the staging app — the shared premium primitives its module
   screens are built on (hero band, glass bar, 3D buttons, popover) plus the
   SQDCM board itself. Kept as staging wrote them so the screens render
   identically; the Midnight overrides that follow re-point the few hard-coded
   light surfaces at the design tokens.
   ========================================================================== */
/* ---- Hero band ---- */
.hero-band {
    border-radius: 22px;
    /* automotive blueprint watermark (right) over a deep premium gradient */
    background:
        url("../img/hero-automotive.3133761112b9.svg") right -6px bottom -10px / auto 168% no-repeat,
        radial-gradient(120% 160% at 92% -20%, rgba(56,189,248,0.30) 0%, rgba(56,189,248,0) 55%),
        linear-gradient(118deg, #0a1020 0%, #122a52 44%, #1b46b0 78%, #2563eb 100%);
    color: #fff;
    overflow: hidden;
    position: relative;
    box-shadow: 0 18px 46px rgba(8, 17, 45, 0.34),
                inset 0 1px 0 rgba(255, 255, 255, 0.10);
    border: 1px solid rgba(255, 255, 255, 0.06);
}
/* fine carbon / speed-line texture */
.hero-band::before {
    content: "";
    position: absolute;
    inset: 0;
    background-image: repeating-linear-gradient(116deg,
        rgba(255, 255, 255, 0.035) 0 1px, transparent 1px 11px);
    pointer-events: none;
    z-index: 0;
}
/* glossy top sheen + bottom accent line (3D depth) */
.hero-band::after {
    content: "";
    position: absolute;
    inset: 0;
    background:
        linear-gradient(180deg, rgba(255,255,255,0.10), rgba(255,255,255,0) 42%),
        linear-gradient(90deg, rgba(56,189,248,0) 0%, rgba(96,165,250,0.55) 50%, rgba(56,189,248,0) 100%) bottom / 100% 2px no-repeat;
    pointer-events: none;
    z-index: 0;
}
.hero-band-inner {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 28px 34px;
    position: relative;
    z-index: 1;
}
/* ==========================================================================
   8D — the completion screen
   An 8D is filled in standing up, with a customer on the phone. Everything
   here is about the field being big enough, the control being obvious, and the
   sequence being visible without reading a word.
   ========================================================================== */

/* ---- 3D buttons ---------------------------------------------------------
   One family, one geometry, colour by role: blue saves, green carries forward,
   amber keeps something alive, slate is neutral, red removes. The press is a
   real 2px drop with the shadow collapsing under it, because a button that
   does not move does not feel pressed. */
.btn3d{--c:#2563eb;--c2:#1d4ed8;display:inline-flex;align-items:center;justify-content:center;
  gap:.35rem;border:0;border-radius:11px;padding:.5rem .95rem;font-weight:700;
  font-size:.82rem;line-height:1.1;color:#fff;cursor:pointer;white-space:nowrap;
  background:linear-gradient(180deg,var(--c) 0%,var(--c2) 100%);
  box-shadow:0 3px 0 0 color-mix(in srgb,var(--c2) 72%,#000),
             0 6px 14px -4px color-mix(in srgb,var(--c) 55%,transparent);
  transform:translateY(0);transition:transform .09s ease,box-shadow .09s ease,filter .12s ease;}
.btn3d:hover{filter:brightness(1.07);}
.btn3d:active{transform:translateY(3px);
  box-shadow:0 0 0 0 color-mix(in srgb,var(--c2) 72%,#000),
             0 2px 6px -3px color-mix(in srgb,var(--c) 55%,transparent);}
.btn3d:focus-visible{outline:3px solid rgba(37,99,235,.35);outline-offset:2px;}
.btn3d[disabled]{opacity:.45;cursor:not-allowed;transform:none;}
.btn3d-sm{padding:.34rem .6rem;font-size:.76rem;border-radius:9px;}
.btn3d-xs{padding:.2rem .5rem;font-size:.68rem;border-radius:8px;
  box-shadow:0 2px 0 0 color-mix(in srgb,var(--c2) 72%,#000);}
.btn3d-xs:active{transform:translateY(2px);box-shadow:none;}
.btn3d-blue{--c:#3b82f6;--c2:#2563eb;}
.btn3d-green{--c:#22c55e;--c2:#16a34a;}
.btn3d-amber{--c:#f59e0b;--c2:#d97706;}
.btn3d-red{--c:#f87171;--c2:#dc2626;}
.btn3d-slate{--c:#94a3b8;--c2:#64748b;}
.btn3d-violet{--c:#a78bfa;--c2:#7c3aed;}
@media (prefers-reduced-motion:reduce){.btn3d{transition:none;}.btn3d:active{transform:none;}}
/* ==========================================================================
   Complaints — the module's own surface
   A quality screen is looked at every day, so the visual language is quiet by
   default and only loud where something is wrong. Three devices, no more:
   a soft aurora behind the module head, glass surfaces for the panels that
   float over it, and one accent gradient that every module control shares.
   Everything animated is behind `prefers-reduced-motion`.
   ========================================================================== */
.cmp-shell{--g1:#2563eb;--g2:#7c3aed;--g3:#0ea5e9;position:relative;}
.cmp-shell::before{content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;
  background:
    radial-gradient(58rem 30rem at 8% -12%, rgba(37,99,235,.10), transparent 62%),
    radial-gradient(46rem 26rem at 96% 4%, rgba(124,58,237,.09), transparent 60%),
    radial-gradient(40rem 24rem at 50% 108%, rgba(14,165,233,.07), transparent 60%);}
@media (prefers-reduced-motion:no-preference){
  .cmp-shell::before{animation:auroraDrift 26s ease-in-out infinite alternate;}
  @keyframes auroraDrift{from{transform:translate3d(0,0,0) scale(1);}
    to{transform:translate3d(-1.5%,1.2%,0) scale(1.05);}}}
/* the module head — the one place the gradient is allowed to be visible */
.cmp-head{position:relative;overflow:hidden;border-radius:20px;padding:1.5rem 1.7rem;
  margin-bottom:1rem;color:#e8eefc;
  background:linear-gradient(135deg,#0b1220 0%,#111c34 46%,#16203a 100%);
  box-shadow:0 1px 2px rgba(2,6,23,.5),0 26px 60px -40px rgba(2,6,23,.95);}
.cmp-head::after{content:"";position:absolute;inset:-40% -10% auto auto;width:34rem;height:34rem;
  border-radius:50%;pointer-events:none;
  background:radial-gradient(closest-side,rgba(59,130,246,.35),transparent 70%);
  filter:blur(6px);}
.cmp-head .eyebrow{position:relative;z-index:1;font-size:.64rem;font-weight:800;
  letter-spacing:.2em;text-transform:uppercase;color:#7dd3fc;margin:0 0 .3rem;}
.cmp-head h1{position:relative;z-index:1;margin:0;font-size:1.75rem;font-weight:800;
  letter-spacing:-.024em;}
.cmp-head p{position:relative;z-index:1;margin:.35rem 0 0;max-width:76ch;font-size:.86rem;
  color:#9fb2d4;}
/* glass panels — used for the strips that sit over the aurora */
.glassbar{background:rgba(255,255,255,.72);backdrop-filter:blur(10px) saturate(1.25);
  -webkit-backdrop-filter:blur(10px) saturate(1.25);
  border:1px solid rgba(226,232,240,.9);border-radius:16px;}
/* the register table, read twenty rows at a time */
.cmp-table{border-radius:16px;overflow:hidden;}
.cmp-table thead th{font-size:.62rem;letter-spacing:.08em;text-transform:uppercase;
  color:#64748b;background:linear-gradient(180deg,#f8fafc,#f1f5f9);
  border-bottom:1px solid #e2e8f0;padding-top:.6rem;padding-bottom:.6rem;}
.cmp-table tbody tr{transition:background .12s ease,box-shadow .12s ease;}
.cmp-table tbody tr:hover{background:#f8fbff;
  box-shadow:inset 3px 0 0 0 var(--g1);}
@media (prefers-reduced-motion:reduce){.cmp-table tbody tr{transition:none;}}
.gr-cockpit.is-stuck .gr-weekbox b{font-size:1.05rem;}
.gr-week{display:flex;align-items:center;gap:.5rem;}
/* ---- gates review, the premium pass ------------------------------------- */
.gr-weekbox{display:flex;flex-direction:column;align-items:center;min-width:150px;}
.gr-weekbox b{font-size:1.25rem;font-weight:800;letter-spacing:-.01em;color:#0f172a;
  line-height:1.05;}
.gr-weekbox span{font-size:.68rem;color:#64748b;}
.gr-weekbox em{font-style:normal;font-size:.6rem;font-weight:800;letter-spacing:.05em;
  text-transform:uppercase;color:#166534;background:#dcfce7;border-radius:99px;
  padding:.08rem .4rem;margin-left:.3rem;}
.rd-pop{position:absolute;z-index:1080;width:288px;background:#fff;border:1px solid #e2e8f0;
  border-radius:14px;padding:.7rem .8rem;
  box-shadow:0 4px 0 -2px #e2e8f0,0 22px 46px -20px rgba(15,23,42,.6);}
.rd-pop-h{font-size:.76rem;font-weight:800;color:#0f172a;margin-bottom:.45rem;}
.rd-pop label{display:block;font-size:.62rem;font-weight:700;letter-spacing:.04em;
  text-transform:uppercase;color:#94a3b8;margin-bottom:.4rem;}
.rd-pop select,.rd-pop input{display:block;width:100%;border:1px solid #e2e8f0;
  border-radius:9px;font-size:.78rem;padding:.28rem .45rem;margin-top:.15rem;
  color:#0f172a;text-transform:none;letter-spacing:0;font-weight:500;}
.rd-pop-r{display:grid;grid-template-columns:1fr 1fr;gap:.45rem;}
.rd-pop-a{display:flex;justify-content:flex-end;gap:.35rem;margin-top:.1rem;}
/* ==========================================================================
   SQDCM — five letters, one month
   ========================================================================== */
.sq-bar{display:flex;flex-wrap:wrap;gap:.8rem 1.6rem;align-items:center;
  justify-content:space-between;padding:.7rem 1rem;margin-bottom:1rem;
  position:sticky;top:8px;z-index:60;}
.sq-legend{display:flex;gap:1rem;flex-wrap:wrap;font-size:.7rem;color:#64748b;}
.sq-legend span{display:inline-flex;align-items:center;gap:.35rem;}
.sq-lg{width:12px;height:12px;border-radius:4px;display:inline-block;}
.sq-lg-green{background:linear-gradient(180deg,#4ade80,#16a34a);}
.sq-lg-amber{background:linear-gradient(180deg,#fbbf24,#d97706);}
.sq-lg-red{background:linear-gradient(180deg,#f87171,#dc2626);}
.sq-lg-none{background:var(--bg);border:1px solid var(--line);}
.sq-row{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:.8rem;}
@media (max-width:1250px){.sq-row{grid-template-columns:repeat(2,minmax(0,1fr));}}
@media (max-width:700px){.sq-row{grid-template-columns:1fr;}}
.sq-card{background:#fff;border:1px solid #e8ecf1;border-top:5px solid var(--dim);
  border-radius:16px;padding:.75rem .8rem .9rem;min-width:0;
  box-shadow:0 1px 2px rgba(15,23,42,.04),0 16px 38px -30px rgba(15,23,42,.6);}
.sq-head{display:flex;align-items:center;gap:.45rem;margin-bottom:.55rem;}
.sq-head i{color:var(--dim);font-size:1.05rem;}
.sq-head b{font-weight:800;font-size:.95rem;color:#0f172a;}
.sq-redcount{margin-left:auto;font-size:.62rem;font-weight:800;color:#fff;
  background:linear-gradient(180deg,#f87171,#dc2626);border-radius:99px;
  padding:.12rem .5rem;box-shadow:0 2px 0 0 #991b1b;
  animation:escPulse 1.9s ease-in-out infinite;}
@media (prefers-reduced-motion:reduce){.sq-redcount{animation:none;}}
/* the letter: a 7-column grid of day cells */
/* the SVG glyph: a real letterform lifted off the gradient */
.sq-glyph{display:block;width:100%;max-width:224px;margin:0 auto .3rem;
  filter:drop-shadow(0 7px 6px rgba(0,0,0,.34));}
/* the dial's centre: the letter itself, solid and lifted like the plate */
.sq-center-l{font:800 76px system-ui,-apple-system,sans-serif;fill:#fff;
  text-anchor:middle;filter:drop-shadow(0 4px 3px rgba(0,0,0,.3));}
.sq-plate{fill:none;stroke:#eef1f5;stroke-width:19;
  stroke-linecap:round;stroke-linejoin:round;}
.sq-plate-in{fill:none;stroke:#fbfcfe;stroke-width:15;
  stroke-linecap:round;stroke-linejoin:round;}
/* the day sectors: the ring is sliced, not decorated. The hover brightens the
   slice IN PLACE — the old hover scaled the cell under the cursor, so at the
   cell's edge the grown cell slid out from under the mouse, un-hovered,
   shrank back, re-hovered: that was the flashing. Nothing moves now. */
.sqv-day path{fill:#fdfefe;stroke:rgba(15,23,42,.10);stroke-width:.6;
  transition:filter .12s ease;}
.sqv-day text{font:800 6.4px ui-monospace,Menlo,monospace;fill:#64748b;
  text-anchor:middle;pointer-events:none;}
.sqv-day.is-live{cursor:pointer;}
.sqv-day.is-live:hover path{filter:brightness(1.1) saturate(1.15);
  stroke:#fff;stroke-width:1.2;}
.sqv-day.is-future path{fill:rgba(255,255,255,.45);stroke:rgba(255,255,255,.25);}
.sqv-day.is-future text{opacity:.5;}
.sqv-day.st-green path{fill:url(#sqGreen);stroke:rgba(255,255,255,.85);stroke-width:.8;}
.sqv-day.st-amber path{fill:url(#sqAmber);stroke:rgba(255,255,255,.85);stroke-width:.8;}
.sqv-day.st-red path{fill:url(#sqRed);stroke:rgba(255,255,255,.85);stroke-width:.8;}
.sqv-day.st-green text,.sqv-day.st-amber text,.sqv-day.st-red text{fill:#fff;}
.sqv-day.is-today path{stroke:#0f172a;stroke-width:1.5;}
@media (prefers-reduced-motion:reduce){.sqv-day path{transition:none;}}
.sq-cell{aspect-ratio:1;border-radius:4px;}
.sq-shape{background:color-mix(in srgb,var(--dim) 10%,#f1f5f9);}
.sq-day{aspect-ratio:1;border-radius:4px;border:0;padding:0;cursor:pointer;
  font-size:.56rem;font-weight:800;line-height:1;color:#64748b;
  background:#eef2f7;box-shadow:inset 0 -1.5px 0 rgba(15,23,42,.08);
  transition:transform .1s ease,box-shadow .1s ease;}
.sq-day:hover:not([disabled]){transform:scale(1.28);z-index:2;position:relative;
  box-shadow:0 3px 8px -2px rgba(15,23,42,.5);}
.sq-day[disabled]{cursor:default;}
.sq-day.is-future{opacity:.4;}
.sq-day.st-green{background:linear-gradient(180deg,#4ade80,#16a34a);color:#fff;
  box-shadow:inset 0 -1.5px 0 #15803d;}
.sq-day.st-amber{background:linear-gradient(180deg,#fbbf24,#d97706);color:#fff;
  box-shadow:inset 0 -1.5px 0 #b45309;}
.sq-day.st-red{background:linear-gradient(180deg,#f87171,#dc2626);color:#fff;
  box-shadow:inset 0 -1.5px 0 #991b1b;}
.sq-day.is-today{outline:2px solid #0f172a;outline-offset:1px;}
@media (prefers-reduced-motion:reduce){.sq-day{transition:none;}
  .sq-day:hover:not([disabled]){transform:none;}}
.sq-means{font-size:.62rem;color:#94a3b8;line-height:1.35;margin:0 0 .5rem;
  text-align:center;}
.sq-uncovered{display:flex;gap:.4rem;align-items:flex-start;font-size:.66rem;
  color:#991b1b;background:linear-gradient(180deg,#fef2f2,#fee2e2);
  border:1px solid #fecaca;border-radius:10px;padding:.35rem .55rem;
  margin-bottom:.45rem;}
.sq-uncovered i{color:#dc2626;}
.sq-say{display:flex;gap:.4rem;align-items:flex-start;font-size:.64rem;
  color:#92400e;background:#fffbeb;border:1px solid #fde68a;border-radius:10px;
  padding:.32rem .55rem;margin-bottom:.45rem;}
.sq-say i{color:#d97706;}
/* the KPI links under the letter */
.sq-kpis{border-top:1px dashed #e8ecf1;padding-top:.45rem;margin-bottom:.5rem;
  display:flex;flex-direction:column;gap:.3rem;}
.sq-kpi{display:flex;align-items:center;gap:.4rem;font-size:.7rem;
  border-left:3px solid #cbd5e1;padding-left:.45rem;}
.sq-kpi.is-hit{border-left-color:#16a34a;}
.sq-kpi.is-miss{border-left-color:#dc2626;background:#fef7f7;}
.sq-kpi-n{color:#475569;min-width:0;flex:1 1 auto;}
.sq-kpi-v{font-weight:800;color:#0f172a;white-space:nowrap;
  font-variant-numeric:tabular-nums;}
.sq-kpi-v em{font-style:normal;font-weight:400;color:#94a3b8;font-size:.62rem;}
.sq-kpi-x{border:0;background:none;color:#cbd5e1;font-size:.85rem;cursor:pointer;
  line-height:1;padding:0 .1rem;}
.sq-kpi-x:hover{color:#dc2626;}
.sq-kpi-day{flex:0 0 auto;}
.sq-kpi-day input{width:62px;border:1px solid #e2e8f0;border-radius:8px;
  font-size:.68rem;padding:.16rem .35rem;text-align:right;
  font-variant-numeric:tabular-nums;background:#fffdf5;}
.sq-kpi-day input:focus{outline:2px solid #d97706;outline-offset:0;background:#fff;}
.sq-kpi-today{font-size:.64rem;font-weight:700;color:#b45309;white-space:nowrap;}
.sq-chart{border-top:1px dashed #e8ecf1;padding-top:.45rem;margin-bottom:.5rem;
  height:120px;}
.sq-kpi-add{display:flex;gap:.3rem;margin-top:.1rem;}
.sq-kpi-add select{flex:1 1 auto;min-width:0;border:1px solid #e2e8f0;border-radius:8px;
  font-size:.68rem;padding:.2rem .35rem;}
.sq-empty{font-size:.68rem;color:#cbd5e1;font-style:italic;margin:0;}
/* the action plan */
.sq-actions{border-top:1px dashed #e8ecf1;padding-top:.45rem;}
.sq-actions-h{display:flex;justify-content:space-between;font-size:.64rem;
  font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:#94a3b8;
  margin-bottom:.35rem;}
.sq-actions-h span{font-weight:400;letter-spacing:0;text-transform:none;}
.sq-action{display:flex;gap:.4rem;align-items:flex-start;border-left:3px solid var(--dim);
  padding:.25rem 0 .25rem .45rem;margin-bottom:.3rem;background:#fbfcfd;border-radius:0 8px 8px 0;}
.sq-action.is-late{border-left-color:#dc2626;background:#fef7f7;}
.sq-action-b{min-width:0;flex:1 1 auto;font-size:.72rem;}
.sq-action-b b{display:block;color:#0f172a;}
.sq-action-b span{display:block;color:#64748b;font-size:.66rem;}
.sq-corr{color:#166534 !important;}
.sq-action-b em{display:block;font-style:normal;color:#94a3b8;font-size:.6rem;}
.sq-action-a{display:flex;gap:.25rem;align-items:center;}
.sq-action-a select{border:1px solid #e2e8f0;border-radius:7px;font-size:.64rem;
  padding:.12rem .25rem;max-width:90px;}
.sq-add summary{font-size:.7rem;font-weight:700;color:#64748b;cursor:pointer;}
.sq-add form{display:flex;flex-direction:column;gap:.3rem;margin-top:.35rem;}
.sq-add input,.sq-add textarea,.sq-add select{border:1px solid #e2e8f0;border-radius:8px;
  font-size:.7rem;padding:.28rem .45rem;width:100%;}
.sq-add-r{display:grid;grid-template-columns:1fr 1fr 1fr;gap:.3rem;}
/* the two dates named apart: "for day" answers a red day, "due" is a deadline */
.sq-add-dates{grid-template-columns:1fr 1fr;}
.sq-add-dates label{display:flex;flex-direction:column;gap:.1rem;margin:0;}
.sq-add-dates label span{font-size:.56rem;font-weight:700;letter-spacing:.04em;
  text-transform:uppercase;color:#94a3b8;}
.sq-pop-b{display:flex;gap:.35rem;margin-bottom:.55rem;}
/* ---- SQDCM header: the Projects hero band, with the blueprint car driving */
.sq-head{margin-bottom:1rem;min-height:128px;
  /* the same band as the Projects hero MINUS its static car watermark —
     the car here is a child element, so it can drive */
  background:
    radial-gradient(120% 160% at 92% -20%, rgba(56,189,248,0.30) 0%, rgba(56,189,248,0) 55%),
    linear-gradient(118deg, #0a1020 0%, #122a52 44%, #1b46b0 78%, #2563eb 100%);}
.sq-head .hero-band-inner{padding:24px 34px;}
.sq-title{color:#fff;margin:0;font-weight:800;letter-spacing:.1em;}
.sq-blueprint{position:absolute;top:-10px;bottom:-10px;width:660px;left:0;
  z-index:0;pointer-events:none;
  background:url("../img/hero-automotive.3133761112b9.svg") center / auto 100% no-repeat;
  animation:sqBlueprint 26s linear infinite;}
@media (prefers-reduced-motion: reduce){
  /* parked exactly where the Projects hero keeps it */
  .sq-blueprint{animation:none;left:auto;right:-6px;}
}
/* ---- SQDCM, the picture pass: gradients, glass, donuts ------------------ */
/* each letter's own world, matched to the classic boards */
.sq-safety{--g1:#2dd4bf;--g2:#0d9488;}
.sq-quality{--g1:#3b82f6;--g2:#1e3a8a;}
.sq-delivery{--g1:#38bdf8;--g2:#0369a1;}
.sq-cost{--g1:#fbbf24;--g2:#d97706;}
.sq-morale{--g1:#6366f1;--g2:#312e81;}
.sq-card{border-top:0;padding:.55rem .6rem .9rem;}
.sq-hero{position:relative;overflow:hidden;border-radius:13px;
  background:linear-gradient(160deg,var(--g1),var(--g2));
  padding:.6rem .65rem .55rem;margin-bottom:.55rem;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.35),
             0 4px 0 -1px color-mix(in srgb,var(--g2) 80%,#000),
             0 16px 30px -18px color-mix(in srgb,var(--g2) 85%,transparent);
  transition:transform .16s ease,box-shadow .16s ease;}
.sq-card:hover .sq-hero{transform:translateY(-2px);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.35),
             0 6px 0 -1px color-mix(in srgb,var(--g2) 80%,#000),
             0 24px 44px -20px color-mix(in srgb,var(--g2) 95%,transparent);}
@media (prefers-reduced-motion:reduce){.sq-hero{transition:none;}
  .sq-card:hover .sq-hero{transform:none;}}
.sq-hero-top{display:flex;align-items:center;justify-content:space-between;
  margin-bottom:.35rem;}
.sq-hero-l{font-weight:800;font-size:.9rem;color:#fff;
  text-shadow:0 1px 2px rgba(0,0,0,.25);}
.sq-mark{position:absolute;right:-14px;bottom:-18px;font-size:6.5rem;
  color:rgba(255,255,255,.12);pointer-events:none;transform:rotate(-8deg);}
.sq-hero-c{display:flex;justify-content:space-around;margin-top:.45rem;
  border-top:1px solid rgba(255,255,255,.25);padding-top:.35rem;}
.sq-hero-c span{display:flex;flex-direction:column;align-items:center;
  font-size:.56rem;color:rgba(255,255,255,.8);line-height:1.2;}
.sq-hero-c b{font-size:.85rem;font-weight:800;color:#fff;
  font-variant-numeric:tabular-nums;}
/* the letter on the gradient: unmarked days are the white plate */
.sq-hero .sq-letter{margin-bottom:0;position:relative;z-index:1;}
/* structure cells match the unmarked days, so the whole stroke reads as ONE
   solid white plate — the silhouette is the letter, the colours sit on it */
.sq-hero .sq-shape{background:linear-gradient(180deg,#fdfefe,#e6ebf1);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.9),inset 0 -2px 0 rgba(15,23,42,.2);}
/* chiseled cells: a bright top lip and a dark sole make each cell a small
   extruded block, and the drop-shadow on the grid lifts the whole letterform
   off the gradient like the vinyl letters on a real board */
.sq-hero .sq-day{ /* light-only: an unmarked day on the SQDCM hero, which is coloured in both themes */background:linear-gradient(180deg,#ffffff,#e9edf3);color:#475569;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.9),inset 0 -2px 0 rgba(15,23,42,.22);}
.sq-hero .sq-day.is-future{opacity:.55;background:rgba(255,255,255,.55);}
.sq-hero .sq-day.st-green{background:linear-gradient(180deg,#4ade80,#16a34a);color:#fff;
  box-shadow:inset 0 -1.5px 0 #15803d,0 0 0 1px rgba(255,255,255,.5);}
.sq-hero .sq-day.st-amber{background:linear-gradient(180deg,#fbbf24,#d97706);color:#fff;
  box-shadow:inset 0 -1.5px 0 #b45309,0 0 0 1px rgba(255,255,255,.5);}
.sq-hero .sq-day.st-red{background:linear-gradient(180deg,#f87171,#dc2626);color:#fff;
  box-shadow:inset 0 -1.5px 0 #991b1b,0 0 0 1px rgba(255,255,255,.6);}
.sq-hero .sq-day.is-today{outline:2px solid #fff;outline-offset:1px;}
/* the donut: target attainment as a conic ring, hit green / miss red */
.sq-donut{--p:0;position:relative;flex:0 0 auto;width:34px;height:34px;border-radius:50%;
  display:grid;place-items:center;
  background:conic-gradient(#16a34a calc(var(--p) * 1%), #e8ecf1 0);
  box-shadow:0 2px 0 0 #cbd5e1;}
.sq-kpi.is-miss .sq-donut{background:conic-gradient(#dc2626 calc(var(--p) * 1%), #fee2e2 0);}
.sq-donut::before{content:"";position:absolute;inset:4px;border-radius:50%;background:var(--card);}
.sq-donut b{position:relative;font-size:.56rem;font-weight:800;color:var(--ink);
  font-variant-numeric:tabular-nums;}
.sq-donut b i{font-style:normal;font-size:.44rem;color:#94a3b8;}
.sq-donut.is-na{background:#eef2f7;}
.sq-kpi{border-left:0;padding-left:0;gap:.5rem;}
.sq-kpi.is-miss{background:transparent;}
.sq-kpi.is-miss .sq-kpi-v{color:#dc2626;}
.sq-kpi.is-hit .sq-kpi-v{color:#166534;}
/* ---- SQDCM actions as SmartArt chevrons: ISSUE ▼ ACTION ▼ WHO -----------
   Vertical on purpose: the letter cards are one column of five, ~280px wide,
   and a horizontal train in that width is three slivers. The flow arrow points
   down — the direction the eye already travels. */
.sqa{display:flex;flex-direction:column;margin-bottom:.5rem;
  filter:drop-shadow(0 3px 2px rgba(15,23,42,.22));
  transition:transform .14s ease,filter .14s ease;}
.sqa:hover{transform:translateY(-2px);
  filter:drop-shadow(0 6px 6px rgba(15,23,42,.3));}
@media (prefers-reduced-motion:reduce){.sqa{transition:none;}
  .sqa:hover{transform:none;}}
.sqa-seg{min-width:0;padding:.4rem .6rem;display:flex;
  flex-direction:column;justify-content:center;}
.sqa-seg i{font-style:normal;font-size:.52rem;font-weight:800;letter-spacing:.09em;
  text-transform:uppercase;opacity:.75;}
.sqa-seg b{font-size:.72rem;font-weight:700;line-height:1.25;}
.sqa-seg span{font-size:.62rem;opacity:.85;}
/* the day chip on the issue segment — which red this action answers */
.sqa-day{display:inline-flex;align-items:center;gap:.22rem;align-self:flex-start;
  font-size:.58rem;font-weight:800;letter-spacing:.03em;text-transform:uppercase;
  background:rgba(255,255,255,.22);border:1px solid rgba(255,255,255,.4);
  border-radius:99px;padding:.06rem .45rem;margin-top:.15rem;opacity:1;}
.sqa-chiprow{display:flex;gap:.25rem;align-items:center;}
.sqa-chiprow .sqa-day{margin-top:.15rem;}
/* ---- the corrective-actions overview at the foot of each letter --------- */
/* the OEM-board strip: open actions counted by kind — a major and eight
   observations are different mornings, and one total hides that */
.sq-cat{display:inline-flex;align-items:center;font-size:.56rem;font-weight:800;
  letter-spacing:.05em;text-transform:uppercase;color:#fff;border-radius:99px;
  padding:.1rem .55rem;line-height:1.25;}
.sqa-day.cat-major,.sqa-day.cat-minor,.sqa-day.cat-improvement,
.sqa-day.cat-observation{border-color:transparent;}
.sq-ov{margin-top:.6rem;border:1px solid #e2e8f0;border-radius:12px;
  background:linear-gradient(180deg,#fff,#f8fafc);
  box-shadow:0 2px 0 -1px #e2e8f0,0 10px 18px -14px rgba(15,23,42,.25);
  padding:.5rem .55rem .45rem;}
.sq-ov-h{font-size:.68rem;font-weight:800;color:#334155;margin-bottom:.4rem;}
.sq-ov-grid{display:grid;grid-template-columns:1fr 1fr;gap:.4rem .5rem;}
.sq-ov-stat{display:flex;flex-direction:column;align-items:center;gap:.15rem;}
.sq-ov-stat b{font-size:1.05rem;line-height:1;color:#0f172a;
  font-variant-numeric:tabular-nums;}
.sq-ov-new{display:flex;align-items:center;gap:.35rem;margin-top:.45rem;
  padding:.3rem .4rem;border-radius:9px;background:#f1f5f9;
  font-size:.62rem;color:#475569;min-width:0;}
.sq-ov-new em{font-style:normal;white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis;flex:1;min-width:0;}
.sq-ov-id{font-weight:800;color:#334155;}
.sq-ov-age{color:#94a3b8;white-space:nowrap;}
.sq-ov-f{display:flex;align-items:center;justify-content:space-between;
  margin-top:.45rem;}
.sq-ov-f a{font-size:.66rem;font-weight:700;color:#2563eb;text-decoration:none;}
.sq-ov-f a:hover{text-decoration:underline;}
.sq-ov-plus{width:26px;height:26px;border-radius:50%;border:0;color:#fff;
  font-size:1rem;font-weight:800;line-height:1;display:inline-flex;
  align-items:center;justify-content:center;cursor:pointer;
  background:linear-gradient(180deg,#60a5fa,#2563eb);
  box-shadow:0 2px 0 #1e40af,0 8px 14px -8px rgba(37,99,235,.6);
  transition:transform .12s ease,box-shadow .12s ease;}
.sq-ov-plus:hover{transform:translateY(-1px);
  box-shadow:0 3px 0 #1e40af,0 10px 16px -8px rgba(37,99,235,.65);}
.sq-ov-plus:active{transform:translateY(1px);box-shadow:0 1px 0 #1e40af;}
/* ---- the actions register (the "view all" behind the overview) ---------- */
.sqr-filter{display:flex;gap:.35rem;flex-wrap:wrap;}
.sqr-letter{display:inline-flex;align-items:center;font-size:.64rem;
  font-weight:800;color:#fff;border-radius:8px;padding:.16rem .5rem;
  background:var(--dim,#64748b);white-space:nowrap;}
.sqr-table td{font-size:.74rem;}
.sqr-issue b{display:block;font-size:.76rem;}
.sqr-issue span{display:block;font-size:.66rem;color:#64748b;}
.sqr-fix{max-width:260px;}
.sqr-closed td{opacity:.55;}
.sqr-closed .sq-cat,.sqr-closed .sqr-letter{filter:grayscale(.4);}
.sqr-late .sqr-issue b{color:#b91c1c;}
.sqr-status{display:flex;gap:.25rem;align-items:center;}
.sqr-status select{border:1px solid #e2e8f0;border-radius:7px;font-size:.66rem;
  padding:.14rem .3rem;}
.sqr-table td.is-burn{color:#dc2626;font-weight:800;}
.sqa-issue{ /* light-only: the lit top face of a 3-D icon — a coloured object, not a surface */color:#fff;border-radius:10px 10px 0 0;
  background:linear-gradient(180deg,color-mix(in srgb,var(--dim) 86%,#fff),var(--dim));
  clip-path:polygon(0 0, 100% 0, 100% calc(100% - 7px), 50% 100%, 0 calc(100% - 7px));
  padding-bottom:.75rem;}
.sqa-fix{color:#0f172a;background:linear-gradient(180deg,#fff,#eef2f7);
  clip-path:polygon(0 0, 50% 7px, 100% 0, 100% calc(100% - 7px), 50% 100%, 0 calc(100% - 7px));
  margin-top:-5px;padding-top:.7rem;padding-bottom:.75rem;}
.sqa-fix i{color:#94a3b8;}
.sqa-fix span{color:#64748b;}
.sqa-who{flex-direction:row;align-items:center;gap:.4rem;flex-wrap:wrap;
  background:linear-gradient(180deg,#fbfcfe,#e9edf3);border-radius:0 0 10px 10px;
  clip-path:polygon(0 0, 50% 7px, 100% 0, 100% 100%, 0 100%);
  margin-top:-5px;padding:.75rem .55rem .4rem;}
.sqa.is-late .sqa-issue{background:linear-gradient(180deg,#f87171,#dc2626);
  animation:m4Burn 1.6s ease-in-out infinite;}
@media (prefers-reduced-motion:reduce){.sqa.is-late .sqa-issue{animation:none;}}
.sqa-av{display:grid;place-items:center;width:26px;height:26px;border-radius:50%;
  background:linear-gradient(180deg,#818cf8,#4f46e5);color:#fff;font-size:.7rem;
  font-weight:800;box-shadow:0 2px 0 0 #3730a3;flex:0 0 auto;}
.sqa-av.is-nobody{background:linear-gradient(180deg,#cbd5e1,#94a3b8);
  box-shadow:0 2px 0 0 #64748b;}
.sqa-who-b{display:flex;flex-direction:column;min-width:0;}
.sqa-who-b b{font-size:.66rem;font-weight:800;color:#0f172a;white-space:nowrap;}
.sqa-who-b span{font-size:.6rem;color:#94a3b8;}
.sqa-who-b span.is-burn{color:#dc2626;font-weight:800;}
.sqa-who select{border:1px solid #e2e8f0;border-radius:7px;font-size:.62rem;
  padding:.12rem .2rem;max-width:86px;}
.sqa.is-late .sqa-issue{background:linear-gradient(180deg,#f87171,#dc2626);
  animation:m4Burn 1.6s ease-in-out infinite;}
@media (prefers-reduced-motion:reduce){.sqa.is-late .sqa-issue{animation:none;}}

/* --- Midnight: the ported staging surfaces re-pointed at the design tokens.
   Staging had no dark theme, so its module CSS hard-codes #fff / #f8fafc / slate
   text. Everything else above is left exactly as staging wrote it; only the
   surfaces that would glow white in Midnight are re-declared here. --- */
:root[data-theme="midnight"] .sq-card,
:root[data-theme="midnight"] .cmp-shell .card,
:root[data-theme="midnight"] .glassbar,
:root[data-theme="midnight"] .rd-pop,
:root[data-theme="midnight"] .sqr-table,
:root[data-theme="midnight"] .cmp-table{
  background:var(--card);border-color:var(--line);color:var(--ink);
}
:root[data-theme="midnight"] .sq-kpi,
:root[data-theme="midnight"] .sq-ov,
:root[data-theme="midnight"] .sqa,
:root[data-theme="midnight"] .sq-add details,
:root[data-theme="midnight"] .sq-actions{
  background:color-mix(in srgb,var(--card) 82%,#000);border-color:var(--line);
}
:root[data-theme="midnight"] .sqa-seg,
:root[data-theme="midnight"] .sq-ov-stat,
:root[data-theme="midnight"] .sq-empty{color:var(--ink);}
:root[data-theme="midnight"] .sq-means,
:root[data-theme="midnight"] .sq-kpi-n,
:root[data-theme="midnight"] .sq-kpi-v,
:root[data-theme="midnight"] .sq-ov-age,
:root[data-theme="midnight"] .sqa-seg i{color:var(--muted-2);}
:root[data-theme="midnight"] .sq-add input,
:root[data-theme="midnight"] .sq-add textarea,
:root[data-theme="midnight"] .sq-add select,
:root[data-theme="midnight"] .sq-kpi-day input,
:root[data-theme="midnight"] .rd-pop input,
:root[data-theme="midnight"] .sqa-who select{
  background:var(--bg);color:var(--ink);border-color:var(--line);
}
:root[data-theme="midnight"] .sqv-day.st-none path{fill:color-mix(in srgb,var(--line) 70%,transparent);}
:root[data-theme="midnight"] .sqv-day text{fill:var(--muted-2);}

/* ==========================================================================
   Shared premium hero band (templates/components/hero.html)
   Ported 1:1 from the staging app. Deep navy in BOTH themes, deliberately —
   the same call the navbar and .ch-hero make: a band that restyles itself in
   Midnight stops reading as the top of the page.
   ========================================================================== */
.hero-band {
  border-radius: 22px;
  /* automotive blueprint watermark (right) over a deep premium gradient */
  background:
    url("../img/hero-automotive.3133761112b9.svg") right -6px bottom -10px / auto 168% no-repeat,
    radial-gradient(120% 160% at 92% -20%, rgba(56,189,248,.30) 0%, rgba(56,189,248,0) 55%),
    linear-gradient(118deg, #0a1020 0%, #122a52 44%, #1b46b0 78%, #2563eb 100%);
  color: #fff;
  overflow: hidden;
  position: relative;
  box-shadow: 0 18px 46px rgba(8,17,45,.34), inset 0 1px 0 rgba(255,255,255,.10);
  border: 1px solid rgba(255,255,255,.06);
}
/* fine carbon / speed-line texture */
.hero-band::before {
  content: ""; position: absolute; inset: 0; pointer-events: none; z-index: 0;
  background-image: repeating-linear-gradient(116deg,
    rgba(255,255,255,.035) 0 1px, transparent 1px 11px);
}
/* glossy top sheen + bottom accent line (3D depth) */
.hero-band::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; z-index: 0;
  background:
    linear-gradient(180deg, rgba(255,255,255,.10), rgba(255,255,255,0) 42%),
    linear-gradient(90deg, rgba(56,189,248,0) 0%, rgba(96,165,250,.55) 50%,
                    rgba(56,189,248,0) 100%) bottom / 100% 2px no-repeat;
}
.hero-band-inner {
  display: flex; justify-content: space-between; align-items: center;
  gap: 1rem; flex-wrap: wrap;
  padding: 28px 34px; position: relative; z-index: 1;
}
.hero-eyebrow {
  font-size: .72rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 2px; color: #93c5fd; margin-bottom: 6px;
  text-shadow: 0 1px 6px rgba(37,99,235,.45);
}
.hero-title {
  font-size: 2rem; font-weight: 800; margin: 0 0 7px;
  letter-spacing: -.2px; text-shadow: 0 2px 10px rgba(0,0,0,.35);
}
.hero-sub { font-size: .95rem; color: #d4def0; }
.btn-hero { /* light-only: a white button on the navy hero, which is navy in both themes */
  border-radius: 13px; font-weight: 700; padding: 11px 20px;
  background: linear-gradient(180deg, #ffffff, #eef2fb);
  border: 1px solid rgba(255,255,255,.8); color: #15294f;
  box-shadow: 0 8px 20px rgba(0,0,0,.24), inset 0 1px 0 rgba(255,255,255,.9);
  transition: transform .14s ease, box-shadow .18s ease;
}
.btn-hero:hover {
  transform: translateY(-2px); color: #0f2557;
  box-shadow: 0 12px 26px rgba(0,0,0,.3), inset 0 1px 0 rgba(255,255,255,.9);
}
@media (prefers-reduced-motion: reduce) {
  .btn-hero, .btn-hero:hover { transition: none; transform: none; }
}
@media (max-width: 575.98px) {
  .hero-band-inner { padding: 20px 22px; }
  .hero-title { font-size: 1.5rem; }
}


/* ==========================================================================
   The weekly gates review (templates/meetings/gates_review.html)
   Ported from the staging app. Neutral surfaces are tokenised so Midnight
   retints them; the red / amber / green stay literal, because they mean
   something and read on either ground.
   ========================================================================== */
/* ==========================================================================
   The weekly gates review — every project, one screen, one hour
   ========================================================================== */
/* The cockpit stays under your thumb while the meeting scrolls the walk:
   the clock and the walked-bar are the two things a chair glances at between
   sentences, and losing them at project four defeats them. Sticky, not fixed —
   it still scrolls away above the hero when you go back up. */
.gr-cockpit{display:flex;flex-wrap:wrap;gap:.8rem 1.6rem;align-items:center;
  justify-content:space-between;padding:.7rem 1rem;margin-bottom:1rem;
  position:sticky;top:8px;z-index:60;
  transition:box-shadow .2s ease,padding .2s ease;}
.gr-cockpit.is-stuck{padding:.45rem 1rem;
  box-shadow:0 4px 0 -2px rgba(226,232,240,.9),0 18px 38px -20px rgba(15,23,42,.55);}
.gr-cockpit.is-stuck .gr-weekbox b{font-size:1.05rem;}
.gr-cockpit.is-stuck .gr-clock-t{font-size:1.2rem;}
@media (prefers-reduced-motion:reduce){.gr-cockpit{transition:none;}}
.gr-week{display:flex;align-items:center;gap:.5rem;}
.gr-label{font-weight:800;font-size:.95rem;color:var(--ink);}
.gr-label em{font-style:normal;font-size:.66rem;font-weight:800;letter-spacing:.05em;
  text-transform:uppercase;color:#166534;background:#dcfce7;border-radius:99px;
  padding:.12rem .5rem;margin-left:.4rem;}
.gr-counts{display:flex;gap:.9rem;flex-wrap:wrap;}
.gr-card{display:grid;grid-template-columns:minmax(0,5fr) minmax(0,4fr);gap:1rem;
  background:var(--card);border:1px solid #e8ecf1;border-left:5px solid #cbd5e1;
  border-radius:16px;padding:.85rem 1rem;margin-bottom:.7rem;
  box-shadow:0 1px 2px rgba(15,23,42,.04),0 14px 34px -28px rgba(15,23,42,.5);}
.gr-card.is-red{border-left-color:#dc2626;background:linear-gradient(180deg,#fff,#fef7f7);}
.gr-card.is-amber{border-left-color:#f59e0b;}
.gr-card.is-green{border-left-color:#16a34a;}
@media (max-width:980px){.gr-card{grid-template-columns:1fr;}}
.gr-head{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap;}
.gr-name{font-weight:800;font-size:1.02rem;color:var(--ink);text-decoration:none;}
.gr-name:hover{color:#1d4ed8;text-decoration:underline;}
.gr-sub{display:flex;align-items:center;gap:.55rem;flex-wrap:wrap;
  font-size:.72rem;color:var(--muted-2,#94a3b8);margin-bottom:.25rem;}
/* the leader rides the same line as the customer — a face, not a field */
.gr-lead{display:inline-flex;align-items:center;gap:.3rem;font-weight:700;color:var(--ink);}
.gr-lead i{display:grid;place-items:center;width:17px;height:17px;border-radius:50%;
  font-style:normal;font-size:.58rem;font-weight:800;color:#fff;
  background:linear-gradient(180deg,#818cf8,#4f46e5);box-shadow:0 1.5px 0 0 #3730a3;}
.gr-rag{font-size:.62rem;font-weight:800;letter-spacing:.06em;text-transform:uppercase;
  border-radius:99px;padding:.14rem .5rem;color:#fff;}
/* Blocked and at-risk are the two flags the meeting exists to catch, so they
   move: red blinks hard (it is the one that cannot wait), amber breathes a
   slower ring (urgent, but not the same urgency — if both blinked the same,
   neither would mean anything). The ghost badge from last week never moves:
   it is memory, not an alarm. `prefers-reduced-motion` keeps the colour and
   drops the motion, same rule as everywhere else in the app. */
.gr-rag-red{background:linear-gradient(180deg,#f87171,#dc2626);box-shadow:0 2px 0 0 #991b1b;
  animation:ragBlink 1s steps(2,end) infinite;}
.gr-rag-amber{background:linear-gradient(180deg,#fbbf24,#d97706);box-shadow:0 2px 0 0 #b45309;
  animation:ragBreathe 1.9s ease-in-out infinite;}
@media (prefers-reduced-motion:reduce){
  .gr-rag-red,.gr-rag-amber{animation:none;}}
.gr-rag-green{background:linear-gradient(180deg,#4ade80,#16a34a);box-shadow:0 2px 0 0 #15803d;}
.gr-rag-ghost{background:var(--bg);color:var(--muted-2,#94a3b8);}
.gr-facts{display:flex;flex-wrap:wrap;gap:.35rem .9rem;margin-bottom:.3rem;}
.gr-gate-released{color:#16a34a;}
.gr-pctbar{display:inline-block;width:52px;height:5px;border-radius:5px;background:#eef2f7;
  overflow:hidden;vertical-align:middle;margin-left:.3rem;}
.gr-pctbar span{display:block;height:100%;border-radius:5px;
  background:linear-gradient(90deg,#2563eb,#16a34a);}
.gr-miles{display:flex;gap:.35rem;flex-wrap:wrap;}
.gr-mile{font-size:.62rem;font-weight:800;border-radius:8px;padding:.14rem .45rem;
  background:#eef2f7;color:var(--muted-2,#64748b);}
.gr-mile.is-met{background:#dcfce7;color:#166534;}
.gr-mile.is-missed{background:#fee2e2;color:#991b1b;}
.gr-mile.is-late{background:#ffedd5;color:#9a3412;}
.gr-notes{min-width:0;border-left:1px dashed #e8ecf1;padding-left:1rem;
  display:flex;flex-direction:column;gap:.4rem;}
@media (max-width:980px){.gr-notes{border-left:0;padding-left:0;border-top:1px dashed #e8ecf1;
  padding-top:.6rem;}}
.gr-last{font-size:.7rem;color:var(--muted-2,#94a3b8);background:var(--bg);border-radius:9px;
  padding:.35rem .55rem;}
.gr-last span{color:var(--muted-2,#64748b);}
.gr-note{display:flex;align-items:flex-start;gap:.45rem;}
.gr-dot{flex:0 0 auto;width:9px;height:9px;border-radius:50%;margin-top:.42rem;display:inline-block;}
.gr-dot-red{background:#dc2626;}
.gr-note-b{min-width:0;flex:1 1 auto;}
.gr-note-b p{margin:0;font-size:.8rem;color:var(--ink);}
.gr-flagonly{color:var(--muted-2,#94a3b8) !important;font-style:italic;}
.gr-note-b em{font-style:normal;font-size:.62rem;color:#cbd5e1;}
.gr-note form{opacity:0;transition:opacity .14s ease;}
.gr-note:hover form,.gr-note:focus-within form{opacity:1;}
.gr-empty{font-size:.74rem;color:#cbd5e1;font-style:italic;margin:0;}
.gr-add{margin-top:auto;padding-top:.3rem;}
.gr-add textarea{width:100%;border:1px solid var(--line);border-radius:10px;font-size:.78rem;
  padding:.4rem .55rem;resize:none;overflow:hidden;min-height:36px;}
.gr-add textarea:focus{outline:2px solid #2563eb;outline-offset:0;}
.gr-add-a{display:flex;gap:.3rem;margin-top:.3rem;justify-content:flex-end;}
/* ---- gates review, the premium pass ------------------------------------- */
.gr-weekbox{display:flex;flex-direction:column;align-items:center;min-width:150px;}
.gr-weekbox b{font-size:1.25rem;font-weight:800;letter-spacing:-.01em;color:var(--ink);
  line-height:1.05;}
.gr-weekbox span{font-size:.68rem;color:var(--muted-2,#64748b);}
.gr-weekbox em{font-style:normal;font-size:.6rem;font-weight:800;letter-spacing:.05em;
  text-transform:uppercase;color:#166534;background:#dcfce7;border-radius:99px;
  padding:.08rem .4rem;margin-left:.3rem;}
.gr-clock{display:flex;flex-direction:column;align-items:center;border:1px solid var(--line);
  border-radius:14px;padding:.4rem 1.1rem;background:var(--card);
  box-shadow:0 2px 0 0 #e2e8f0,0 10px 22px -18px rgba(15,23,42,.6);}
.gr-clock-t{font-size:1.5rem;font-weight:800;font-variant-numeric:tabular-nums;
  letter-spacing:.02em;color:var(--ink);line-height:1.1;}
.gr-clock-s{font-size:.62rem;color:var(--muted-2,#94a3b8);}
.gr-clock.is-warm{border-color:#fcd34d;background:#fffbeb;}
.gr-clock.is-warm .gr-clock-t{color:#b45309;}
.gr-clock.is-over{border-color:#fca5a5;background:#fef2f2;}
.gr-clock.is-over .gr-clock-t{color:#dc2626;animation:clockPulse 1.4s ease-in-out infinite;}
@media (prefers-reduced-motion:reduce){.gr-clock.is-over .gr-clock-t{animation:none;}}
.gr-walk{flex:1 1 240px;max-width:360px;}
.gr-walk-h{display:flex;justify-content:space-between;font-size:.68rem;font-weight:700;
  color:#475569;margin-bottom:.25rem;}
.gr-walk-n{color:var(--muted-2,#94a3b8);font-weight:400;}
.gr-walk-n i{display:inline-block;width:8px;height:8px;border-radius:50%;vertical-align:baseline;}
.gr-walkbar{height:8px;border-radius:8px;background:#eef2f7;overflow:hidden;}
.gr-walkbar span{display:block;height:100%;border-radius:8px;
  background:linear-gradient(90deg,#2563eb,#16a34a);
  transition:width .6s cubic-bezier(.4,0,.2,1);}
@media (prefers-reduced-motion:reduce){.gr-walkbar span{transition:none;}}
/* the phase medallion: a conic ring filled to the stage completion */
.gr-medal{--pct:0;position:relative;flex:0 0 auto;width:44px;height:44px;border-radius:50%;
  display:grid;place-items:center;
  background:conic-gradient(#2563eb calc(var(--pct) * 1%), #e8ecf1 0);
  box-shadow:0 2px 0 0 #cbd5e1,0 8px 18px -12px rgba(15,23,42,.7);}
.gr-medal::before{content:"";position:absolute;inset:4px;border-radius:50%;background:var(--card);}
.gr-medal b{position:relative;font-size:1rem;font-weight:800;color:var(--ink);}
.gr-card.is-red .gr-medal{background:conic-gradient(#dc2626 calc(var(--pct) * 1%), #fee2e2 0);}
.gr-card.is-amber .gr-medal{background:conic-gradient(#d97706 calc(var(--pct) * 1%), #fef3c7 0);}
.gr-card.is-green .gr-medal{background:conic-gradient(#16a34a calc(var(--pct) * 1%), #dcfce7 0);}
.gr-title{min-width:0;flex:1 1 auto;}
.gr-name-row{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap;min-width:0;}
/* the part number, literally highlighted: mono on highlighter yellow, so two
   projects of one customer can never be mixed mid-sentence */
.gr-part{text-decoration:none;cursor:pointer;display:inline-block;
  transition:transform .12s ease,box-shadow .12s ease;
  font-family:ui-monospace,'SF Mono',Menlo,Consolas,monospace;
  font-size:.82rem;font-weight:800;letter-spacing:.02em;white-space:nowrap;
  color:#713f12;background:linear-gradient(180deg,#fef9c3,#fef08a);
  border:1px solid #fde047;border-radius:8px;padding:.1rem .5rem;
  box-shadow:0 2px 0 0 #facc15;}
.gr-part:hover{color:#713f12;transform:translateY(-1px);
  box-shadow:0 3px 0 0 #facc15,0 8px 14px -8px rgba(202,138,4,.7);}
.gr-part:active{transform:translateY(1px);box-shadow:0 1px 0 0 #facc15;}
@media (prefers-reduced-motion:reduce){.gr-part{transition:none;}
  .gr-part:hover{transform:none;}}
/* the journey rail: Gate 0 → Phase 5 as six nodes */
.gr-rail{display:flex;align-items:center;margin:.55rem 0 .6rem;}
.gr-node{position:relative;flex:0 0 auto;width:24px;height:24px;border-radius:50%;
  display:grid;place-items:center;background:var(--bg);border:2px solid #cbd5e1;}
.gr-node i{font-style:normal;font-size:.6rem;font-weight:800;color:var(--muted-2,#94a3b8);}
.gr-node.st-complete{background:linear-gradient(180deg,#22c55e,#16a34a);border-color:#15803d;
  box-shadow:0 1px 0 0 #15803d;}
.gr-node.st-complete i{color:#fff;}
.gr-node.st-in_progress{background:#eff6ff;border-color:#2563eb;}
.gr-node.st-in_progress i{color:#1d4ed8;}
.gr-node.st-overdue{background:linear-gradient(180deg,#f87171,#dc2626);border-color:#991b1b;}
.gr-node.st-overdue i{color:#fff;}
.gr-node.is-here{transform:scale(1.22);z-index:1;
  box-shadow:0 0 0 4px rgba(37,99,235,.16),0 6px 14px -6px rgba(37,99,235,.7);}
.gr-link{flex:1 1 auto;height:3px;background:var(--bg);min-width:10px;}
.gr-link.is-done{background:linear-gradient(90deg,#16a34a,#86efac);}
.gr-burn{display:inline-grid;place-items:center;min-width:22px;height:22px;border-radius:8px;
  padding:0 .3rem;background:linear-gradient(180deg,#f87171,#dc2626);color:#fff;
  box-shadow:0 2px 0 0 #991b1b;font-size:.74rem;}
.gr-mile i{font-size:.55rem;margin-right:.2rem;}
/* the conversation as bubbles */
.gr-av{flex:0 0 auto;display:grid;place-items:center;width:26px;height:26px;border-radius:50%;
  background:linear-gradient(180deg,#64748b,#475569);color:#fff;font-size:.7rem;
  font-weight:800;box-shadow:0 2px 0 0 #334155;margin-top:.1rem;}
.gr-av-red{background:linear-gradient(180deg,#f87171,#dc2626);box-shadow:0 2px 0 0 #991b1b;}
.gr-av-amber{background:linear-gradient(180deg,#fbbf24,#d97706);box-shadow:0 2px 0 0 #b45309;}
.gr-av-green{background:linear-gradient(180deg,#4ade80,#16a34a);box-shadow:0 2px 0 0 #15803d;}
.gr-bubble{min-width:0;flex:1 1 auto;background:var(--bg);border:1px solid #eef2f7;
  border-radius:3px 13px 13px 13px;padding:.4rem .6rem;}
.gr-bubble p{margin:0;font-size:.8rem;color:var(--ink);}
.gr-bubble em{font-style:normal;font-size:.62rem;color:var(--muted-2,#94a3b8);}
.gr-card{transition:transform .16s ease,box-shadow .16s ease;}
.gr-card:hover{transform:translateY(-2px);
  box-shadow:0 1px 2px rgba(15,23,42,.05),0 22px 44px -30px rgba(15,23,42,.6);}
@media (prefers-reduced-motion:reduce){.gr-card{transition:none;}.gr-card:hover{transform:none;}}
/* ---- @mentions ----------------------------------------------------------- */
.mention{color:#6d28d9;background:#f3effe;border-radius:6px;padding:0 .25rem;
  font-weight:700;}
.mention-box{position:absolute;z-index:1080;display:none;background:var(--card);
  border:1px solid var(--line);border-radius:12px;padding:.25rem;
  box-shadow:0 4px 0 -2px #e2e8f0,0 18px 40px -18px rgba(15,23,42,.55);}
.mention-item{display:flex;align-items:center;gap:.5rem;padding:.3rem .55rem;
  border-radius:9px;font-size:.8rem;font-weight:600;color:var(--ink);cursor:pointer;}
.mention-item.is-sel,.mention-item:hover{background:#f3effe;color:#4c1d95;}
.mention-av{display:grid;place-items:center;width:22px;height:22px;border-radius:50%;
  background:linear-gradient(180deg,#a78bfa,#7c3aed);color:#fff;font-size:.66rem;
  font-weight:800;box-shadow:0 1px 0 0 #5b21b6;}
/* ---- the thread as a window, not a column ------------------------------- */
/* This re-proportions the row and MUST stay behind the same breakpoint as the
   rule that stacks it. Unconditional and later in the file, it beat
   `@media (max-width:980px){.gr-card{grid-template-columns:1fr}}` at every
   width, so on a phone the row kept two columns: the gate stepper squeezed
   into 45% and the note a four-word-wide box beside it. */
@media (min-width:981px){
  .gr-card{grid-template-columns:minmax(0,56%) minmax(0,1fr);align-items:start;}
}
.gr-card{align-items:start;}
.gr-thread-wrap{position:relative;min-width:0;}
.gr-thread{max-height:228px;overflow-y:auto;display:flex;flex-direction:column;
  gap:.4rem;padding-right:.25rem;overscroll-behavior:contain;scrollbar-width:thin;}
.gr-scroll{position:absolute;right:.35rem;bottom:.35rem;width:30px;height:30px;
  border:0;border-radius:50%;display:grid;place-items:center;cursor:pointer;
  color:#fff;background:linear-gradient(180deg,#3b82f6,#2563eb);
  box-shadow:0 3px 0 0 #1d4ed8,0 10px 18px -10px rgba(37,99,235,.9);
  animation:scrollNudge 1.6s ease-in-out infinite;}
.gr-scroll:active{transform:translateY(2px);box-shadow:0 1px 0 0 #1d4ed8;}
@media (prefers-reduced-motion:reduce){.gr-scroll{animation:none;}}
/* ---- the 4M+ readiness chips in the gates review ------------------------ */
/* six equal columns — uniform squares, the due date under each one */
.gr-ready{display:grid;grid-template-columns:auto repeat(6,minmax(0,1fr));
  align-items:start;gap:.3rem;margin:.3rem 0 0;}
.gr-4m-cell{display:flex;flex-direction:column;align-items:stretch;gap:.1rem;min-width:0;}
.gr-4m-due{font-size:.6rem;color:var(--muted-2,#94a3b8);text-align:center;line-height:1.2;
  font-variant-numeric:tabular-nums;}
.gr-4m-due.is-burn{color:#dc2626;font-weight:800;}
.gr-ready-l{font-style:normal;font-size:.56rem;font-weight:800;letter-spacing:.07em;
  color:var(--muted-2,#94a3b8);text-transform:uppercase;margin-right:.15rem;align-self:center;}
/* 3D square tiles: the strip sits in a shallow perspective, each tile tumbles
   in from flat (rotateX 88° → 0) one after the other, and hover tilts it like
   a key pressed from above. The tumble runs once, on load — a meeting screen
   that never stops moving is a screen people stop seeing. */
.gr-ready{perspective:520px;}
.gr-4m{display:inline-flex;align-items:center;justify-content:center;gap:.3rem;
  width:100%;border:1px solid var(--line);background:var(--bg);color:var(--muted-2,#94a3b8);border-radius:7px;
  font-size:.68rem;font-weight:700;padding:.28rem .25rem;cursor:pointer;line-height:1.2;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  transform-style:preserve-3d;transform-origin:50% 100%;box-shadow:0 3px 0 0 #e2e8f0;
  animation:m4Tumble .42s cubic-bezier(.2,.9,.3,1.15) backwards;
  transition:transform .14s ease,box-shadow .14s ease;}
.gr-4m-cell:nth-child(3) .gr-4m{animation-delay:.06s}
.gr-4m-cell:nth-child(4) .gr-4m{animation-delay:.12s}
.gr-4m-cell:nth-child(5) .gr-4m{animation-delay:.18s}
.gr-4m-cell:nth-child(6) .gr-4m{animation-delay:.24s}
.gr-4m-cell:nth-child(7) .gr-4m{animation-delay:.3s}
.gr-4m:hover:not([disabled]){transform:rotateX(-10deg) translateY(-2px);
  box-shadow:0 4px 0 0 #cbd5e1,0 10px 16px -8px rgba(15,23,42,.45);}
.gr-4m:active:not([disabled]){transform:rotateX(6deg) translateY(1px);
  box-shadow:0 1px 0 0 #cbd5e1;}
.gr-4m[disabled]{cursor:default;}
.gr-4m-ok{background:linear-gradient(180deg,#dcfce7,#bbf7d0);border-color:#86efac;color:#166534;
  box-shadow:0 3px 0 0 #86efac;}
.gr-4m-late{background:linear-gradient(180deg,#fef3c7,#fde68a);border-color:#fcd34d;color:#92400e;
  box-shadow:0 3px 0 0 #fcd34d;}
.gr-4m-run{background:#eff6ff;border-color:#93c5fd;color:#1d4ed8;box-shadow:0 3px 0 0 #93c5fd;}
.gr-4m-hold{background:#f5f3ff;border-color:#ddd6fe;color:#5b21b6;box-shadow:0 3px 0 0 #ddd6fe;}
.gr-4m-burn{background:linear-gradient(180deg,#fee2e2,#fecaca);border-color:#f87171;color:#991b1b;
  animation:m4Tumble .42s cubic-bezier(.2,.9,.3,1.15) backwards,
            m4Burn 1.5s ease-in-out .5s infinite;}
@media (prefers-reduced-motion:reduce){
  .gr-4m,.gr-4m-burn{animation:none;transition:none;}
  .gr-4m:hover:not([disabled]){transform:none;}}
/* reclaim the strip's height from the rail so the card rhythm stays put */
.gr-rail{margin:.4rem 0 .45rem;}
@keyframes scrollNudge{0%,100%{transform:translateY(0);}50%{transform:translateY(3px);}}


/* ── process-flow characteristics, one row each (ACS staging port) ─────────
   NB: `.pf-chars` was already taken by the diagram node's chips, which is why
   these are `pfc-*`. One row per characteristic controlled at an operation,
   each with its own special-characteristic class, because the class describes
   the characteristic and not the operation. */
.pfc-list { display: flex; flex-direction: column; gap: 3px; min-width: 215px; }
/* nowrap + width:auto beat the grid's `.cell-input{width:100%}`, which put the
   class dropdown and the remove button on lines of their own. */
.pfc-row { display: flex; align-items: center; gap: 3px; flex-wrap: nowrap; }
.pfc-row .pfc-text { flex: 1 1 auto; min-width: 0; width: auto; }
.pfc-row .pfc-cls {
  flex: 0 0 56px; width: 56px; font-size: .72rem; padding-right: .25rem;
  background-image: none;              /* the global chevron eats the value */
}
.pfc-row.is-special .pfc-cls {
  font-weight: 700; color: #dc2626;
  border-color: rgba(220, 38, 38, .45);
}
.pfc-row .pfc-del { flex: 0 0 auto; line-height: 1; opacity: .45; }
.pfc-row:hover .pfc-del { opacity: 1; }
.pfc-add { font-size: .7rem; opacity: .75; align-self: flex-start; padding: 0; }
.pfc-add:hover { opacity: 1; }


/* ── FMEA worksheet: the process-step band (ACS staging port) ──────────────
   One band per process step with its failure modes underneath. The step's own
   facts live here because they belong to the step — they used to be copied
   onto every row beneath it. */
.fmea-stepband > td {
  background: var(--surface-2, #eef2f7);
  border-top: 2px solid var(--line, #d7dee8);
  padding: .3rem .5rem !important;
  position: sticky; left: 0;          /* reachable on a very wide sheet */
}
.fmea-stepband-in { min-height: 26px; }
.fmea-stepband.is-editing > td { background: var(--surface-1, #fff); }
:root[data-theme="midnight"] .fmea-stepband > td { background: rgba(148,163,184,.10); }

.fmea-actions-row > td { background: var(--surface-2, #f6f8fb); padding: .5rem .75rem !important; }
.fmea-actions-in { max-width: 1200px; position: sticky; left: 0; }
.fmea-actions-tbl th, .fmea-actions-tbl td { padding: .2rem .3rem !important; }
:root[data-theme="midnight"] .fmea-actions-row > td { background: rgba(148,163,184,.08); }


/* ── the worksheet ribbon (ported 1:1 from the ACS staging app) ────────────
   A sticky action bar above the sheet, not a row of pills. Each action is a
   coloured 3-D tile with its name under it: on a 28-column sheet you find a
   button by its colour and shape long before you read it, and the label stops
   the colour from being the only thing carrying the meaning. */
.docbar {
  position: sticky; top: 0; z-index: 1020;
  background: linear-gradient(var(--card, #fff), var(--surface-2, #f7f9fc));
  border: 1px solid var(--line, #e5e9f2);
  border-bottom: 2px solid var(--line-2, #dbe3ee);
  border-radius: 12px 12px 0 0; padding: .4rem .55rem;
  display: flex; flex-wrap: wrap; align-items: stretch; gap: .3rem;
  box-shadow: 0 4px 14px rgba(15, 23, 42, .07);
}
.docbar-sep { width: 1px; margin: 0 .3rem;
  background: linear-gradient(transparent, var(--line-2, #dbe3ee) 18%,
                              var(--line-2, #dbe3ee) 82%, transparent); }
.docbar-g { display: inline-flex; align-items: stretch; gap: .25rem; }
.docbar-t { align-self: center; font-size: .58rem; font-weight: 800;
  letter-spacing: .07em; text-transform: uppercase;
  color: var(--ink-soft, #94a3b8); margin-right: .2rem; }
.docbtn {
  --a: #64748b;
  display: inline-flex; flex-direction: column; align-items: center;
  justify-content: flex-start; gap: .2rem; min-width: 56px;
  padding: .3rem .4rem .25rem; border: 1px solid transparent;
  border-radius: 10px; background: transparent; text-decoration: none;
  color: var(--ink-soft); line-height: 1;
}
.docbtn:hover { background: var(--surface-2, #eef2f8);
  border-color: var(--line, #e2e8f0); color: var(--ink, #1e293b); }
.docbtn:focus-visible { outline: 2px solid var(--accent, #2563eb); outline-offset: 1px; }
.docbtn .dbi { /* light-only: the lit top face of a 3-D icon — a coloured object, not a surface */
  width: 30px; height: 30px; border-radius: 9px; display: inline-flex;
  align-items: center; justify-content: center; color: #fff; font-size: .92rem;
  background: linear-gradient(150deg,
      color-mix(in srgb, var(--a) 78%, #fff 16%),
      color-mix(in srgb, var(--a) 82%, #000));
  box-shadow: 0 2px 0 color-mix(in srgb, var(--a) 60%, #000),
              0 5px 12px -3px color-mix(in srgb, var(--a) 55%, transparent),
              inset 0 1px 0 rgba(255, 255, 255, .45);
  transition: transform .08s ease, box-shadow .08s ease;
}
.docbtn:active .dbi { transform: translateY(2px);
  box-shadow: 0 0 0 color-mix(in srgb, var(--a) 60%, #000),
              0 2px 6px -3px color-mix(in srgb, var(--a) 55%, transparent),
              inset 0 1px 0 rgba(255, 255, 255, .35); }
.docbtn .dbl { font-size: .6rem; font-weight: 700; white-space: nowrap; }
.docbtn[disabled], .docbtn:disabled { opacity: .38; cursor: not-allowed; }
.docbtn[disabled]:hover { background: transparent; border-color: transparent; }
.docbtn[disabled] .dbi { box-shadow: none; filter: grayscale(.7); }
@media (prefers-reduced-motion: reduce) { .docbtn .dbi { transition: none; } }
/* On a phone the ribbon is wider than the screen — six 98px tiles come to
   475px — and because `.docbar-g` is an inline-flex that will not shrink
   below its content, it was the whole DOCUMENT that scrolled sideways. The
   house rule is that wide furniture scrolls inside its own box, so here it
   does. Shrinking the tiles instead would have made them untappable, which is
   the one thing a phone must not do to a bar of buttons.

   Found by `check_responsive` on the 5S tabs; it fixes the PFMEA, the Control
   Plan and the Process Flow at the same time, since all four share this bar. */
@media (max-width: 575.98px) {
  .docbar { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: thin;
            -webkit-overflow-scrolling: touch; }
  .docbar > * { flex: 0 0 auto; }
}

/* the same four actions, on the row itself — the ribbon is where you look for
   them once the sheet is wide and you have scrolled away from the first cell */
.fm-actbtns { display: grid; grid-template-columns: repeat(2, auto);
  gap: 2px; margin-top: 2px; }
.fm-actbtns .btn { --bs-btn-padding-y: 0; --bs-btn-padding-x: .2rem;
  font-size: .62rem; line-height: 1.3; }
.fm-handle { width: 46px; }
tr.is-picked > td { background: color-mix(in srgb, var(--accent, #2f6fed) 9%, transparent) !important; }
tr.is-picked > td:first-child { box-shadow: inset 3px 0 0 var(--accent, #2f6fed); }

:root[data-theme="midnight"] .docbar {
  background: linear-gradient(rgba(148,163,184,.10), rgba(148,163,184,.04));
  box-shadow: 0 4px 14px rgba(0, 0, 0, .35);
}

/* ==========================================================================
   Metrology — premium layer
   The register is the screen a metrology technician leaves open all day, so
   it gets the same treatment as the FMEA worksheet and the SPC detail: a
   hero, 3D KPI icons, extruded charts, and depth from lighting rather than
   from borders. Everything that moves is behind prefers-reduced-motion.
   ========================================================================== */

/* A red state PULSES. In this module red never means "slightly worse" — it
   means a device is out of calibration, quarantined, or a §7.1.5.2.1
   obligation is open, and a technician scanning a hundred rows must not be
   able to read past it. Amber and grey stay still, or the pulse would carry
   no information. */
@keyframes metPulse {
  0%   { box-shadow: 0 0 0 0 rgba(225, 29, 72, .60); opacity: 1; }
  55%  { box-shadow: 0 0 0 7px rgba(225, 29, 72, 0); opacity: .82; }
  100% { box-shadow: 0 0 0 0 rgba(225, 29, 72, 0);   opacity: 1; }
}
.met-blink { animation: metPulse 1.15s ease-in-out infinite;
  will-change: box-shadow, opacity; border-radius: 999px; }
@keyframes metPulseSoft {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: .45; transform: scale(.9); }
}
.met-blink-dot { animation: metPulseSoft 1.15s ease-in-out infinite; }

/* Metrology hero — the module's own accent strip on top of .fmea-hero */
.met-hero-ok::before       { background: linear-gradient(180deg, #34d399, #059669); }
.met-hero-warn::before     { background: linear-gradient(180deg, #fbbf24, #d97706); }
.met-hero-danger::before   { background: linear-gradient(180deg, #fb7185, #e11d48); }
.met-hero-muted::before    { background: linear-gradient(180deg, #94a3b8, #475569); }

/* KPI tile — 3D icon, big number, tone rail. Same vocabulary as the SPC and
   MSA KPI bands so the app reads as one product. */
.met-kpi { position: relative; overflow: hidden; display: flex; align-items: center;
  gap: .8rem; background: var(--card); border: 1px solid var(--line);
  border-radius: 16px; padding: .8rem .95rem; height: 100%;
  box-shadow: var(--shadow-xs);
  transition: transform .18s cubic-bezier(.2,.7,.3,1), box-shadow .18s ease; }
.met-kpi:hover { transform: translateY(-3px); box-shadow: var(--shadow); }
.met-kpi::after { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px;
  background: var(--line); }
.met-kpi.t-ok::after     { background: linear-gradient(180deg, #34d399, #059669); }
.met-kpi.t-warn::after   { background: linear-gradient(180deg, #fbbf24, #d97706); }
.met-kpi.t-danger::after { background: linear-gradient(180deg, #fb7185, #e11d48); }
.met-kpi-body { min-width: 0; }
.met-kpi-val { font-size: 1.6rem; font-weight: 800; line-height: 1; color: var(--ink);
  letter-spacing: -.02em; }
.met-kpi-val.is-danger { color: var(--danger); }
.met-kpi-val.is-warn   { color: #b45309; }
.met-kpi-lbl { font-size: .74rem; font-weight: 700; color: var(--ink); margin-top: .28rem; }
.met-kpi-sub { font-size: .68rem; color: var(--ink-soft); }

/* Register rows — a state rail on the left of each row, so the eye finds the
   broken devices before it reads a single word. */
.met-table tbody tr { transition: background .14s ease, box-shadow .14s ease; }
.met-table tbody tr:hover { background: color-mix(in srgb, var(--accent) 5%, transparent); }
.met-table tbody tr > td:first-child { position: relative; }
.met-table tbody tr > td:first-child::before { content: ""; position: absolute;
  left: 0; top: 6px; bottom: 6px; width: 3px; border-radius: 3px; background: transparent; }
.met-table tr.r-ok     > td:first-child::before { background: var(--ok); }
.met-table tr.r-warn   > td:first-child::before { background: var(--warn); }
.met-table tr.r-danger > td:first-child::before { background: var(--danger); }

/* Device photo — a lit plate rather than a bare image */
.met-photo { border-radius: 16px; overflow: hidden; position: relative;
  box-shadow: 0 14px 30px -12px rgba(2,6,23,.45); }
.met-photo::after { content: ""; position: absolute; inset: 0;
  background: linear-gradient(160deg, rgba(255,255,255,.22), rgba(255,255,255,0) 46%);
  pointer-events: none; }

/* A gauge for "how much of the register is actually usable" */
.met-gauge { position: relative; height: 10px; border-radius: 999px;
  background: color-mix(in srgb, var(--ink) 9%, transparent); overflow: hidden; }
.met-gauge > span { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 999px;
  background: linear-gradient(90deg, #34d399, #059669);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.5);
  animation: metGrow .9s cubic-bezier(.2,.7,.3,1) both; }
.met-gauge.g-warn > span   { background: linear-gradient(90deg, #fbbf24, #d97706); }
.met-gauge.g-danger > span { background: linear-gradient(90deg, #fb7185, #e11d48); }
@keyframes metGrow { from { width: 0 !important; } }

/* Obligation cards — the §7.1.5.2.1 chain, which must look like a chain */
.met-chain { display: flex; flex-direction: column; gap: .55rem; }
.met-chain-row { display: flex; align-items: flex-start; gap: .7rem;
  padding: .6rem .8rem; border: 1px solid var(--line); border-radius: 12px;
  background: var(--bg); }
.met-chain-row.open { border-color: color-mix(in srgb, var(--danger) 40%, transparent);
  background: color-mix(in srgb, var(--danger) 6%, transparent); }
.met-chain-ic { width: 26px; height: 26px; border-radius: 8px; flex: none;
  display: grid; place-items: center; color: #fff; font-size: .8rem;
  background: linear-gradient(135deg, #94a3b8, #475569); }
.met-chain-row.open .met-chain-ic { background: linear-gradient(135deg, #fb7185, #e11d48); }

@media (prefers-reduced-motion: reduce) {
  .met-blink, .met-blink-dot, .met-gauge > span { animation: none; }
  .met-kpi:hover { transform: none; }
}

/* The hero chips need a neutral variant: a device with no study and no
   control-plan obligation is not a fault, and colouring it amber would say
   otherwise. */
.fk-ic.g-slate { background: linear-gradient(135deg, #94a3b8, #475569); }

/* ── The navbar between a tablet and a wide laptop ─────────────────────────
   The bar needs 1168px to lay itself out at its full size, but Bootstrap
   expands it at 992px — so from an iPad in landscape up to about 1240px it
   was rendering a desktop navbar wider than the screen and every page in the
   application scrolled sideways. Collapsing it to a hamburger that early
   would be the easy fix and the wrong one: this is a dense application whose
   users live in the menus, and hiding navigation on a 1100px laptop to save
   sixty pixels trades a real cost for a cosmetic one. So the bar is tightened
   in that band instead, and the two discretionary items — the quick-icon
   shortcuts and the search hint — appear only above 1400px where there is
   room for them. */
@media (min-width: 992px) and (max-width: 1399.98px) {
  .proq-nav .nav-link { padding-left: .5rem; padding-right: .5rem; font-size: .86rem; }
  .proq-nav .navbar-nav { gap: 0 !important; }
  .proq-nav .brand-tag { display: none; }
}

/* A page header's action cluster wraps rather than pushing the page sideways.
   The header row already wraps, but the cluster inside it is a single flex
   item: five buttons in a row measure 715px, nearly twice the width of a
   phone, so the whole document scrolled sideways on every screen that had
   more than about three actions. Fourteen templates share this shape, which
   is why it is fixed once here rather than in each of them. Left-aligned once
   wrapped, because `ms-auto` pushing a second row to the right edge reads as
   a mistake. */
@media (max-width: 991.98px) {
  .d-flex.flex-wrap > .d-flex.gap-2.ms-auto,
  .d-flex.flex-wrap > .ms-auto.d-flex.gap-2 {
    flex-wrap: wrap; margin-left: 0 !important;
  }
}

/* ===================================================================
   Workload: module top bar, team Gantt, paused-work notice.
   Ported from the staging app, where these screens were designed;
   kept together and unedited so the two apps can be diffed.
   =================================================================== */
/* ---- Team Gantt: people down, weeks across, tasks in the cell ----------
   Everything here is built to be READ at a glance and HANDLED with a mouse:
   a bar is a physical little object you can pick up, a week cell is a place
   you can drop it into, and both say so with depth rather than a caption. */

/* control panel -------------------------------------------------------- */
.tg-controls{display:flex;flex-wrap:wrap;align-items:center;gap:1.1rem;
  padding:.7rem .9rem;border-radius:16px;
  background:linear-gradient(180deg,#ffffff,#f4f7fc);
  border:1px solid #dfe6f3;
  box-shadow:0 10px 24px -18px rgba(15,23,42,.55),inset 0 1px 0 #fff;}
.tg-ctl-form{display:flex;flex-wrap:wrap;align-items:center;gap:1.1rem;margin:0;}
.tg-ctl{display:flex;align-items:center;gap:.5rem;}
.tg-ctl-label{font-size:.62rem;font-weight:800;letter-spacing:.09em;
  text-transform:uppercase;color:#8b97ab;}
.tg-seg{display:inline-flex;gap:3px;padding:3px;border-radius:11px;
  background:linear-gradient(180deg,#e6ebf5,#f2f5fb);
  box-shadow:inset 0 2px 4px rgba(15,23,42,.12),0 1px 0 #fff;}
.tg-seg-btn{display:inline-block;padding:.3rem .7rem;border-radius:8px;
  font-size:.72rem;font-weight:800;color:#5b6880;text-decoration:none;
  background:linear-gradient(180deg,#fff,#eef2f9);
  box-shadow:0 2px 0 #cfd8e8,0 4px 8px -5px rgba(15,23,42,.5),inset 0 1px 0 #fff;
  transition:transform .12s ease,box-shadow .12s ease,color .12s ease;}
.tg-seg-btn:hover{color:#1d4ed8;transform:translateY(-1px);
  box-shadow:0 3px 0 #cfd8e8,0 8px 14px -8px rgba(29,78,216,.6),inset 0 1px 0 #fff;}
.tg-seg-btn:active{transform:translateY(1px);box-shadow:0 1px 0 #cfd8e8,inset 0 2px 4px rgba(15,23,42,.18);}
.tg-seg-btn.is-on{color:#fff;background:linear-gradient(180deg,#3b82f6,#1d4ed8);
  box-shadow:0 3px 0 #17399c,0 8px 16px -8px rgba(29,78,216,.85),inset 0 1px 0 rgba(255,255,255,.45);}
.tg-select{border:0;border-radius:10px;padding:.34rem .7rem;font-size:.76rem;font-weight:700;
  color:#334155;background:linear-gradient(180deg,#fff,#eef2f9);
  box-shadow:0 2px 0 #cfd8e8,0 4px 8px -5px rgba(15,23,42,.45),inset 0 1px 0 #fff;}
.tg-select:focus{outline:2px solid #2563eb;outline-offset:2px;}
.tg-stats{display:flex;flex-wrap:wrap;gap:.4rem;margin-left:auto;}
.tg-stat{display:inline-flex;align-items:baseline;gap:.3rem;padding:.24rem .7rem;
  border-radius:99px;font-size:.68rem;font-weight:600;color:#475569;
  background:linear-gradient(180deg,#fff,#eef2f9);
  box-shadow:0 2px 0 #d7dfec,inset 0 1px 0 #fff;}
.tg-stat b{font-size:.9rem;font-weight:800;color:#0f172a;}
.tg-stat.is-late{color:#b91c1c;background:linear-gradient(180deg,#fff5f5,#fee2e2);
  box-shadow:0 2px 0 #fca5a5,inset 0 1px 0 #fff;}
.tg-stat.is-late b{color:#b91c1c;}
.tg-stat.is-undated{color:#92400e;background:linear-gradient(180deg,#fffbeb,#fef3c7);
  box-shadow:0 2px 0 #fcd34d,inset 0 1px 0 #fff;}
.tg-stat.is-undated b{color:#92400e;}

/* the board ------------------------------------------------------------ */
.tg-board{border-radius:18px;overflow:hidden;background:#fff;
  box-shadow:0 24px 50px -30px rgba(15,23,42,.6),0 0 0 1px #e4e9f2;}
.tg-wrap{max-height:74vh;overflow:auto;}
/* Fixed layout is what lets a title fill its cell: the columns are sized by
   the header, never by the longest task, so `text-overflow:ellipsis` cuts at
   the width the layout actually gave — wide when four weeks are shown, narrow
   at twenty-six. The table still grows past the viewport (and scrolls) once
   the weeks no longer fit at a readable width. */
.tg{border-collapse:separate;border-spacing:0;table-layout:fixed;
  width:max(100%, calc(206px + 3 * 66px + var(--nc,8) * 132px + var(--nd,0) * 322px));}
.tg th.tg-wk{width:auto;}          /* the week columns share what is left */
.tg thead th{position:sticky;top:0;z-index:3;color:#fff;font-size:.6rem;
  letter-spacing:.05em;text-transform:uppercase;padding:.45rem .3rem;
  text-align:center;border:0;white-space:nowrap;
  background:linear-gradient(180deg,#24407f 0%,#1b2f60 55%,#132247 100%);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.16),inset 0 -2px 0 rgba(0,0,0,.25);}
.tg thead th.is-now{background:linear-gradient(180deg,#3b82f6,#1d4ed8 60%,#1e40af);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.35),inset 0 -2px 0 rgba(0,0,0,.22);}
.tg-cw{display:block;font-weight:800;text-shadow:0 1px 1px rgba(0,0,0,.4);}
.tg-cw i{font-size:.55rem;opacity:.65;margin-left:.15rem;}
.tg-dt{display:block;font-weight:500;opacity:.75;font-size:.55rem;}
.tg-wk-btn{display:block;color:inherit;text-decoration:none;border-radius:6px;
  padding:.05rem .2rem;transition:background .12s ease;}
.tg-wk-btn:hover{color:#fff;background:rgba(255,255,255,.14);}
.tg-wk-btn:hover .tg-cw i{opacity:1;}
.tg thead th.tg-wk.is-open{background:linear-gradient(180deg,#2f4fa0,#1d3272 60%,#16255c);}
/* the day strip under an opened week */
.tg thead th.tg-day-h{font-size:.54rem;padding:.25rem .1rem;font-weight:700;
  background:linear-gradient(180deg,#1b2f60,#132247);}
.tg thead th.tg-day-h.is-we{background:linear-gradient(180deg,#152648,#0e1a35);opacity:.8;}
.tg thead th.tg-day-h.is-today{background:linear-gradient(180deg,#3b82f6,#1d4ed8);}
.tg-dow{display:block;letter-spacing:.06em;}
.tg-dnum{display:block;font-weight:800;font-size:.62rem;opacity:.85;}
.tg th.tg-who,.tg td.tg-who{position:sticky;left:0;z-index:2;background:#fff;
  width:206px;text-align:left;padding:.45rem .7rem;
  box-shadow:6px 0 12px -8px rgba(15,23,42,.45);}
.tg thead th.tg-who{z-index:4;
  background:linear-gradient(180deg,#24407f 0%,#1b2f60 55%,#132247 100%);}
.tg-person{display:flex;align-items:center;gap:.5rem;}
.tg-person-txt{min-width:0;}
.tg-av{width:30px;height:30px;border-radius:50%;display:inline-flex;align-items:center;
  justify-content:center;font-size:.74rem;font-weight:800;color:#fff;flex:0 0 auto;
  background:linear-gradient(150deg,#7cb0ff,#2563eb 55%,#1740a8);
  box-shadow:0 3px 0 #17399c,0 6px 12px -7px rgba(23,57,156,.9),
             inset 0 1px 0 rgba(255,255,255,.55);}
.tg-av.is-nobody{background:linear-gradient(150deg,#dfe6f0,#94a3b8 60%,#64748b);
  box-shadow:0 3px 0 #52607a,inset 0 1px 0 rgba(255,255,255,.5);}
.tg-name{font-size:.8rem;font-weight:700;color:#0f172a;text-decoration:none;}
.tg-name:hover{color:#1d4ed8;text-decoration:underline;}
.tg-sub{font-size:.62rem;color:#94a3b8;}
.tg td{border-bottom:1px solid #eef2f6;border-right:1px solid #f3f6fa;
  vertical-align:top;padding:.3rem;}
.tg tbody tr:hover td{background-color:rgba(37,99,235,.028);}
.tg tbody tr:hover td.tg-who{background:#f8faff;}

/* week cell = a place you may drop into ------------------------------- */
.tg-cell{position:relative;overflow:hidden;
  background:rgba(37,99,235,calc(var(--load,0) * .0045));
  transition:box-shadow .15s ease,background .15s ease;}
.tg-cell.is-now{box-shadow:inset 3px 0 0 #2563eb;}
.tg-cell.is-day{min-width:0;background:#fff;}
.tg-cell.is-day.is-we{background:repeating-linear-gradient(45deg,
  #f8fafc 0 6px, #f1f5f9 6px 12px);}
.tg-cell.is-day.is-today{background:rgba(37,99,235,.09);
  box-shadow:inset 0 0 0 1px rgba(37,99,235,.35);}
.tg-board.is-dragging .tg-cell{box-shadow:inset 0 0 0 1px rgba(37,99,235,.22);}
.tg-board.is-dragging .tg-cell.is-now{box-shadow:inset 3px 0 0 #2563eb,inset 0 0 0 1px rgba(37,99,235,.22);}
.tg-cell.is-over{background:rgba(37,99,235,.14);
  box-shadow:inset 0 0 0 2px #2563eb,0 0 22px -6px rgba(37,99,235,.75);}
.tg-cell.is-nope{background:rgba(220,38,38,.09);cursor:not-allowed;
  box-shadow:inset 0 0 0 2px #dc2626;}
.tg-bars{display:flex;flex-direction:column;gap:3px;min-height:26px;}

/* the bar = a small object you can pick up ----------------------------- */
.tg-bar{display:flex;flex-direction:column;gap:1px;text-decoration:none;
  border-radius:8px;padding:.22rem .4rem .24rem .45rem;position:relative;
  background:linear-gradient(180deg,#fff, color-mix(in srgb,var(--c) 13%,#fff));
  border-left:3px solid var(--c);color:#0f172a;
  box-shadow:0 1px 0 rgba(255,255,255,.9) inset,
             0 2px 0 color-mix(in srgb,var(--c) 28%,#e2e8f0),
             0 5px 10px -7px rgba(15,23,42,.55);
  animation:tgIn .4s cubic-bezier(.2,.9,.3,1) backwards;
  animation-delay:calc(var(--row,0) * 45ms);
  transition:transform .14s cubic-bezier(.2,.9,.3,1),box-shadow .14s ease;}
.tg-bar[draggable="true"]{cursor:grab;}
.tg-bar[draggable="true"]:active{cursor:grabbing;}
.tg-bar:hover{color:#0f172a;transform:translateY(-2px);
  box-shadow:0 1px 0 rgba(255,255,255,.95) inset,
             0 4px 0 color-mix(in srgb,var(--c) 34%,#dbe3ef),
             0 12px 20px -10px color-mix(in srgb,var(--c) 62%,transparent);}
.tg-bar.is-dragging{opacity:.45;transform:scale(.97) rotate(-1.2deg);}
.tg-bar-top{display:flex;align-items:center;gap:.28rem;font-size:.63rem;font-weight:700;
  line-height:1.15;}
.tg-bar-top i{font-size:.6rem;color:var(--c);flex:0 0 auto;}
.tg-bar-title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  min-width:0;flex:1 1 auto;}
.tg-bar-proj{display:flex;align-items:center;gap:.24rem;font-size:.56rem;font-weight:600;
  color:#64748b;letter-spacing:.01em;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap;padding-left:.02rem;}
.tg-bar-proj i{font-size:.52rem;opacity:.75;flex:0 0 auto;}
.tg-when{font-style:normal;font-weight:800;color:#64748b;margin-left:auto;flex:0 0 auto;}
/* --- state colours. They override the module tint on purpose: a manager
   scanning the board is asking "what is late / waiting / done", and the module
   is still there in the icon and the tooltip. --- */
.tg-bar.u-overdue{background:linear-gradient(180deg,#ef4444,#b91c1c);
  border-left-color:#7f1d1d;color:#fff;
  box-shadow:0 1px 0 rgba(255,255,255,.25) inset,0 2px 0 #7f1d1d,
             0 6px 12px -7px rgba(153,27,27,.85);}
.tg-bar.u-overdue .tg-bar-top i,.tg-bar.u-overdue .tg-when,
.tg-bar.u-overdue .tg-bar-proj,.tg-bar.u-overdue .tg-bar-proj i{color:#fff;opacity:.92;}
.tg-bar.u-overdue:hover{color:#fff;
  box-shadow:0 1px 0 rgba(255,255,255,.3) inset,0 4px 0 #7f1d1d,
             0 14px 22px -10px rgba(185,28,28,.9);}
/* waiting for a signature */
.tg-bar.s-waiting{background:linear-gradient(180deg,#fffbeb,#fde68a);
  border-left-color:#d97706;color:#78350f;
  box-shadow:0 1px 0 rgba(255,255,255,.9) inset,0 2px 0 #fbbf24,
             0 5px 10px -7px rgba(146,64,14,.55);}
.tg-bar.s-waiting .tg-bar-top i,.tg-bar.s-waiting .tg-when{color:#b45309;}
.tg-bar.s-waiting .tg-bar-proj{color:#92400e;}
.tg-bar.s-waiting:hover{color:#78350f;
  box-shadow:0 1px 0 rgba(255,255,255,.95) inset,0 4px 0 #fbbf24,
             0 13px 20px -10px rgba(217,119,6,.75);}
/* approved and released — history, and it does not pick up */
.tg-bar.s-done{background:linear-gradient(180deg,#f0fdf4,#bbf7d0);
  border-left-color:#16a34a;color:#14532d;cursor:default;
  box-shadow:0 1px 0 rgba(255,255,255,.9) inset,0 2px 0 #86efac,
             0 5px 10px -7px rgba(20,83,45,.5);}
.tg-bar.s-done .tg-bar-top i,.tg-bar.s-done .tg-when{color:#16a34a;}
.tg-bar.s-done .tg-bar-proj{color:#3f6212;}
.tg-bar.s-done .tg-bar-title{text-decoration:line-through;text-decoration-color:rgba(20,83,45,.35);}
.tg-bar.s-done:hover{color:#14532d;
  box-shadow:0 1px 0 rgba(255,255,255,.95) inset,0 4px 0 #86efac,
             0 13px 20px -10px rgba(22,163,74,.6);}
/* a released stage that had gone past its date is still DONE: green wins */
.tg-bar.u-overdue.s-done{background:linear-gradient(180deg,#f0fdf4,#bbf7d0);
  border-left-color:#16a34a;color:#14532d;}
.tg-bar.u-overdue.s-done .tg-bar-top i,.tg-bar.u-overdue.s-done .tg-bar-proj,
.tg-bar.u-overdue.s-done .tg-bar-proj i,.tg-bar.u-overdue.s-done .tg-when{color:#16a34a;}
.tg-bar.is-extra{display:none;}
.tg-cell.is-open .tg-bar.is-extra{display:flex;}
.tg-bar.is-saving{animation:tgPulse .8s ease-in-out infinite;}
.tg-bar.is-moved{animation:tgLand .9s cubic-bezier(.2,.9,.3,1);}
.tg-more{display:inline-block;margin-top:2px;padding:.06rem .38rem;border:0;
  border-radius:6px;font-size:.56rem;font-weight:700;color:#475569;
  background:linear-gradient(180deg,#fff,#e8eefa);
  box-shadow:0 1px 0 #cbd5e1,inset 0 1px 0 #fff;cursor:pointer;
  transition:transform .12s ease,color .12s ease;}
.tg-more:hover{color:#1d4ed8;transform:translateY(-1px);}
.tg-more:active{transform:translateY(1px);}

/* side columns: counted, and openable so their work can be dragged out -- */
.tg-side{width:66px;text-align:center;position:relative;}
.tg thead th.tg-side{width:66px;}
.tg-count{display:inline-flex;min-width:24px;justify-content:center;font-size:.68rem;
  font-weight:800;color:#fff;border-radius:99px;padding:.1rem .45rem;border:0;cursor:pointer;
  background:linear-gradient(180deg,#aab6c6,#68748a);
  box-shadow:0 2px 0 #4d5871,0 5px 10px -6px rgba(15,23,42,.7),
             inset 0 1px 0 rgba(255,255,255,.4);
  transition:transform .12s ease;}
.tg-count:hover{transform:translateY(-1px);}
.tg-count:active{transform:translateY(1px);}
.tg-side.is-open .tg-count{box-shadow:0 0 0 3px rgba(37,99,235,.28),0 2px 0 #4d5871;}
.tg-side.is-late .tg-count{background:linear-gradient(180deg,#f87171,#dc2626);
  box-shadow:0 2px 0 #991b1b,0 5px 10px -6px rgba(153,27,27,.8),
             inset 0 1px 0 rgba(255,255,255,.4);}
.tg-count.is-later{background:linear-gradient(180deg,#a5b4fc,#4f46e5);
  box-shadow:0 2px 0 #3730a3,inset 0 1px 0 rgba(255,255,255,.4);}
.tg-count.is-undated{background:linear-gradient(180deg,#fcd34d,#d97706);
  box-shadow:0 2px 0 #92400e,inset 0 1px 0 rgba(255,255,255,.45);}
.tg-nil{color:#cbd5e1;}
.tg-pop{display:none;position:absolute;right:0;top:100%;z-index:12;
  width:330px;max-height:340px;overflow:auto;text-align:left;
  background:var(--card);border-radius:14px;padding:.45rem;
  box-shadow:0 26px 46px -20px rgba(15,23,42,.62),0 0 0 1px var(--line);}
.tg-side.is-open .tg-pop{display:block;animation:tgIn .18s ease;}
.tg-pop-head{font-size:.58rem;font-weight:800;letter-spacing:.05em;text-transform:uppercase;
  color:#94a3b8;padding:.1rem .25rem .3rem;}
.tg-pop-foot{font-size:.58rem;color:#94a3b8;padding:.3rem .25rem 0;font-style:italic;}
.tg-pop .tg-bar{margin-bottom:3px;animation:none;}
.tg-bar-top{min-width:0;}

/* legend + toast ------------------------------------------------------- */
.tg-legend{display:flex;flex-wrap:wrap;align-items:center;gap:.6rem;
  padding:.55rem .9rem;font-size:.68rem;color:#64748b;
  background:linear-gradient(180deg,#f8fafc,#eef2f8);border-top:1px solid #e6ebf3;}
.tg-legend i{color:#2563eb;}
.tg-legend-sep{width:1px;height:14px;background:#d5dce8;}
.tg-toast{position:fixed;right:22px;bottom:22px;z-index:1080;
  max-width:min(420px,80vw);padding:.7rem 1rem;border-radius:13px;
  font-size:.8rem;font-weight:600;color:#fff;pointer-events:none;
  background:linear-gradient(180deg,#1f3a8a,#152a63);
  box-shadow:0 18px 34px -14px rgba(15,23,42,.8),inset 0 1px 0 rgba(255,255,255,.22);
  opacity:0;transform:translateY(18px) scale(.96);
  transition:opacity .22s ease,transform .22s cubic-bezier(.2,.9,.3,1);}
.tg-toast.is-open{opacity:1;transform:translateY(0) scale(1);}
.tg-toast.is-bad{background:linear-gradient(180deg,#b91c1c,#7f1d1d);}

@keyframes tgIn{from{opacity:0;transform:translateY(6px) scale(.96);}
                to{opacity:1;transform:none;}}
@keyframes tgPulse{0%,100%{opacity:1;}50%{opacity:.5;}}
@keyframes tgLand{0%{transform:scale(1.1);box-shadow:0 0 0 6px rgba(37,99,235,.35);}
                  60%{transform:scale(1);box-shadow:0 0 0 10px rgba(37,99,235,0);}
                  100%{transform:none;}}
@media (prefers-reduced-motion: reduce){
  .tg-bar,.tg-bar:hover,.tg-seg-btn:hover,.tg-more:hover,.tg-count:hover{
    transform:none;animation:none;}
  .tg-bar.is-saving,.tg-bar.is-moved{animation:none;}
  .tg-toast{transition:opacity .01s;}
}

/* ---- Workload module top bar (templates/workload/_nav.html) ---- */
.wl-tabs { display:flex; flex-wrap:wrap; gap:.35rem; padding:.35rem;
    border-radius:.85rem; background:#eef2f9; border:1px solid #dde4f0;
    box-shadow:inset 0 1px 2px rgba(15,23,42,0.04); }
.wl-tab { display:inline-flex; align-items:center; gap:.45rem;
    padding:.5rem 1rem; border-radius:.6rem; font-size:.875rem; font-weight:600;
    color:#475569; text-decoration:none; white-space:nowrap;
    transition:background .15s ease, color .15s ease, box-shadow .15s ease; }
.wl-tab i { font-size:1rem; opacity:.8; }
.wl-tab:hover { background:#fff; color:#1e3a8a; }
.wl-tab.is-on { background:linear-gradient(135deg,#1e3a8a,#2563eb); color:#fff;
    box-shadow:0 3px 10px rgba(30,58,138,.30); }
.wl-tab.is-on i { opacity:1; }
.wl-tab:focus-visible { outline:2px solid #2563eb; outline-offset:2px; }

/* ---- "set aside": what a paused project took off this screen ---- */
.wl-aside{display:flex;align-items:center;flex-wrap:wrap;gap:.6rem;
  margin-bottom:1rem;padding:.6rem .9rem;border-radius:12px;font-size:.8rem;
  color:#78350f;background:linear-gradient(180deg,#fffbeb,#fef3c7);
  border:1px solid #fcd34d;box-shadow:0 2px 0 #fde68a,inset 0 1px 0 #fff;}
.wl-aside > i{font-size:1.05rem;color:#d97706;flex:0 0 auto;}
.wl-aside span{flex:1 1 240px;}
.wl-aside-link{ /* light-only: a soft chip that carries its own coloured ink */margin-left:auto;padding:.24rem .7rem;border-radius:8px;
  font-size:.74rem;font-weight:700;color:#78350f;text-decoration:none;
  background:linear-gradient(180deg,#fff,#fde68a);
  box-shadow:0 2px 0 #f59e0b,inset 0 1px 0 #fff;transition:transform .12s ease;}
.wl-aside-link:hover{color:#78350f;transform:translateY(-1px);}
.wl-aside-link:active{transform:translateY(1px);}
.tg-stat.is-done{color:#14532d;background:linear-gradient(180deg,#f0fdf4,#bbf7d0);
  box-shadow:0 2px 0 #86efac,inset 0 1px 0 #fff;}
.tg-stat.is-done b{color:#14532d;}
.tg-key{display:inline-flex;align-items:center;gap:.3rem;font-size:.66rem;font-weight:600;}
.tg-key::before{content:"";width:14px;height:10px;border-radius:3px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.7);}
.tg-key-plain::before{ /* light-only: a legend swatch, beside three coloured ones */background:linear-gradient(180deg,#fff,#dbeafe);border-left:3px solid #2563eb;}
.tg-key-wait::before{background:linear-gradient(180deg,#fffbeb,#fde68a);border-left:3px solid #d97706;}
.tg-key-done::before{background:linear-gradient(180deg,#f0fdf4,#bbf7d0);border-left:3px solid #16a34a;}
.tg-key-late::before{background:linear-gradient(180deg,#ef4444,#b91c1c);border-left:3px solid #7f1d1d;}
.tg-select-wide{max-width:230px;}

/* ---- customer milestones on the team board ---- */
.tg-ms-row td{background:#f8fafc;border-bottom:2px solid #dbe3f0;padding:.25rem .3rem;}
.tg-ms-row td.tg-who{background:#f8fafc;}
.tg-ms-head{display:inline-flex;align-items:center;gap:.35rem;font-size:.66rem;
  font-weight:800;letter-spacing:.03em;text-transform:uppercase;color:#1e3a8a;}
.tg-ms-head i{color:#2563eb;}
.tg-ms-cell{vertical-align:top;}
.tg-ms-cell.is-we{background:repeating-linear-gradient(45deg,
  #f1f5f9 0 6px, #e8eef6 6px 12px);}
.tg-flag{display:flex;align-items:center;gap:.25rem;margin-bottom:2px;
  padding:.14rem .35rem;border-radius:7px;text-decoration:none;
  font-size:.58rem;font-weight:700;color:#fff;
  background:linear-gradient(180deg,#3b82f6,#1d4ed8);
  box-shadow:0 2px 0 #17399c,0 5px 10px -6px rgba(23,57,156,.8),
             inset 0 1px 0 rgba(255,255,255,.35);
  transition:transform .12s ease;}
.tg-flag:hover{color:#fff;transform:translateY(-1px);}
.tg-flag i{font-size:.55rem;opacity:.9;}
.tg-flag b{font-weight:800;letter-spacing:.02em;}
.tg-flag span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;opacity:.85;}
/* the guide: the column the customer's date falls in, all the way down */
.tg td.tg-cell.has-ms{box-shadow:inset -2px 0 0 rgba(37,99,235,.45);}
.tg td.tg-cell.is-now.has-ms{box-shadow:inset 3px 0 0 #2563eb,inset -2px 0 0 rgba(37,99,235,.45);}
.tg-ms-cell.has-ms{box-shadow:inset -2px 0 0 rgba(37,99,235,.45);}
.tg-key-ms::before{background:linear-gradient(180deg,#3b82f6,#1d4ed8);border-left:3px solid #17399c;}


/* The §7.1.5.2.1 suspect window: what the application saw a device measure
   between its last good calibration and a bad one. Set apart from the
   obligations above it because it is evidence, not another question. */
.met-window { border-left: 3px solid var(--danger); padding: .35rem .6rem;
  background: color-mix(in srgb, var(--danger) 6%, transparent);
  border-radius: 0 8px 8px 0; color: var(--ink-soft); }

/* A repeat whose documents were never changed. Set apart from the repeat
   itself because it is a different, worse fact: the first says it happened
   again, this one says nothing was done about it the last time. */
.cmb-gap { margin-top: .3rem; padding: .3rem .55rem; border-radius: 8px;
  color: var(--danger);
  background: color-mix(in srgb, var(--danger) 8%, transparent);
  border-left: 3px solid var(--danger); }

/* ============================================================ account page */
/* The account menu rendered as a page, for the sidebar shell — where a
   dropdown anchored to the bottom of a full-height fixed column has nowhere to
   open (measured: 562px below the fold, 55px off the left edge).

   It reuses the dropdown's own markup rather than a second copy, so these
   rules re-dress `.dropdown-item` and `.dropdown-divider` instead of replacing
   them. Everything is token-driven, so Midnight comes for free. */
.acct-page { max-width: 640px; margin: 0 auto; }
.acct-head {
  display: flex; align-items: center; gap: .85rem; margin-bottom: 1rem;
  padding: 1rem 1.1rem; border-radius: 14px;
  background: var(--card); border: 1px solid var(--line);
  box-shadow: 0 1px 2px rgba(15, 23, 42, .04);
}
.acct-avatar { width: 46px; height: 46px; font-size: 1rem; flex: 0 0 auto; }
.acct-name { font-size: 1.12rem; font-weight: 700; margin: 0; color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.acct-sub { font-size: .82rem; color: var(--muted); }

.acct-menu {
  margin: 0; padding: .35rem 0; border-radius: 14px;
  background: var(--card); border: 1px solid var(--line); overflow: hidden;
  box-shadow: 0 1px 2px rgba(15, 23, 42, .04);
}
/* A row on a page is a touch target, not a menu line: bigger, and the whole
   width is clickable. */
.acct-menu .dropdown-item {
  display: flex; align-items: center; width: 100%;
  padding: .72rem 1.05rem; font-size: .92rem; color: var(--ink);
  border: 0; background: none; text-align: left; white-space: normal;
}
.acct-menu .dropdown-item:hover, .acct-menu .dropdown-item:focus-visible {
  background: var(--accent-soft, rgba(37, 99, 235, .07)); color: var(--ink);
}
.acct-menu .dropdown-item i { font-size: 1rem; opacity: .75; }
/* A chevron says the row goes somewhere; the sign-out button is not a link. */
.acct-menu li > a.dropdown-item::after {
  content: "\f285"; font-family: bootstrap-icons; margin-left: auto;
  font-size: .72rem; opacity: .35;
}
.acct-menu .dropdown-divider {
  margin: .25rem 0; border-top: 1px solid var(--line); opacity: 1;
}
/* The three preference blocks (navigation, theme, language) keep their own
   controls; they only need room to breathe on a page. */
.acct-menu > li.px-3 { padding: .7rem 1.05rem !important; }
.acct-menu .theme-switch { gap: .4rem; }
.acct-menu .theme-opt { padding: .45rem .7rem; font-size: .85rem; }
.acct-menu .lang-select { max-width: 320px; }
/* The identity line is the page header here, so it does not repeat. */
.acct-menu > li:first-child { display: none; }

/* ========================================================= value stream map */
/* Rother & Shook's form, drawn from geometry computed in apps/lean/vsm.py.
   Tokens first so Midnight is a re-tint rather than a second stylesheet. */
.vsm-wrap {
  --vsm-ink: var(--ink); --vsm-line: var(--line); --vsm-muted: var(--muted);
  --vsm-paper: var(--card);
  --vsm-va: #16a34a;            /* value-adding: the dropped rungs */
  --vsm-nva: #f59e0b;           /* waiting: the raised ones, and most of them */
  --vsm-neck: #dc2626;          /* over takt */
  --vsm-part: #2563eb;
  --vsm-push-bg: rgba(148, 163, 184, .18);
  --vsm-push-fg: rgba(100, 116, 139, .85);
  --vsm-info: #6366f1;
  --vsm-stock: #dc2626;          /* the stock triangles: filled, and loud */
  --vsm-plant: #eff6ff;
  --vsm-plant-line: #93c5fd;
  --vsm-lorry: #1e40af;
  border: 1px solid var(--line); border-radius: 14px;
  background: var(--card); overflow: hidden; margin-bottom: 1rem;
}
:root[data-theme="midnight"] .vsm-wrap {
  --vsm-va: #4ade80; --vsm-nva: #fbbf24; --vsm-neck: #f87171;
  --vsm-part: #60a5fa; --vsm-info: #4f46e5;
  --vsm-stock: #b91c1c; --vsm-plant: rgba(37, 99, 235, .14);
  --vsm-plant-line: #3b82f6; --vsm-lorry: #3b82f6;
  --vsm-push-bg: rgba(148, 163, 184, .12);
  --vsm-push-fg: rgba(148, 163, 184, .6);
}
.vsm-bar {
  display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
  padding: .55rem .9rem; border-bottom: 1px solid var(--line);
  font-size: .74rem; color: var(--muted);
}
.vsm-legend { display: inline-flex; align-items: center; gap: .35rem; }
.vsm-key { width: 14px; height: 4px; border-radius: 2px; display: inline-block; }
.vsm-key-va { background: var(--vsm-va); }
.vsm-key-nva { background: var(--vsm-nva); }
.vsm-key-neck { background: var(--vsm-neck); }
.vsm-play {
  margin-left: auto; border: 1px solid var(--line); background: transparent;
  color: var(--muted); border-radius: 8px; padding: .2rem .6rem;
  font-size: .72rem; display: inline-flex; align-items: center; gap: .3rem;
}
.vsm-play:hover { color: var(--ink); }
/* A map is wide by nature. It scrolls in its own box; the page never does. */
.vsm-scroll { overflow-x: auto; overflow-y: hidden; }
/* Natural size, and it SCROLLS rather than shrinking.
   Two mistakes were made here in order. `width: 100%` stretched a 626-unit map
   across a 1450px card and scaled every glyph with it. Replacing that with
   `max-width: 100%` fixed the small maps and broke the big ones the other way:
   a ten-step stream is 3164 units wide, squeezed into 1430px it renders at 45%,
   and the data boxes — which are the whole reason for the map — become
   unreadable. A drawing nobody can read is not a smaller drawing, it is a
   missing one. So it keeps its size and the container scrolls, the way the
   FMEA worksheet and the control-plan grid already do, with a Fit control for
   when somebody wants the shape rather than the numbers. */
.vsm-svg { display: block; max-width: none; height: auto; }
.vsm-wrap.is-fit .vsm-svg { max-width: 100%; }
.vsm-scroll { scrollbar-width: thin; }

/* ---- information flow ---------------------------------------------------- */
/* Filled and shadowed: on the standard form the scheduling box is the
   loudest thing above the line, because it is what causes the piles below. */
.vsm-ctrl { fill: var(--vsm-info); stroke: none; filter: url(#vsm-soft); }
.vsm-ctrl-t { font-size: 12.5px; font-weight: 800; fill: #fff; text-anchor: middle;
  letter-spacing: .02em; }
.vsm-ctrl-s { font-size: 10.5px; fill: rgba(255, 255, 255, .82); text-anchor: middle; }
.vsm-iflow { color: var(--vsm-info); }
/* Electronic information is the zig-zag in the standard; a dash carries the
   same "not a physical thing" meaning at this scale and stays legible. */
.vsm-ielec, .vsm-isched {
  fill: none; stroke: var(--vsm-info); stroke-width: 1.1;
  stroke-dasharray: 5 4; opacity: .75;
}
.vsm-isched { opacity: .38; }
.vsm-ilabel { font-size: 10px; fill: var(--vsm-info); text-anchor: middle;
  font-weight: 600; }
.vsm-ilabel-c { fill: var(--vsm-muted); }

/* ---- plants -------------------------------------------------------------- */
.vsm-plant-b { fill: var(--vsm-plant); stroke: var(--vsm-plant-line); stroke-width: 1.4; }
.vsm-roof-l { fill: none; stroke: var(--vsm-plant-line); stroke-width: 1.4; }
.vsm-plant-t { font-size: 12px; font-weight: 700; fill: var(--vsm-ink); text-anchor: middle; }
.vsm-plant-s { font-size: 9.5px; fill: var(--vsm-muted); text-anchor: middle; }

/* ---- material flow ------------------------------------------------------- */
/* Filled, not outlined. On a drawn map the stock triangles are the first
   thing you see, and that is the point of them. */
.vsm-tri { fill: var(--vsm-stock); stroke: none; }
.vsm-tri-i { font-size: 12px; font-weight: 800; fill: #fff; text-anchor: middle; }
.vsm-tri-q { font-size: 11px; font-weight: 700; fill: var(--vsm-ink); text-anchor: middle; }
.vsm-tri-d { font-size: 10.5px; fill: var(--vsm-nva); text-anchor: end; font-weight: 700; }
.vsm-arrow { color: var(--vsm-line); }
.vsm-arrow line { stroke: var(--vsm-line); stroke-width: 1.6; }
.vsm-arrow-t { font-size: 9.5px; fill: var(--vsm-muted); }

.vsm-step-b { fill: var(--vsm-paper); stroke: var(--vsm-line); stroke-width: 1.6; }
.vsm-step-head { fill: var(--c, #64748b); }
.vsm-step-t { font-size: 12px; font-weight: 700; fill: #fff; text-anchor: middle;
  letter-spacing: .01em; }
.vsm-op-n { font-size: 11px; fill: var(--vsm-muted); font-weight: 600; text-anchor: middle; }
.vsm-step.is-neck .vsm-step-b { stroke: var(--vsm-neck); stroke-width: 2.2; }
.vsm-load { font-size: 10px; font-weight: 700; fill: var(--vsm-muted); text-anchor: end; }
.vsm-step.is-neck .vsm-load { fill: var(--vsm-neck); }
.vsm-op circle, .vsm-op path { fill: var(--vsm-muted); }
.vsm-op-n { font-size: 10px; fill: var(--vsm-muted); font-weight: 600; }
.vsm-data { fill: none; stroke: var(--vsm-line); stroke-width: 1.2; }
.vsm-d { font-size: 10px; fill: var(--vsm-ink); }
.vsm-truck { fill: var(--vsm-lorry); stroke: none; }
.vsm-wheel { fill: var(--vsm-lorry); }
.vsm-ship-t { font-size: 9.5px; fill: var(--vsm-muted); text-anchor: middle; }

/* ---- the lead-time ladder ------------------------------------------------ */
.vsm-l-path { fill: none; stroke: var(--vsm-line); stroke-width: 1.2; }
.vsm-l { stroke-width: 3; stroke-linecap: butt; }
.vsm-l-wait { stroke: var(--vsm-nva); }
.vsm-l-work { stroke: var(--vsm-va); }
.vsm-l-t { font-size: 10px; font-weight: 600; }
.vsm-l-t-wait { fill: var(--vsm-nva); }
.vsm-l-t-work { fill: var(--vsm-va); }
.vsm-totals-b { fill: var(--vsm-paper); stroke: var(--vsm-line); stroke-width: 1.4; }
.vsm-sum { font-size: 11px; font-weight: 600; fill: var(--vsm-muted); text-anchor: start; }
.vsm-sum-v { font-weight: 800; fill: var(--vsm-nva); font-size: 12px; }
.vsm-sum-va .vsm-sum-v { fill: var(--vsm-va); }
.vsm-sum-pce { font-weight: 700; fill: var(--vsm-va); }

/* ---- kaizen bursts ------------------------------------------------------- */
.vsm-burst { fill: rgba(250, 204, 21, .9); stroke: #a16207; stroke-width: 1; }
/* A burst nobody owns is an outline; one wired to an Improvement is filled.
   The difference between a wish and a commitment should be visible from across
   the room, which is where these maps are usually read. */
.vsm-burst:not(.is-owned) { fill: none; stroke-dasharray: 3 2; }

/* ---- the motion ---------------------------------------------------------- */
/* Each station cycles its OWN part at its OWN pace, rather than one part being
   handed along. That is the truthful thing to animate: the dwell is each step's
   share of the total cycle time, so the slow station visibly crawls while the
   quick ones flick past, and line balance becomes something you see instead of
   something you read off a table. The queues are NOT played to scale — see the
   note in vsm.py; the ladder carries that truth to the day. */
@keyframes vsm-run {
  0%   { transform: translateX(0);     opacity: 0; }
  12%  { opacity: 1; }
  88%  { opacity: 1; }
  100% { transform: translateX(150px); opacity: 0; }
}
@keyframes vsm-swell {
  0%, 100% { opacity: .55; transform: translateY(0); }
  50%      { opacity: 1;   transform: translateY(-2px); }
}
.vsm-part { fill: var(--vsm-part); opacity: 0; }
.vsm-step.is-neck .vsm-part { fill: var(--vsm-neck); }
@media (prefers-reduced-motion: no-preference) {
  .vsm-part {
    animation: vsm-run var(--dwell, 2s) linear var(--enter, 0s) infinite;
  }
  /* Only the queues in front of a station that cannot keep pace move. A
     drawing where everything pulses says nothing. */
  .vsm-inv.is-growing .vsm-tri { animation: vsm-swell 2.4s ease-in-out infinite; }
}
.vsm-wrap.is-paused .vsm-part,
.vsm-wrap.is-paused .vsm-inv .vsm-tri { animation-play-state: paused; }

/* ---- the map's legend ----------------------------------------------------- */
/* Swatches are drawn with the map's own classes inside a `.vsm-wrap`, so they
   inherit the same tokens and cannot drift from the drawing they explain. */
.vsm-legend.fx-card { overflow: visible; }
.lg-row {
  display: grid; grid-template-columns: 64px 1fr; gap: .7rem;
  align-items: start; padding: .5rem 0;
  border-bottom: 1px dashed var(--line);
}
.lg-row:last-child { border-bottom: 0; }
.lg-sw { display: flex; align-items: center; justify-content: center; }
.lg-svg { width: 54px; height: 34px; overflow: visible; }
.lg-term { font-size: .84rem; font-weight: 700; color: var(--ink); }
.lg-what { font-size: .8rem; color: var(--muted); line-height: 1.45; }
.lg-calc { font-size: .78rem; margin-top: .15rem; }
.lg-f { font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  color: var(--ink-soft); }
.lg-tick { stroke: var(--vsm-line); stroke-width: 1.6; stroke-linecap: round; }
.lg-line { stroke: var(--vsm-line); stroke-width: 1.8; }
.lg-shelf { fill: none; stroke: var(--vsm-line); stroke-width: 1.4; }
.lg-ball { fill: none; stroke: var(--vsm-part); stroke-width: 1.8; }
.lg-t { font-size: 7.5px; fill: var(--vsm-muted); font-weight: 700; }
/* The legend's dot does not run: it is a picture of the thing, not the thing. */
.lg-part { opacity: 1 !important; animation: none !important; }

/* ================================================================ 5S board */
/* Three bands and no amber-by-default: "never audited" is its own colour,
   because an area nobody has looked at must not sit next to one that is
   genuinely bad. */
.fives-matrix th { font-size: .74rem; text-transform: uppercase;
  letter-spacing: .04em; color: var(--muted); }
.fives-jp { font-size: .66rem; font-weight: 500; color: var(--muted);
  text-transform: none; letter-spacing: 0; }
.fives-cell {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 42px; padding: .2rem .45rem; border-radius: 8px;
  font-size: .82rem; font-weight: 700;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .35);
}
.fives-cell.fives-lg { min-width: 56px; font-size: .9rem; padding: .28rem .6rem; }
.fives-ok   { background: #dcfce7; color: #14532d; }
.fives-warn { background: #fef3c7; color: #78350f; }
.fives-bad  { background: #fee2e2; color: #7f1d1d; }
.fives-none { background: var(--surface-2, #eef2f8); color: var(--muted); }
:root[data-theme="midnight"] .fives-ok   { background: rgba(22,163,74,.24); color: #86efac; }
:root[data-theme="midnight"] .fives-warn { background: rgba(245,158,11,.22); color: #fcd34d; }
:root[data-theme="midnight"] .fives-bad  { background: rgba(220,38,38,.24); color: #fca5a5; }
:root[data-theme="midnight"] .fives-none { background: rgba(148,163,184,.14); color: var(--muted); }

/* the five S as a staircase — they are one tool, in order: an area cannot
   sustain what it has not standardised, and standardising an unsorted area
   standardises the clutter */
.fives-stair {
  display: grid; grid-template-columns: repeat(5, 1fr); gap: .3rem;
  align-items: end; height: 92px;
}
.fives-step {
  position: relative; height: var(--h, 8%); min-height: 20px;
  border-radius: 6px 6px 3px 3px;
  display: flex; flex-direction: column; justify-content: flex-start;
  align-items: center; padding-top: .12rem;
  /* A lit face and a stacked shadow: the same extrusion the KPI tiles use, so
     the module reads as one surface rather than a chart pasted in. */
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5),
              0 2px 0 -1px rgba(2, 6, 23, .28),
              0 6px 14px -8px rgba(2, 6, 23, .4);
  transition: height .35s cubic-bezier(.22, 1, .36, 1);
}
.fives-step.fives-ok   { background: linear-gradient(180deg, #4ade80, #16a34a); }
.fives-step.fives-warn { background: linear-gradient(180deg, #fbbf24, #d97706); }
.fives-step.fives-bad  { background: linear-gradient(180deg, #f87171, #dc2626); }
.fives-step.fives-none { background: linear-gradient(180deg, #cbd5e1, #94a3b8); }
.fives-step-v { font-size: .66rem; font-weight: 800; color: #fff;
  text-shadow: 0 1px 1px rgba(0, 0, 0, .3); }
.fives-step-l { position: absolute; bottom: -1.05rem; font-size: .6rem;
  color: var(--muted); white-space: nowrap; }
@media (prefers-reduced-motion: reduce) { .fives-step { transition: none; } }

/* the checklist reference */
.fives-sec { margin-bottom: .6rem; }
.fives-sec-h { font-size: .78rem; font-weight: 700; color: var(--ink);
  display: flex; align-items: center; gap: .35rem; margin-bottom: .2rem; }
.fives-dot { width: 9px; height: 9px; border-radius: 50%; display: inline-block; }
.fives-dot-sort { background: #dc2626; }
.fives-dot-set { background: #2563eb; }
.fives-dot-shine { background: #0891b2; }
.fives-dot-standardise { background: #7c3aed; }
.fives-dot-sustain { background: #16a34a; }
.fives-qs { list-style: none; margin: 0; padding-left: .9rem; }
.fives-qs li { font-size: .78rem; color: var(--muted); line-height: 1.5;
  position: relative; padding-left: .5rem; }
.fives-qs li::before { content: "·"; position: absolute; left: -.3rem;
  color: var(--line); font-weight: 700; }
.fives-from {
  font-size: .6rem; font-weight: 800; padding: 0 .25rem; border-radius: 4px;
  background: var(--surface-2, #eef2f8); color: var(--muted); margin-left: .2rem;
}
/* The active tab in the ribbon. */
.docbtn.is-on { background: var(--accent-soft, #eaf1fe);
  border-color: var(--accent, #2563eb); color: var(--ink); }

/* ── 5S: the tool's own pictures ──────────────────────────────────────────
   5S is the one method whose whole technique is visual, so the module draws
   it: a live wheel filled from the plant's own scores, and a line drawing per
   S used everywhere the S is named. Colours match `.fives-dot-*` above and a
   test pins that they still do. */
.s5-wheel { display: flex; justify-content: center; }
.s5-wheel svg { width: 100%; max-width: 330px; height: auto; overflow: visible; }
.s5-track { fill: rgba(148,163,184,.16); }
.s5-fill  { fill: var(--c); transform-box: view-box; transform-origin: 150px 106px;
            animation: s5Bloom .62s cubic-bezier(.2,.9,.3,1.2) both; }
@keyframes s5Bloom { from { transform: scale(.3); opacity: 0; } to { transform: scale(1); opacity: 1; } }
.s5-seg { cursor: default; }
.s5-seg:hover .s5-fill { filter: brightness(1.1) saturate(1.1); }
.s5-seg:hover .s5-track { fill: rgba(148,163,184,.3); }
.s5-hole  { fill: var(--card, #fff); }
.s5-wheel-lg svg { max-width: 380px; }
.s5-mid   { font: 800 22px/1 Inter, system-ui, sans-serif; fill: var(--ink); letter-spacing: -.02em; }
.s5-mid-v { font: 700 13px/1 Inter, system-ui, sans-serif; fill: var(--muted); }
.s5-lab-n { font: 700 11.5px/1 Inter, system-ui, sans-serif; fill: var(--ink); }
.s5-lab-j { font: 500 9.5px/1 Inter, system-ui, sans-serif; fill: var(--muted); }
.s5-lab-v { font: 800 12px/1 Inter, system-ui, sans-serif; fill: var(--c); }
.s5-lab-m { font-weight: 600; font-size: 9px; fill: var(--muted); }
:root[data-theme="midnight"] .s5-track { fill: rgba(148,163,184,.13); }

/* The glyphs. One drawing per S, referenced by `<use>`, inheriting the S's
   own colour from wherever it is placed. */
.s5-glyph { width: 1.25em; height: 1.25em; vertical-align: -.22em; flex: 0 0 auto; }
.s5-glyph-md { width: 1.15rem; height: 1.15rem; }
.s5-glyph-lg { width: 2.1rem; height: 2.1rem; }
.s5-c-sort        { color: #dc2626; }
.s5-c-set         { color: #2563eb; }
.s5-c-shine       { color: #0891b2; }
.s5-c-standardise { color: #7c3aed; }
.s5-c-sustain     { color: #16a34a; }

/* The poster: the five S as the plant knows them, above the work. */
.s5-poster { display: grid; gap: .6rem; grid-template-columns: repeat(5, 1fr); }
@media (max-width: 991px) { .s5-poster { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 575px) { .s5-poster { grid-template-columns: 1fr; } }
.s5-card { position: relative; overflow: hidden; border-radius: .7rem; padding: .7rem .75rem .65rem;
           background: var(--card, #fff); border: 1px solid var(--line);
           box-shadow: 0 1px 2px rgba(15,23,42,.05); }
.s5-card::before { content: ""; position: absolute; inset: 0 auto 0 0; width: 4px; background: var(--c); }
.s5-card-h { display: flex; align-items: center; gap: .5rem; margin-bottom: .3rem; }
.s5-card-n { font-size: .82rem; font-weight: 800; color: var(--ink); line-height: 1.1; }
.s5-card-j { font-size: .66rem; font-weight: 500; color: var(--muted); }
.s5-card-g { font-size: .72rem; color: var(--muted); line-height: 1.45; }
.s5-card-num { position: absolute; right: .5rem; top: .3rem; font-size: 1.6rem; font-weight: 800;
               color: var(--c); opacity: .13; line-height: 1; }

/* The staircase steps carry their own drawing above the bar. */
.fives-step-g { position: absolute; top: -1.35rem; }
.fives-stair { padding-top: 1.35rem; }

/* The red-tag form drawn as the thing it is: a tag, with a hole and a string.
   Somebody filling this in has one in their hand. */
.s5-tagcard { position: relative; border: 2px solid #dc2626; border-radius: .6rem;
              background: linear-gradient(180deg, rgba(220,38,38,.07), transparent 42%); }
.s5-tagcard::before { content: ""; position: absolute; left: 50%; top: -14px; width: 2px; height: 14px;
                      background: #dc2626; opacity: .55; }
.s5-tagcard::after { content: ""; position: absolute; left: 50%; top: 8px; width: 10px; height: 10px;
                     margin-left: -5px; border: 2px solid #dc2626; border-radius: 50%;
                     background: var(--bg, #f8fafc); }
.s5-tagcard .card-header { border-bottom: 1px dashed rgba(220,38,38,.4); background: transparent;
                           padding-top: 1.3rem; text-align: center; color: #b91c1c; font-weight: 800;
                           letter-spacing: .06em; text-transform: uppercase; font-size: .78rem; }
:root[data-theme="midnight"] .s5-tagcard .card-header { color: #fca5a5; }

@media (prefers-reduced-motion: reduce) { .s5-fill { animation: none; } }
.s5-wheel-sm svg { max-width: 108px; }
.s5-target { fill: none; stroke: #16a34a; stroke-width: 1.4; stroke-dasharray: 4 3.5; opacity: .75; }

/* 5S: the photograph of a non-conformity, on the row it belongs to. */
.s5-ph { position: relative; flex: 0 0 auto; }
.s5-ph-img { width: 42px; height: 42px; object-fit: cover; border-radius: 7px;
             border: 1px solid var(--line); display: block; }
.s5-ph-x { position: absolute; top: -6px; right: -6px; width: 18px; height: 18px;
           border-radius: 50%; border: 0; background: #dc2626; color: #fff;
           font-size: .72rem; line-height: 1; padding: 0; cursor: pointer; }
.s5-ph-add { width: 42px; height: 42px; border-radius: 7px; cursor: pointer;
             border: 1px dashed var(--line-2, #cbd5e1); color: var(--muted);
             display: inline-flex; align-items: center; justify-content: center;
             margin: 0; transition: border-color .15s, color .15s; }
.s5-ph-add:hover { border-color: var(--accent, #2563eb); color: var(--accent, #2563eb); }

/* 5S: the small controls on a checklist row. Kept faint until the row is
   hovered — the sheet is read far more often than it is edited. */
.fives-qedit { opacity: 0; transition: opacity .12s; margin-left: .35rem; white-space: nowrap; }
.fives-qs li:hover .fives-qedit, .fives-qedit:focus-within { opacity: 1; }
@media (hover: none) { .fives-qedit { opacity: .6; } }

/* 5S: the editable sheet. The S bands separate it without a second table. */
.fives-edit-head td { background: var(--surface-2, #f1f5f9); font-size: .8rem;
                      padding-top: .5rem; padding-bottom: .5rem; }
.fives-edit textarea { min-height: 2.6rem; resize: vertical; }

/* Every textarea is sized by its own content (see `growCell` in app.js).
   The CSS half: no scrollbar to fight the measurement, a floor so an empty
   box is still a box, and the user's drag-handle left working. */
textarea:not([data-fixed-height]) {
  overflow-y: hidden;
  min-height: 2.2rem;
  resize: vertical;
}
/* In a grid cell the floor is one line: a table of thirty rows must not open
   at three times its height because every cell reserved room it is not using. */
.table textarea:not([data-fixed-height]),
td textarea:not([data-fixed-height]) { min-height: 1.9rem; }

/* ── the levelling box ─────────────────────────────────────────────────────
   Slots in a row, read left to right, because that is the order the plant
   makes them in. Wrapping is deliberate: a box that scrolls sideways hides
   the second half of the pattern, and the second half is where the
   alternation either holds or does not. */
.hj-box {
  display: flex; flex-wrap: wrap; gap: 4px;
}
.hj-slot {
  flex: 0 0 auto; min-width: 62px;
  display: flex; flex-direction: column; align-items: center;
  padding: .3rem .35rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface-2, #eef2f8);
  line-height: 1.15;
}
.hj-slot .hj-n {
  font-size: .62rem; letter-spacing: .04em;
  color: var(--muted);
}
.hj-slot .hj-p {
  font-size: .74rem; font-weight: 600;
  max-width: 78px; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap;
}
/* The tail's slots are kept, not filled — drawn as an outline so an empty
   slot reads as reserved rather than as a gap somebody forgot. */
.hj-slot.hj-free {
  background: transparent;
  border-style: dashed;
}
.hj-slot.hj-free .hj-p { color: var(--muted); font-weight: 500; }
:root[data-theme="midnight"] .hj-slot { background: rgba(148,163,184,.12); }

/* ── the spaghetti canvas ──────────────────────────────────────────────────
   The SVG sits exactly on the plan, and its viewBox is width-relative on
   both axes so a diagonal measures correctly (see apps/lean/spaghetti.py).
   `preserveAspectRatio="none"` plus a box of the image's own shape means the
   two scales are equal anyway — it is belt and braces against rounding. */
.sp-stage { position: relative; display: inline-block; max-width: 100%; }
.sp-stage img { display: block; max-width: 100%; height: auto; }
.sp-stage svg {
  position: absolute; inset: 0; width: 100%; height: 100%;
  cursor: crosshair; touch-action: none;
}
.sp-swatch {
  display: inline-block; width: 12px; height: 12px; border-radius: 3px;
  background: var(--muted);
}

/* ── the Hoshin X-matrix ───────────────────────────────────────────────────
   Four correlation blocks and four legs, laid out so every mark lines up
   with what it refers to. The traditional printed diamond does not: getting
   its corners to align needs the legs drawn twice, and two copies of a leg
   is two records of one thing. See the comment in hoshin.html. */
/* `safe center` and not plain `center`: centred content that overflows is
   clipped at BOTH ends and the left half cannot be scrolled back to — the
   same trap the Ascent pyramid hit, and a wide matrix overflows readily. */
.hx-wrap { overflow-x: auto; display: flex; justify-content: safe center; }
.hx {
  display: grid;
  grid-template-columns: max-content minmax(0, max-content) max-content;
  gap: 4px 10px;
  align-items: start;
  min-width: max-content;
}
.hx-head { display: flex; gap: 2px; align-items: flex-end; }
.hx-head-s { justify-content: flex-end; }
.hx-title {
  align-self: end; text-align: center; font-size: .7rem;
  color: var(--muted); white-space: nowrap; padding-bottom: .2rem;
}
.hx-corner { display: flex; flex-direction: column; gap: 2px; }
.hx-corner.hx-right { align-items: flex-end; }
.hx-row { display: flex; gap: 2px; height: 20px; align-items: center; }
.hx-cell {
  width: 18px; height: 18px; border-radius: 3px;
  background: var(--card, #fff);
  border: 1px solid var(--line);
}
/* A link somebody decided: solid. */
.hx-cell.on { background: var(--accent, #2563eb); border-color: transparent; }
/* Derived: hollow, because a correlation that falls out of the other three
   is not the same claim as one a person made. */
.hx-cell.derived {
  background: transparent;
  border: 2px solid var(--accent, #2563eb);
}
.hx-vlabel {
  width: 18px; min-height: 118px;
  display: flex; align-items: flex-end; justify-content: center;
  font-size: .68rem; line-height: 1;
}
.hx-vlabel span {
  writing-mode: vertical-rl; transform: rotate(180deg);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  max-height: 118px;
}
.hx-break span { font-weight: 600; }
.hx-mid { display: flex; flex-direction: column; gap: 2px; }
.hx-mid-people { border-top: 1px dashed var(--line); padding-top: 4px; }
.hx-corner + .hx-mid-people { }
.hx-item {
  height: 20px; display: flex; align-items: center; gap: .4rem;
  font-size: .74rem; line-height: 1; white-space: nowrap;
  padding: 0 .5rem; justify-content: center;
}
.hx-mid-item {
  background: var(--surface-2, #eef2f8); border-radius: 4px;
}
.hx-item .hx-t { overflow: hidden; text-overflow: ellipsis; max-width: 24rem; }
.hx-pct { color: var(--muted); font-variant-numeric: tabular-nums; }
.hx-empty { font-size: .72rem; color: var(--muted); padding: 0 .4rem; }

/* A component chip that can be renamed in place: the input borrows the
   chip's own colour and weight so the strip does not turn into a form. */
.pf-comp-in {
  border: none; background: transparent; padding: 0 .15rem;
  font: inherit; color: inherit; min-width: 3rem;
  border-bottom: 1px dashed currentColor;
}
.pf-comp-in:focus { outline: none; background: var(--card, #fff); }

/* ── the lean route ────────────────────────────────────────────────────────
   Nineteen tools on one screen, and the first version of this drew them as
   nineteen identical grey text blocks. A person hunting for SMED read all
   nineteen labels every time — which is the definition of a screen that is
   hard to use, and the reason it was rebuilt.

   Three things carry the redesign and each is doing a job:

   * The ORDER is the content, so the five stages hang off a SPINE with a
     numbered node and a progress ring. A tool list that reads as a menu is
     one a plant picks from, and picking heijunka on a Monday morning is how
     the 70-90% fail. See apps/lean/house.py.
   * Every tool has a FACE — an extruded icon in a fixed colour
     (catalogue.TOOL_FACE). The eye finds a shape before it reads a word.
     The label always stays, so the colour is never the only thing carrying
     the meaning.
   * STATE is the rail and the icon's lighting, never the tile's own
     surface: a band of twelve coloured tiles reads as twelve warnings.

   Motion is on LOAD and on HOVER, never at rest. Nineteen idle animations
   on a front door is a battery bill, and all of it sits behind
   prefers-reduced-motion. */

.ln-route { position: relative; }
/* The spine. Drawn behind the bands so a stage's node sits on it. */
.ln-route::before {
  content: ""; position: absolute; left: 21px; top: 26px; bottom: 26px;
  width: 2px; border-radius: 2px;
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--accent) 55%, transparent),
    color-mix(in srgb, var(--accent) 18%, transparent));
  z-index: 0;
}
@media (max-width: 575.98px) { .ln-route::before { display: none; } }

.ln-stage { position: relative; margin: 0 0 .85rem 0; padding-left: 54px; }
@media (max-width: 575.98px) { .ln-stage { padding-left: 0; } }

/* The node: a 3-D disc carrying the stage's own icon, with a ring showing
   how much of that stage the plant has actually started. */
.ln-node {
  position: absolute; left: 0; top: 6px; width: 44px; height: 44px;
  border-radius: 50%; z-index: 1;
  display: grid; place-items: center;
  color: #fff; font-size: 1.05rem;
  background:
    radial-gradient(120% 120% at 32% 22%, #6d7ff5 0%, #4f46e5 46%, #3730a3 100%);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, .5),
    inset 0 -6px 10px rgba(0, 0, 0, .28),
    0 3px 0 #312e81, 0 8px 16px rgba(2, 6, 23, .28);
}
.ln-node i { filter: drop-shadow(0 1px 1px rgba(0, 0, 0, .35)); }
.ln-node-ring {
  position: absolute; inset: -6px; border-radius: 50%; pointer-events: none;
  /* --p is the started percentage, set inline from house.route(). */
  background: conic-gradient(var(--ok, #16a34a) calc(var(--p, 0) * 1%),
                             transparent 0);
  -webkit-mask: radial-gradient(closest-side, transparent 78%, #000 79%);
          mask: radial-gradient(closest-side, transparent 78%, #000 79%);
  animation: lnRing .9s cubic-bezier(.2, .8, .3, 1) both;
}
@keyframes lnRing { from { transform: rotate(-90deg) scale(.6); opacity: 0; }
                    to   { transform: none; opacity: 1; } }
.ln-node-n {
  position: absolute; right: -4px; bottom: -4px;
  min-width: 18px; height: 18px; padding: 0 4px; border-radius: 9px;
  background: var(--card, #fff); color: var(--ink);
  border: 1px solid var(--line);
  font-size: .66rem; font-weight: 800; line-height: 16px; text-align: center;
}

.ln-stage-h { display: flex; align-items: center; gap: .6rem;
              flex-wrap: wrap; padding: .35rem 0 .5rem; }
.ln-stage-t { font-weight: 700; font-size: .95rem; letter-spacing: -.01em; }
.ln-stage-b { font-size: .76rem; color: var(--muted); }
/* The counts sit BESIDE the stage they describe, not pushed to the far edge:
   at 1500px `margin-left:auto` put "2 ready" twelve hundred pixels from the
   word Foundation, and nothing that far apart is read as belonging together. */
.ln-stage-c { display: flex; gap: .3rem; flex-wrap: wrap; align-items: center; }

.ln-tools {
  display: grid; gap: .55rem;
  grid-template-columns: repeat(auto-fill, minmax(228px, 1fr));
}

/* ── one tool ─────────────────────────────────────────────────────────── */
.ln-tool {
  position: relative; overflow: hidden;
  display: flex; gap: .6rem; align-items: flex-start;
  border: 1px solid var(--line); border-left: 3px solid var(--line);
  border-radius: 12px; padding: .6rem .65rem;
  background: var(--card, #fff);
  transition: transform .16s cubic-bezier(.2, .8, .3, 1),
              box-shadow .16s ease, border-color .16s ease;
  animation: lnRise .42s cubic-bezier(.2, .8, .3, 1) both;
  animation-delay: calc(var(--i, 0) * 26ms);
}
@keyframes lnRise { from { opacity: 0; transform: translateY(10px) scale(.985); }
                    to   { opacity: 1; transform: none; } }
.ln-tool:hover {
  transform: translateY(-3px);
  box-shadow: 0 10px 26px rgba(2, 6, 23, .12);
  border-color: color-mix(in srgb, var(--accent) 35%, var(--line));
}

/* The face. `.ic3d`'s own palette, so the module looks like the rest of the
   product, plus a tilt and a gloss sweep that only run on hover. It is
   pointer-events:none deliberately: a transformed child must never be able
   to take a click away from the link beside it — the App Map's lesson. */
.ln-face {
  position: relative; flex: 0 0 auto; pointer-events: none;
  width: 42px; height: 42px; border-radius: 12px;
  display: grid; place-items: center; color: #fff; font-size: 1.2rem;
  background: linear-gradient(150deg, var(--i1), var(--i2));
  box-shadow:
    inset 0 1.5px 0 rgba(255, 255, 255, .55),
    inset 0 -7px 11px rgba(0, 0, 0, .2),
    0 3px 0 var(--is), 0 7px 14px rgba(2, 6, 23, .22);
  transition: transform .22s cubic-bezier(.2, .8, .3, 1),
              box-shadow .22s ease, filter .22s ease;
}
.ln-face::after {
  content: ""; position: absolute; inset: 3px 3px 52% 3px;
  border-radius: 9px 9px 42% 42%;
  background: linear-gradient(180deg, rgba(255, 255, 255, .45), rgba(255, 255, 255, 0));
}
/* The sweep: a highlight that crosses the face once when the tile is
   hovered. Transform-only, so it costs the compositor and not the CPU. */
.ln-face::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  background: linear-gradient(105deg, transparent 38%,
              rgba(255, 255, 255, .5) 50%, transparent 62%);
  transform: translateX(-120%);
}
.ln-tool:hover .ln-face::before { animation: lnSweep .62s ease-out; }
@keyframes lnSweep { to { transform: translateX(120%); } }
.ln-tool:hover .ln-face {
  transform: perspective(420px) rotateX(-14deg) rotateY(9deg) translateY(-3px);
  box-shadow:
    inset 0 1.5px 0 rgba(255, 255, 255, .6),
    inset 0 -7px 11px rgba(0, 0, 0, .2),
    0 6px 0 var(--is), 0 14px 22px rgba(2, 6, 23, .3);
}
.ln-face i { position: relative; z-index: 1;
             filter: drop-shadow(0 1px 1px rgba(0, 0, 0, .3)); }
.ln-face-indigo  { --i1: #818cf8; --i2: #4f46e5; --is: #3730a3; }
.ln-face-teal    { --i1: #2dd4bf; --i2: #0d9488; --is: #115e59; }
.ln-face-emerald { --i1: #34d399; --i2: #059669; --is: #065f46; }
.ln-face-amber   { --i1: #fbbf24; --i2: #d97706; --is: #92400e; }
.ln-face-rose    { --i1: #fb7185; --i2: #e11d48; --is: #9f1239; }
.ln-face-slate   { --i1: #94a3b8; --i2: #475569; --is: #334155; }
.ln-face-violet  { --i1: #a78bfa; --i2: #7c3aed; --is: #5b21b6; }

/* The grid makes every tile as tall as the tallest in its row, so the join
   chip is pushed to the bottom and lines up across the row. Ragged bottoms
   in a grid of nineteen read as a rendering fault rather than as content of
   different lengths. */
.ln-body { min-width: 0; flex: 1 1 auto; display: flex; flex-direction: column; }
.ln-body > .ln-join { margin-top: auto; padding-top: .3rem; }
.ln-tool-h { display: flex; align-items: center; gap: .35rem; }
.ln-name {
  font-weight: 650; font-size: .84rem; text-decoration: none;
  color: var(--ink); line-height: 1.25;
}
.ln-name:hover { color: var(--accent); }
.ln-name.ln-none { color: var(--muted); cursor: help; }

/* The whole tile is the way in, not the few pixels of its name.
   Measured before this existed: the link on the 5S tile was 13x12px inside a
   115x106 tile — one per cent of it — so a tap in the middle hit the `div`
   and did nothing, and whether a tool "worked" came down to how long its name
   happened to be. `Visual management` was ten per cent and felt fine;
   `5S` and `TPM` did not.

   A stretched pseudo-element rather than wrapping the card in an anchor,
   because the card already holds its own interactive parts and an `<a>`
   inside an `<a>` is not valid HTML. */
.ln-name::after {
  content: ""; position: absolute; inset: 0; z-index: 0;
}
/* …and those parts stay above it, so the join list still opens on hover and
   the lock and door notes still show their titles. A tile that swallowed
   them would trade one dead target for three. */
.ln-tool > .ln-body > .ln-join,
.ln-tool .ln-door,
.ln-tool .ln-block,
.ln-tool .ln-flag { position: relative; z-index: 1; }
/* A tool the application cannot open yet has no anchor and so no overlay —
   it must not look like a door. */
.ln-tool:has(a.ln-name) { cursor: pointer; }
.ln-n {
  margin-left: auto; flex: 0 0 auto;
  font-size: .68rem; font-weight: 800;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent);
  padding: .05rem .38rem; border-radius: 6px;
}
.ln-sum { font-size: .73rem; color: var(--muted); line-height: 1.35;
          margin-top: .1rem; }

/* State is the rail plus a small mark on the face — never the tile's own
   background, or a stage of twelve reads as twelve warnings. */
.ln-tool.ln-verified { border-left-color: var(--accent, #2563eb); }
.ln-tool.ln-done     { border-left-color: var(--ok, #16a34a); }
.ln-tool.ln-active   { border-left-color: var(--warn, #f59e0b); }
.ln-tool.ln-ready    { border-left-color: color-mix(in srgb, var(--ok) 45%, var(--line)); }
.ln-tool.ln-locked   { border-left-color: var(--line); }
/* Locked is drawn, not hidden. The face goes grey and the card sits back,
   because a tool a plant may not start yet still has to be findable — it is
   the thing the lock is explaining. */
.ln-tool.ln-locked .ln-face { filter: grayscale(1) brightness(.96); }
.ln-tool.ln-locked .ln-name,
.ln-tool.ln-locked .ln-sum { opacity: .78; }
.ln-tool.ln-early { border-left-color: var(--warn, #f59e0b); }

.ln-flag, .ln-block, .ln-door {
  font-size: .68rem; margin-top: .3rem; line-height: 1.3;
  display: flex; gap: .25rem; align-items: flex-start;
}
/* amber-800, the same value `.badge-soft.warn` uses: --warn itself measures
   3.2:1 on white and is a fill colour, not a text one. */
.ln-flag  { color: #b45309; }
[data-theme="midnight"] .ln-flag { color: var(--warn); }
/* One line, with the whole sentence in the title. Printed in full these
   were three and four lines long, which is what left the short tiles in a
   row half empty — and a paragraph on a map is a document. */
.ln-clip {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; cursor: help;
}
.ln-block { color: var(--muted); }
.ln-door  { color: var(--muted); font-style: italic; }

/* What this tool hands to what. Folded to a single chip by default: twelve
   explanations on one screen is a document, not a map. The names appear on
   hover, and the whole sentence is in the title. */
.ln-join { margin-top: .35rem; font-size: .66rem; }
.ln-join-n {
  display: inline-flex; align-items: center; gap: .2rem; cursor: help;
  color: var(--muted); background: var(--surface-2, #f1f5f9);
  border-radius: 5px; padding: .05rem .3rem;
}
.ln-join-list {
  display: flex; flex-wrap: wrap; gap: .22rem; margin-top: .25rem;
  max-height: 0; overflow: hidden; opacity: 0;
  transition: max-height .2s ease, opacity .2s ease;
}
.ln-tool:hover .ln-join-list,
.ln-tool:focus-within .ln-join-list { max-height: 90px; opacity: 1; }
.ln-in, .ln-out {
  padding: .05rem .3rem; border-radius: 4px; white-space: nowrap; cursor: help;
}
.ln-in  { background: color-mix(in srgb, var(--accent) 12%, transparent); color: var(--accent); }
/* --ok on white measures 2.5:1 and fails AA, so the outbound chip takes the
   darker green `.badge-soft.ok` already uses for text on a pale tint. On
   Midnight the tint is dark and the bright token is the readable one, which
   is the same pair of rules that badge follows. */
.ln-out { background: color-mix(in srgb, var(--ok) 14%, transparent); color: #047857; }
[data-theme="midnight"] .ln-out { color: var(--ok); }

/* ── the focus bar ────────────────────────────────────────────────────── */
/* Nineteen tools is navigable once a person can ask for the four they could
   start. Client-side, because it is only class toggling. */
.ln-focus { display: flex; gap: .35rem; flex-wrap: wrap; align-items: center;
            margin: 0 0 .8rem; }
.ln-chip {
  border: 1px solid var(--line); background: var(--card, #fff);
  color: var(--muted); border-radius: 999px;
  padding: .18rem .7rem; font-size: .75rem; font-weight: 600;
  cursor: pointer; transition: all .14s ease;
}
.ln-chip:hover { border-color: color-mix(in srgb, var(--accent) 45%, var(--line)); }
.ln-chip.on {
  background: var(--accent); border-color: var(--accent); color: #fff;
  box-shadow: 0 2px 0 color-mix(in srgb, var(--accent) 65%, #000);
}
.ln-chip .ln-chip-n { opacity: .7; margin-left: .25rem; font-weight: 800; }
/* Filtered OUT rather than removed: the tile keeps its place in the grid so
   the layout does not jump, and a stage that empties says so. */
.ln-tool.ln-hide { display: none; }
.ln-stage.ln-hide { display: none; }

/* ── the maturity mini-bar and the findings list ──────────────────────── */
.ln-mat { display: inline-flex; gap: 2px; vertical-align: middle;
          margin-right: .35rem; cursor: help; }
.ln-mat i { width: 9px; height: 14px; border-radius: 2px; display: block;
            background: var(--line); }
.ln-mat i.l1 { background: color-mix(in srgb, var(--danger, #dc2626) 65%, var(--line)); }
.ln-mat i.l2 { background: color-mix(in srgb, var(--warn, #f59e0b) 75%, var(--line)); }
.ln-mat i.l3 { background: color-mix(in srgb, var(--ok, #16a34a) 60%, var(--line)); }
.ln-mat i.l4 { background: var(--ok, #16a34a); }
.ln-mat i.l5 { background: var(--accent, #2563eb); }

.ln-find { display: flex; gap: .5rem; align-items: flex-start;
           padding: .5rem .8rem; border-bottom: 1px solid var(--line);
           font-size: .8rem; }
.ln-find:last-child { border-bottom: 0; }
.ln-sig {
  flex: 0 0 auto; font-size: .6rem; font-weight: 800; letter-spacing: .04em;
  padding: .1rem .35rem; border-radius: 4px; margin-top: .1rem;
  background: var(--surface-2, #f1f5f9); color: var(--muted);
}
.ln-sig.high, .ln-sig.danger { background: color-mix(in srgb, var(--danger) 15%, transparent); color: var(--danger, #dc2626); }
.ln-sig.warn, .ln-sig.medium { background: color-mix(in srgb, var(--warn) 18%, transparent); color: var(--warn, #b45309); }
.ln-why { display: block; color: var(--muted); font-size: .74rem; line-height: 1.35; }

@media (prefers-reduced-motion: reduce) {
  .ln-tool, .ln-face, .ln-node-ring, .ln-join-list, .ln-chip {
    animation: none !important; transition: none !important;
  }
  .ln-tool:hover { transform: none; }
  .ln-tool:hover .ln-face { transform: none; }
  .ln-tool:hover .ln-face::before { animation: none; }
  .ln-join-list { max-height: none; opacity: 1; }
}

/* ── the coaching engine ───────────────────────────────────────────────────
   A launcher bottom-right on every screen, injected by app.js. It is a
   floating control rather than a band in the page because it appears on
   thirty different layouts and none of them left room for it — and because
   help that pushes the work down the page is help that gets switched off.

   The badge counts only what is OWED. A permanent number that turns out to
   be three things to read is a badge people stop seeing within a week. */
.coach { position: fixed; right: 20px; bottom: 20px; z-index: 1035;
         display: flex; flex-direction: column; align-items: flex-end; gap: 10px; }
@media (max-width: 575.98px) { .coach { right: 12px; bottom: 12px; } }

.coach-btn {
  position: relative; width: 48px; height: 48px; border-radius: 50%;
  border: 0; cursor: pointer; color: #fff; font-size: 1.25rem;
  display: grid; place-items: center; order: 2;
  background: radial-gradient(120% 120% at 32% 22%, #6d7ff5 0%, #4f46e5 46%, #3730a3 100%);
  box-shadow: inset 0 2px 0 rgba(255,255,255,.45), inset 0 -7px 12px rgba(0,0,0,.26),
              0 3px 0 #312e81, 0 10px 22px rgba(2,6,23,.32);
  transition: transform .16s cubic-bezier(.2,.8,.3,1), box-shadow .16s ease;
}
.coach-btn:hover { transform: translateY(-2px); }
.coach-btn:active { transform: translateY(1px); box-shadow: inset 0 2px 0 rgba(255,255,255,.4),
              inset 0 -7px 12px rgba(0,0,0,.26), 0 1px 0 #312e81, 0 4px 12px rgba(2,6,23,.3); }
.coach-n {
  position: absolute; top: -3px; right: -3px; min-width: 20px; height: 20px;
  border-radius: 10px; padding: 0 5px;
  background: var(--danger, #e11d48); color: #fff;
  font-size: .7rem; font-weight: 800; line-height: 20px; text-align: center;
  border: 2px solid var(--bg, #f4f6fb);
}

.coach-panel {
  order: 1; width: min(390px, calc(100vw - 40px)); max-height: min(560px, 74vh);
  overflow: auto; background: var(--card, #fff);
  border: 1px solid var(--line); border-radius: 16px;
  box-shadow: 0 24px 56px rgba(2,6,23,.24), 0 2px 8px rgba(2,6,23,.10);
  animation: coachIn .2s cubic-bezier(.2,.8,.3,1) both;
}
@keyframes coachIn { from { opacity: 0; transform: translateY(10px) scale(.98); }
                     to   { opacity: 1; transform: none; } }

.ch-head { display: flex; align-items: flex-start; gap: 10px;
           padding: 14px 14px 10px; border-bottom: 1px solid var(--line); }
.ch-title { display: flex; align-items: center; gap: 10px; flex: 1 1 auto; min-width: 0; }
.ch-spark {
  width: 34px; height: 34px; border-radius: 10px; flex: 0 0 auto;
  display: grid; place-items: center; color: #fff; font-size: 1rem;
  background: linear-gradient(150deg, #818cf8, #4f46e5);
  box-shadow: inset 0 1.5px 0 rgba(255,255,255,.5), 0 2px 0 #3730a3;
}
.ch-t { font-weight: 700; font-size: .92rem; line-height: 1.2; }
.ch-s { font-size: .74rem; color: var(--muted); margin-top: 1px; }
.ch-pip { display: inline-block; width: 7px; height: 7px; border-radius: 50%;
          margin-right: 4px; vertical-align: baseline; }
.ch-pip.rose { background: var(--danger, #e11d48); }
.ch-pip.amber { background: var(--warn, #d97706); }
.ch-pip.indigo { background: var(--indigo, #6366f1); }
.ch-x { border: 0; background: transparent; color: var(--muted); cursor: pointer;
        padding: 2px 4px; border-radius: 6px; font-size: .85rem; }
.ch-x:hover { background: var(--surface-2); color: var(--ink); }

.ch-list { padding: 6px 0; }
.ch-tip { padding: 11px 14px; border-bottom: 1px solid var(--line); }
.ch-tip:last-child { border-bottom: 0; }
.ch-tip-h { display: flex; align-items: baseline; gap: 8px; }
.ch-tip-t { font-weight: 650; font-size: .86rem; line-height: 1.35; }
.ch-lvl {
  flex: 0 0 auto; font-size: .6rem; font-weight: 800; letter-spacing: .05em;
  text-transform: uppercase; padding: .1rem .35rem; border-radius: 4px;
  white-space: nowrap;
}
/* Semantic, and separate from the accent: rose is owed, amber is next,
   indigo is an explanation. Text colours are the darker AA-safe pair, not
   the fill tokens. */
.ch-lvl.ch-rose   { background: var(--danger-soft, #fdeaef); color: #a4102f; }
.ch-lvl.ch-amber  { background: var(--warn-soft, #fdf3e3); color: #b45309; }
.ch-lvl.ch-indigo { background: var(--accent-soft, #eaf1fe); color: var(--accent-600, #1d4ed8); }
[data-theme="midnight"] .ch-lvl.ch-rose   { background: #33181f; color: #fb7185; }
[data-theme="midnight"] .ch-lvl.ch-amber  { background: #33260c; color: var(--warn); }
[data-theme="midnight"] .ch-lvl.ch-indigo { background: var(--accent-soft); color: var(--accent-600); }

.ch-tip-d { font-size: .78rem; line-height: 1.45; color: var(--muted); margin-top: 4px; }
.ch-tip-a { display: flex; align-items: center; gap: 12px; margin-top: 7px; }
.ch-go { font-size: .76rem; font-weight: 650; text-decoration: none; color: var(--accent);
         display: inline-flex; align-items: center; gap: 4px; }
.ch-go:hover { text-decoration: underline; }
.ch-got { border: 1px solid var(--line); background: transparent; color: var(--muted);
          font-size: .72rem; border-radius: 999px; padding: .1rem .6rem; cursor: pointer; }
.ch-got:hover { border-color: var(--accent); color: var(--accent); }

.ch-foot { display: flex; align-items: baseline; gap: 10px; justify-content: space-between;
           padding: 10px 14px 12px; border-top: 1px solid var(--line);
           font-size: .7rem; color: var(--muted); background: var(--surface-2); }
.ch-foot a { font-weight: 600; white-space: nowrap; }

@media (prefers-reduced-motion: reduce) {
  .coach-panel { animation: none; }
  .coach-btn { transition: none; }
  .coach-btn:hover, .coach-btn:active { transform: none; }
}

/* The area's own "what next" list — the same steps the coaching panel shows,
   from the same engine. Numbered because they ARE an order: the first one is
   ranked above the rest by what it unlocks, not by where it sits in a list. */
.ln-next { list-style: none; counter-reset: nx; padding: 0; margin: 0 0 1rem; }
.ln-next-i {
  counter-increment: nx; position: relative; padding: .5rem .6rem .5rem 2.1rem;
  border: 1px solid var(--line); border-left: 3px solid var(--line);
  border-radius: 9px; background: var(--card, #fff); margin-bottom: .35rem;
}
.ln-next-i::before {
  content: counter(nx); position: absolute; left: .55rem; top: .55rem;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--surface-2); color: var(--muted);
  font-size: .68rem; font-weight: 800; line-height: 18px; text-align: center;
}
.ln-next-recover, .ln-next-overdue { border-left-color: var(--danger, #e11d48); }
.ln-next-score, .ln-next-unblock  { border-left-color: var(--warn, #f59e0b); }
.ln-next-start, .ln-next-raise, .ln-next-commit, .ln-next-finish {
  border-left-color: var(--accent, #2563eb); }

/* One standard's step sequence. Numbered because the order IS the method —
   a standard is a sequence before it is a list of things that happen. */
.sw-steps { counter-reset: sw; list-style: none; padding: 0; margin: 0; }
.sw-steps li {
  counter-increment: sw; position: relative;
  padding: .34rem 0 .34rem 2.1rem; font-size: .86rem; line-height: 1.45;
  border-bottom: 1px solid var(--line);
}
.sw-steps li:last-child { border-bottom: 0; }
.sw-steps li::before {
  content: counter(sw); position: absolute; left: 0; top: .42rem;
  width: 1.35rem; height: 1.35rem; border-radius: 50%;
  background: var(--surface-2); color: var(--muted);
  font-size: .66rem; font-weight: 800; line-height: 1.35rem; text-align: center;
}
/* A check against a superseded revision is kept and visibly not counted. */
.sw-old { opacity: .55; }
.sw-old td:first-child { position: relative; }

/* The leanness board. The "why" line under each measure is the point of the
   screen — a number with no definition beside it is a number two people
   compute differently — so it is set small and grey rather than hidden
   behind a tooltip nobody hovers. */
.ln-measures td { vertical-align: top; }
.ln-measures td .small { line-height: 1.35; max-width: 42ch; }
.ln-measures input { min-width: 5rem; }

/* ── the kamishibai board ─────────────────────────────────────────────────
   One row per card, one column per period. Green and red only, because
   process confirmation is binary by design — an amber turns every card into
   a negotiation about which orange this is, the same reason the tier board
   refuses one. Grey is "nobody looked", which is a fact about the ROUND and
   not about the process, so it is a different shape as well as a different
   colour. */
.km-grid th.km-h { font-size: .62rem; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--muted); line-height: 1.15;
  padding: .35rem .2rem; white-space: nowrap; }
.km-grid th.km-h span { display: block; font-size: .78rem; color: var(--ink); }
.km-grid th.km-now { color: var(--accent); }
.km-grid th.km-now span { color: var(--accent); }
.km-c { width: 2.6rem; padding: .2rem !important; }
.km-dot { display: inline-block; width: 15px; height: 15px; border-radius: 4px;
          background: var(--surface-2); border: 1px solid var(--line); }
.km-confirmed .km-dot { background: var(--ok, #16a34a); border-color: transparent; }
.km-found .km-dot { background: var(--danger, #e11d48); border-color: transparent; }
/* Never turned: hollow, so it does not read as a quiet pass. */
.km-missed .km-dot { background: transparent;
  border: 1px dashed var(--danger, #e11d48); }
.km-off .km-dot { background: transparent; border-style: dotted; opacity: .5; }
.km-turn { display: inline-flex; gap: 2px; }
.km-btn { width: 17px; height: 17px; border-radius: 4px; border: 1px solid var(--line);
  background: var(--card); color: var(--muted); font-size: .6rem; line-height: 1;
  padding: 0; cursor: pointer; display: inline-grid; place-items: center; }
.km-btn:hover { transform: scale(1.15); }
.km-ok:hover { background: var(--ok, #16a34a); color: #fff; border-color: transparent; }
.km-no:hover { background: var(--danger, #e11d48); color: #fff; border-color: transparent; }
@media (prefers-reduced-motion: reduce) { .km-btn:hover { transform: none; } }

/* ── the improvement kata ─────────────────────────────────────────────────
   Progress toward a target condition, and an experiment's outcome. The
   "different" outcome is drawn in the ACCENT rather than in a warning
   colour, deliberately: a prediction that did not hold is the only outcome
   that taught anybody anything, and colouring it as a miss would teach the
   opposite. */
.ka-bar { height: 6px; border-radius: 3px; background: var(--surface-2);
          overflow: hidden; }
.ka-bar i { display: block; height: 100%; border-radius: 3px;
            background: linear-gradient(90deg, var(--accent), var(--ok)); }
.ka-card { border-left: 3px solid var(--line) !important; }
.ka-stale { border-left-color: var(--danger, #e11d48) !important; }
.ka-exp { border: 1px solid var(--line); border-left: 3px solid var(--line);
          border-radius: 8px; padding: .55rem .7rem; margin-bottom: .5rem; }
.ka-as_expected { border-left-color: var(--ok, #16a34a); }
.ka-different { border-left-color: var(--accent, #2563eb); }
.ka-not_yet { border-left-color: var(--line); border-style: dashed; }
.ka-ob-addressing { background: var(--warn-soft, #fdf3e3) !important; color: #b45309 !important; }
.ka-ob-cleared { background: var(--ok-soft, #e7f7ef) !important; color: #047857 !important; }

/* The eight wastes, ranked. The vital few carry the accent; the rest are
   drawn too, because a category that never appears is itself information —
   nobody is seeing it, and one of those two facts is worth knowing. */
.gm-row { padding: .3rem 0; }
.gm-row + .gm-row { border-top: 1px solid var(--line); }
.gm-bar { height: 5px; border-radius: 3px; background: var(--surface-2);
          overflow: hidden; margin: .2rem 0 .15rem; }
.gm-bar i { display: block; height: 100%; border-radius: 3px;
            background: var(--line-2, #c2c9d4); }
.gm-vital .gm-bar i { background: var(--accent); }
.gm-vital .fw-semibold { color: var(--accent); }

/* Andon — jidoka's own screen. The repeat block is the finding, so it gets
   the rail; the late response is the number, so it gets the weight. */
.an-repeat { padding: .4rem 0; border-left: 3px solid var(--danger, #dc3545);
             padding-left: .6rem; margin-bottom: .4rem; }
.an-repeat + .an-repeat { border-top: 1px solid var(--line); padding-top: .5rem; }
.an-late { font-weight: 600; color: #b45309; }
:root[data-theme="midnight"] .an-late { color: #fbbf24; }

/* ══ the phone's bottom bar ═══════════════════════════════════════════════
   Below `lg` the desktop navbar is already collapsed to a top strip; this is
   what replaces the mega-menus it cannot show. The bar belongs to the module
   you are in — see `apps/core/mobile.py` and `docs/MOBILE.md`.

   Above `lg` it is `display:none` and costs nothing: the markup is a nav of
   five links, and the desktop shell is untouched. */
.pq-mobnav{display:none}

@media (max-width: 991.98px){
  .pq-mobnav{
    display:block; position:fixed; left:0; right:0; bottom:0; z-index:1040;
    background:var(--card); border-top:1px solid var(--line);
    box-shadow:0 -6px 20px -14px rgba(2,8,23,.4);
    padding-bottom:env(safe-area-inset-bottom);
  }
  /* the strip that names the module, so the bar having changed is explained */
  .pq-mobnav-in{
    font-size:.62rem; font-weight:800; letter-spacing:.06em; text-transform:uppercase;
    color:var(--ink-soft); text-align:center; padding:.28rem 0 .1rem;
    border-bottom:1px solid var(--line);
  }
  .pq-mobnav-row{display:flex; align-items:stretch}
  /* Back keeps its own narrow lane at the head of the bar, fenced from the
     tabs by the same hairline Home uses on a module bar. It carries no label:
     a chevron pointing left is the one icon on a phone that needs none, and
     the width it saves is what keeps five labelled tabs fitting at 375px. */
  .pq-mobback{
    flex:0 0 2.6rem; display:flex; align-items:center; justify-content:center;
    padding:.5rem 0 .55rem; border:0; background:none; color:var(--ink-soft);
    border-right:1px solid var(--line);
  }
  .pq-mobback .pq-mobtab-i{width:26px; height:26px; border-radius:8px}
  .pq-mobback i{font-size:.9rem}
  .pq-mobback:active .pq-mobtab-i{
    transform:translateY(2px);
    box-shadow:inset 0 1.2px 0 rgba(255,255,255,.45),
      inset 0 -4px 7px rgba(0,0,0,.22), 0 1px 0 var(--is);
  }
  .pq-mobtab{
    flex:1 1 0; min-width:0;
    display:flex; flex-direction:column; align-items:center;
    justify-content:center; gap:.16rem; padding:.5rem .15rem .55rem;
    color:var(--ink-soft); text-decoration:none; font-size:.6rem; font-weight:700;
    line-height:1.15; text-align:center; position:relative; min-width:0;
  }
  /* The icon rides a 3-D face, the same construction `.ic3d` uses everywhere
     else in the product: a gradient front, an inset highlight along the top,
     a stacked extrusion underneath and a gloss clipped to the upper half.
     Built here rather than by adding `.ic3d` to the markup because the sizes
     are different and the resting state is a MUTED face — five accent chips
     in a row would leave nothing to say which tab you are on. */
  .pq-mobtab-i{
    position:relative; display:grid; place-items:center;
    width:30px; height:30px; border-radius:9px; color:#fff;
    --i1:#94a3b8; --i2:#475569; --is:#334155;
    background:linear-gradient(150deg,var(--i1),var(--i2));
    box-shadow:inset 0 1.2px 0 rgba(255,255,255,.5),
      inset 0 -5px 8px rgba(0,0,0,.2),
      0 2px 0 var(--is), 0 3px 0 var(--is), 0 5px 9px -3px rgba(2,8,23,.4);
    transition:transform .16s cubic-bezier(.2,.7,.3,1), box-shadow .16s ease;
  }
  .pq-mobtab-i::after{
    content:""; position:absolute; inset:2px 2px 52% 2px;
    border-radius:7px 7px 42% 42%; pointer-events:none;
    background:linear-gradient(180deg,rgba(255,255,255,.45),rgba(255,255,255,0));
  }
  .pq-mobtab i{font-size:.95rem; line-height:1; position:relative; z-index:1;
    filter:drop-shadow(0 1px 1px rgba(0,0,0,.28))}
  /* The tab you are on is lit and stands a little taller; the others sit
     back. Colour and height together, because on a phone in daylight one of
     the two is often all you get. */
  .pq-mobtab.is-on .pq-mobtab-i{
    --i1:#60a5fa; --i2:#2563eb; --is:#1d4ed8;
    transform:translateY(-2px);
    box-shadow:inset 0 1.2px 0 rgba(255,255,255,.55),
      inset 0 -5px 8px rgba(0,0,0,.2),
      0 2px 0 var(--is), 0 3px 0 var(--is), 0 4px 0 var(--is),
      0 8px 13px -4px rgba(37,99,235,.5);
  }
  /* The same travelling highlight the rest of the app's 3-D faces carry,
     declared HERE rather than in the shared list at the foot of this file:
     everything naming this bar has to sit behind the breakpoint, or it
     reaches a desktop that is not supposed to change. `::after` is already
     the gloss, so the band rides `::before`, clipped by its own radius. */
  .pq-mobtab-i::before{
    content:""; position:absolute; inset:0; border-radius:inherit;
    pointer-events:none;
    background-image:linear-gradient(105deg,
        rgba(255,255,255,0)   38%,
        rgba(255,255,255,.55) 47%,
        rgba(255,255,255,.16) 54%,
        rgba(255,255,255,0)   62%);
    background-size:300% 100%; background-repeat:no-repeat;
    background-position:0% 0;
    animation:pq-sheen 7.5s 600ms infinite;
  }

  /* pressed, not hovered: a thumb has no hover */
  .pq-mobtab:active .pq-mobtab-i{
    transform:translateY(2px);
    box-shadow:inset 0 1.2px 0 rgba(255,255,255,.45),
      inset 0 -4px 7px rgba(0,0,0,.22), 0 1px 0 var(--is);
  }
  /* The count sits ON the icon, not beside the label: beside it, a three-digit
     figure pushes the label out of a 78px slot.
     It is positioned against the TAB, not against the icon span. An
     absolutely-positioned box is shrink-to-fit against its containing block,
     so anchored to the ~20px icon it squeezed a real count — the demo company
     has 101 unread alerts — into 20px and the digits spilled out of the pill.
     The tab is 78px, which is room for three digits and the ring. */
  .pq-mobtab-b{position:absolute; top:.22rem; left:calc(50% + .3rem);
    min-width:1.2rem; height:1.2rem; padding:0 .3rem; border-radius:.6rem;
    z-index:2;
    background:var(--danger); color:#fff; font-size:.66rem; font-weight:800;
    display:flex; align-items:center; justify-content:center; line-height:1;
    white-space:nowrap;
    /* a ring in the bar's own colour, so the count reads as a count and not
       as part of the glyph it sits on */
    box-shadow:0 0 0 2px var(--card)}
  .pq-mobtab span{
    max-width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  }
  .pq-mobtab.is-on{color:var(--accent)}
  .pq-mobtab.is-on::after{
    content:""; position:absolute; top:0; left:24%; right:24%; height:3px;
    border-radius:0 0 3px 3px; background:var(--accent);
  }
  /* Home keeps its slot on every bar, and on a module bar it is fenced off:
     the one thing that does not change has to look like it does not. */
  /* `:first-child` was Home until the Back lane took that place, and a rule
     that quietly stopped matching would have left the fence gone with nothing
     failing. Naming the tab that FOLLOWS Back says what is meant. */
  .pq-mobnav.is-module .pq-mobback + .pq-mobtab{
    flex:0 0 3.7rem; border-right:1px solid var(--line);
  }
  .pq-mobnav.is-module .pq-mobback + .pq-mobtab i{opacity:.72}
  /* The bar covers the foot of the page, so the page gives the room back.
     The module bar is taller by its naming strip; `:has` adds that, and the
     base value stands on its own where `:has` is not supported. */
  body{padding-bottom:4.6rem}
  body:has(.pq-mobnav.is-module){padding-bottom:5.6rem}
}

/* ══ the lean route on a phone ════════════════════════════════════════════
   Below `lg` the route becomes a tiled board, the same shape the phone's home
   uses: the face IS the tile, and twenty-five tools fit on one scroll instead
   of the two-metre column of cards they made as full rows.

   **No new markup.** These are the SAME `.ln-tool` elements the desktop route
   draws, restyled — which matters for more than tidiness: the focus chips
   count `.ln-tool[data-ln-state]`, so a second copy of every tool for phones
   would have made every chip read double, and the page would have argued with
   itself exactly the way the comment on that counter warns about.

   The desktop route is untouched. */
@media (max-width: 991.98px){
  /* The stage header first, because it was broken: `.ln-stage` dropped its
     54px padding below 576px while `.ln-node` stayed absolutely positioned at
     left:0, so the disc sat ON the title — "Foundation" rendered as "ation".
     In flow it cannot overlap anything. */
  .ln-route::before{display:none}
  .ln-stage{padding-left:0; display:grid; grid-template-columns:auto 1fr;
    column-gap:.55rem; align-items:center; margin-bottom:1.1rem}
  /* `relative`, never `static`: the ring and the stage number are absolutely
     positioned INSIDE the node, so making it static handed them the whole
     stage as their containing block and the ring drew as a 300px circle
     across every tile. */
  .ln-node{position:relative; left:auto; top:auto;
    width:36px; height:36px; font-size:.9rem}
  .ln-node-ring{inset:-4px}
  .ln-node-n{right:-3px; bottom:-3px; min-width:15px; height:15px;
    line-height:13px; font-size:.58rem}
  .ln-stage-h{grid-column:2; padding:0; gap:.35rem}
  .ln-stage-b{display:none}          /* the blurb is on the desktop route */
  .ln-tools{grid-column:1 / -1; margin-top:.5rem}

  /* the board */
  .ln-tools{grid-template-columns:repeat(3,1fr); gap:.5rem}
  .ln-tool{
    flex-direction:column; align-items:center; justify-content:center;
    gap:.35rem; padding:.55rem .3rem; min-height:106px; text-align:center;
    border-left-width:1px; border-top:3px solid var(--line);
  }
  /* The state rail moves from the left edge to the top: on a 110px tile a
     left rail is a sliver nobody reads. */
  .ln-tool{border-left-color:var(--line)}
  .ln-face{width:46px; height:46px; font-size:1.55rem}
  .ln-body{flex:0 0 auto; width:100%; align-items:center}
  .ln-tool-h{justify-content:center; width:100%}
  .ln-name{font-size:.66rem; font-weight:700; line-height:1.15;
    display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
    overflow:hidden}
  /* the count rides the corner, as it does on the home's tiles */
  .ln-n{position:absolute; top:.22rem; right:.22rem; margin-left:0;
    font-size:.6rem; padding:.02rem .28rem}
  /* What a tile cannot say in words it still says as a glyph: locked, and
     started ahead of its ground, are the two findings this module exists to
     surface and they must not vanish with the sentence. */
  .ln-sum,.ln-join,.ln-door{display:none}
  .ln-flag,.ln-block{position:absolute; left:.25rem; top:.22rem; margin:0;
    padding:0; font-size:.7rem}
  .ln-flag span,.ln-block span{display:none}
  /* hover tilts belong to a pointer, not a thumb */
  .ln-tool:hover{transform:none; box-shadow:none}
  .ln-tool:hover .ln-face{transform:none}
}

/* ══ the huddle board ═════════════════════════════════════════════════════
   One row per programme, worst first — see apps/meetings/board.py. The row is
   what the meeting walks, so everything on it is sized to be read standing
   up: the code and the counts at a glance, the note where the eye already is,
   and what we said before folded away until somebody asks. */
.hb-row { border-top: 1px solid var(--line); padding: .6rem .85rem; }
.hb-row:first-of-type { border-top: 0; }
/* The colour is a rail, never a wash: a filled row hides the text on it, and
   this row is mostly text. */
.hb-red    { box-shadow: inset 4px 0 0 var(--danger); }
.hb-amber  { box-shadow: inset 4px 0 0 var(--warn); }
.hb-green  { box-shadow: inset 4px 0 0 var(--ok); }
.hb-none   { box-shadow: inset 4px 0 0 var(--line); }

.hb-head { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.hb-code { font-weight: 700; text-decoration: none; }
.hb-name { color: var(--ink); font-size: .9rem; min-width: 0;
           overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hb-phase { font-size: .72rem; color: var(--muted); }
.hb-counts { display: flex; gap: .25rem; flex-wrap: wrap; margin-left: auto; }

/* The three dots the team presses. Pressing the one already on clears it —
   a colour put on by mistake must come off without a fourth control. */
.hb-rag { display: flex; gap: .3rem; flex: 0 0 auto; }
.hb-dot { width: 18px; height: 18px; border-radius: 50%; border: 2px solid var(--line);
          background: var(--card); padding: 0; cursor: pointer;
          transition: transform .12s ease, box-shadow .12s ease; }
.hb-dot:hover { transform: scale(1.15); }
/* `border:` and not `border-color:`. The guard that keeps fill colours off
   text matches the substring "color: var(--ok)", and `border-color` contains
   it — so the shorthand says the same thing without tripping a rule that is
   right to be blunt. */
.hb-dot-green.on  { background: var(--ok);     border: 2px solid var(--ok); }
.hb-dot-amber.on  { background: var(--warn);   border: 2px solid var(--warn); }
.hb-dot-red.on    { background: var(--danger); border: 2px solid var(--danger); }
.hb-dot.on { box-shadow: 0 0 0 3px color-mix(in srgb, currentColor 18%, transparent); }

.hb-flag { font-size: .72rem; color: var(--danger); margin-top: .3rem; }
/* `align-items: start`, or the grid stretches the note to whatever height the
   actions column happens to be: a programme with three open actions opened a
   150px empty box, and one with none opened a single line. The box should be
   the size of what is in it, not of what is beside it. */
.hb-body { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 320px);
           gap: .6rem; margin-top: .45rem; align-items: start; }
/* One line until there is something to say. The shared auto-grow gives
   every textarea room as it fills; without a floor it opened at the
   height of the tallest thing on the row and the board became a column
   of empty boxes. */
.hb-note { resize: vertical; min-height: 2.3rem; max-height: 14rem; }
.hb-side { display: flex; flex-direction: column; gap: .2rem; }
.hb-action { display: flex; align-items: baseline; gap: .35rem; font-size: .76rem; }
.hb-action-t { min-width: 0; overflow: hidden; text-overflow: ellipsis;
               white-space: nowrap; }
.hb-action.hb-empty { color: var(--muted); }
.hb-add { font-size: .76rem; text-decoration: none; align-self: flex-start; }
.hb-first { margin: .4rem 0 0; font-size: .74rem; color: var(--muted); }
.hb-trail { margin-top: .4rem; font-size: .76rem; }
.hb-trail summary { cursor: pointer; color: var(--muted); }
.hb-trail-row { display: flex; gap: .5rem; padding: .15rem 0; }
.hb-trail-d { flex: 0 0 3.4rem; color: var(--muted); }

/* On a phone the row stacks: the note under the head, the actions under it. */
@media (max-width: 767.98px) {
  .hb-body { grid-template-columns: minmax(0, 1fr); }
  .hb-counts { margin-left: 0; width: 100%; }
}

/* ─────────────────────────────────────────────────────────────────────────
   Midnight, the last sweep. These were found by a guard rather than by eye
   (apps/core/test_midnight.py): a surface painted with a light hex renders
   perfectly in whichever theme its author had open, and as a white slab in
   the other one. Restated in tokens; Classic is untouched.

   What is NOT here is as deliberate as what is. A white chip behind a
   company logo, a balloon on a customer's drawing, the lit top face of a
   3-D icon and a soft chip that carries its own dark ink are white on
   PURPOSE — each is declared at its own rule with a `light-only:` note.
   ───────────────────────────────────────────────────────────────────────── */

/* the phase stepper */
:root[data-theme="midnight"] .phase-step{ background:var(--card); }
:root[data-theme="midnight"] .phase-step.done{
  background:linear-gradient(180deg, color-mix(in srgb,var(--ok) 14%,var(--card)), var(--card)); }

/* the programme Gantt: the label rail and the "Today" flag */
:root[data-theme="midnight"] .gantt-label-col{ background:var(--card); }
:root[data-theme="midnight"] .gantt-today::before{ background:var(--card); }

/* the gate-review card, tinted red */
:root[data-theme="midnight"] .gr-card.is-red{
  background:linear-gradient(180deg, var(--card), color-mix(in srgb,var(--danger) 9%,var(--card))); }

/* SQDCM: the action train's lower chevron, and a day cell being typed into */
:root[data-theme="midnight"] .sqa-fix{
  background:linear-gradient(180deg, var(--card), color-mix(in srgb,var(--card) 92%,#000));
  color:var(--ink); }
:root[data-theme="midnight"] .sqa-fix i,
:root[data-theme="midnight"] .sqa-fix span{ color:var(--muted); }
:root[data-theme="midnight"] .sq-kpi-day input:focus{ background:var(--card); }

/* the workload tab bar */
:root[data-theme="midnight"] .wl-tabs{ background:var(--bg); border-color:var(--line); }
:root[data-theme="midnight"] .wl-tab{ color:var(--muted); }
:root[data-theme="midnight"] .wl-tab:hover{ background:var(--card); color:var(--ink); }

/* the Team Gantt. Its header is navy in both themes; everything under it
   was written light, down to the sticky person rail and every day cell. */
:root[data-theme="midnight"] .tg-controls,
:root[data-theme="midnight"] .tg-seg-btn,
:root[data-theme="midnight"] .tg-select,
:root[data-theme="midnight"] .tg-stat,
:root[data-theme="midnight"] .tg-more{
  background:linear-gradient(180deg, var(--card), color-mix(in srgb,var(--card) 90%,#000)); }
:root[data-theme="midnight"] .tg-seg-btn,
:root[data-theme="midnight"] .tg-select,
:root[data-theme="midnight"] .tg-stat{ color:var(--muted); }
:root[data-theme="midnight"] .tg-stat b{ color:var(--ink); }
:root[data-theme="midnight"] .tg-board{ background:var(--card); box-shadow:0 24px 50px -30px rgba(0,0,0,.7),0 0 0 1px var(--line); }
:root[data-theme="midnight"] .tg th.tg-who,
:root[data-theme="midnight"] .tg td.tg-who{ background:var(--card); }
:root[data-theme="midnight"] .tg tbody tr:hover td.tg-who{ background:var(--bg); }
:root[data-theme="midnight"] .tg td{ border-bottom-color:var(--line); border-right-color:var(--line); }
:root[data-theme="midnight"] .tg-name{ color:var(--ink); }
:root[data-theme="midnight"] .tg-sub,
:root[data-theme="midnight"] .tg-bar-proj,
:root[data-theme="midnight"] .tg-when{ color:var(--muted); }
:root[data-theme="midnight"] .tg-cell.is-day{ background:var(--card); }
:root[data-theme="midnight"] .tg-cell.is-day.is-we{
  background:repeating-linear-gradient(45deg, var(--bg) 0 6px, var(--card) 6px 12px); }
/* the bar in its plain state — the coloured states carry their own ink */
:root[data-theme="midnight"] .tg-bar{
  background:linear-gradient(180deg, var(--card), color-mix(in srgb,var(--c) 20%,var(--card)));
  color:var(--ink); }
:root[data-theme="midnight"] .tg-bar:hover{ color:var(--ink); }

/* The same sweep over the shared sheet, widened from "white" to any LIGHT
   NEUTRAL — `.tg-legend` was #f8fafc→#eef2f8, which is not white and was a
   white slab under the Team Gantt all the same. Two kinds of rule are held
   back deliberately: anything sitting on the SQDCM hero, which is coloured
   in both themes, and the left border of a gate-review card, which IS its
   RAG colour — a `:root[data-theme]` rule outranks `.gr-card.is-red`, so
   restating it would erase the rail it was meant to leave alone. */
:root[data-theme="midnight"] .notif-menu .dropdown-item:hover .notif-msg,
:root[data-theme="midnight"] .qt-menu .qt-head,
:root[data-theme="midnight"] .qt-menu .qt-sub,
:root[data-theme="midnight"] .rd-pop label,
:root[data-theme="midnight"] .sq-legend,
:root[data-theme="midnight"] .sq-kpi-v em,
:root[data-theme="midnight"] .sq-actions-h,
:root[data-theme="midnight"] .sq-action-b em,
:root[data-theme="midnight"] .sq-add summary,
:root[data-theme="midnight"] .sq-ov-h,
:root[data-theme="midnight"] .sq-ov-id,
:root[data-theme="midnight"] .gr-walk-h,
:root[data-theme="midnight"] .tg-ctl-label,
:root[data-theme="midnight"] .tg-pop-head,
:root[data-theme="midnight"] .tg-pop-foot{ color:var(--muted); }
:root[data-theme="midnight"] .proq-nav .dropdown-menu.qt-menu .qt-item,
:root[data-theme="midnight"] .qt-menu .qt-title,
:root[data-theme="midnight"] .rm-cell,
:root[data-theme="midnight"] .gr-cell,
:root[data-theme="midnight"] .rd-pop-h{ color:var(--ink); }
:root[data-theme="midnight"] .qt-menu .qt-pill,
:root[data-theme="midnight"] .ctm-avatar.is-empty,
:root[data-theme="midnight"] .sq-day,
:root[data-theme="midnight"] .sq-ov-new{ background:var(--bg); color:var(--muted); }
:root[data-theme="midnight"] .phase-step .ph-num,
:root[data-theme="midnight"] .rm-low,
:root[data-theme="midnight"] .rm-unrated,
:root[data-theme="midnight"] .risk-table .cell-input.is-required,
:root[data-theme="midnight"] .cc-minibar,
:root[data-theme="midnight"] .cc-riskbar,
:root[data-theme="midnight"] .gantt-row:hover,
:root[data-theme="midnight"] .stat-target,
:root[data-theme="midnight"] .cmp-table tbody tr:hover,
:root[data-theme="midnight"] .sq-shape,
:root[data-theme="midnight"] .sq-kpi.is-miss,
:root[data-theme="midnight"] .sq-action.is-late,
:root[data-theme="midnight"] .sq-donut.is-na,
:root[data-theme="midnight"] .gr-pctbar,
:root[data-theme="midnight"] .gr-mile,
:root[data-theme="midnight"] .gr-clock.is-warm,
:root[data-theme="midnight"] .gr-clock.is-over,
:root[data-theme="midnight"] .gr-walkbar,
:root[data-theme="midnight"] .gr-node.st-in_progress{ background:var(--bg); }
:root[data-theme="midnight"] .phase-step.na,
:root[data-theme="midnight"] .auth-wrap,
:root[data-theme="midnight"] .shimmer,
:root[data-theme="midnight"] .sqa-who,
:root[data-theme="midnight"] .tg-seg,
:root[data-theme="midnight"] .tg-ms-cell.is-we{ background:linear-gradient(180deg, var(--card), color-mix(in srgb, var(--card) 92%, #000)); }
:root[data-theme="midnight"] .phase-step.na .ph-num,
:root[data-theme="midnight"] .gr-focus:hover,
:root[data-theme="midnight"] .gr-focus.is-overdue:hover,
:root[data-theme="midnight"] .tg-legend-sep{ background:color-mix(in srgb, var(--line) 55%, var(--card)); }
:root[data-theme="midnight"] .evidence-drop,
:root[data-theme="midnight"] .sq-action{ background:var(--card); }
:root[data-theme="midnight"] .charter-phase-n,
:root[data-theme="midnight"] .tg-legend{ background:linear-gradient(180deg, var(--card), color-mix(in srgb, var(--card) 92%, #000)); color:var(--muted); }

/* The soft chips on the shared sheet. A pale tint carrying its own dark ink
   has to move as a PAIR — Midnight's palette already says what that looks
   like (`--ok-soft:#0f2a20` beneath `--ok:#34d399`): an opaque dark tint of
   the chip's own hue, with the same hue lifted for the letters, so a green
   chip still reads green and a red one still reads red. */
:root[data-theme="midnight"] .rag-amber{ background:color-mix(in srgb, #7c3aed 20%, var(--card)); color:color-mix(in srgb, #7c3aed 42%, #ffffff); }
:root[data-theme="midnight"] .gantt-today::before{ color:color-mix(in srgb, #e11d48 42%, #ffffff); }
:root[data-theme="midnight"] .gr-weekbox em,
:root[data-theme="midnight"] .gr-label em{ background:color-mix(in srgb, #166534 20%, var(--card)); }
:root[data-theme="midnight"] .sq-uncovered,
:root[data-theme="midnight"] .gr-mile.is-missed{ background:color-mix(in srgb, #991b1b 20%, var(--card)); color:color-mix(in srgb, #991b1b 42%, #ffffff); }
:root[data-theme="midnight"] .sq-say{ background:color-mix(in srgb, #92400e 20%, var(--card)); color:color-mix(in srgb, #92400e 42%, #ffffff); }
:root[data-theme="midnight"] .gr-mile.is-met{ background:color-mix(in srgb, #166534 20%, var(--card)); color:color-mix(in srgb, #166534 42%, #ffffff); }
:root[data-theme="midnight"] .gr-mile.is-late{ background:color-mix(in srgb, #9a3412 20%, var(--card)); color:color-mix(in srgb, #9a3412 42%, #ffffff); }
:root[data-theme="midnight"] .mention{ background:color-mix(in srgb, #6d28d9 20%, var(--card)); color:color-mix(in srgb, #6d28d9 42%, #ffffff); }
:root[data-theme="midnight"] .mention-item.is-sel,
:root[data-theme="midnight"] .mention-item:hover{ background:color-mix(in srgb, #4c1d95 20%, var(--card)); color:color-mix(in srgb, #4c1d95 42%, #ffffff); }
:root[data-theme="midnight"] .gr-4m-run{ background:color-mix(in srgb, #1d4ed8 20%, var(--card)); color:color-mix(in srgb, #1d4ed8 42%, #ffffff); }
:root[data-theme="midnight"] .gr-4m-hold{ background:color-mix(in srgb, #5b21b6 20%, var(--card)); color:color-mix(in srgb, #5b21b6 42%, #ffffff); }
:root[data-theme="midnight"] .tg-stat.is-late{ background:color-mix(in srgb, #b91c1c 20%, var(--card)); color:color-mix(in srgb, #b91c1c 42%, #ffffff); }

/* ═══════════════════════════════════════════════════════════════════════════
   LIVING SHAPES — the 3-D language the app already speaks, given light.

   Every module builds its objects the same way: a gradient face, a gloss, and
   a stack of shadows under it that makes the thing sit ON the page rather than
   in it. What they were missing is the one cue that says an object is real —
   light MOVING across it. So nothing here invents a new shape: it puts a
   travelling specular band on the shapes that are already there, and on the
   tab that is currently open, in every module.

   Four decisions carry it.

   The band lives on `::before`, which every one of these shapes had free
   (the two that use `::after` use it for their gloss, which is untouched).
   It is CLIPPED by `border-radius: inherit`: a pseudo-element's
   own background is always cut to its rounded border box, so the sweep can
   never escape the face, and no parent needs `overflow: hidden` — which on a
   shape whose depth IS a box-shadow would have cut its extrusion off.

   It sweeps `background-position`, not `transform`. A moving child would have
   to be clipped by the parent, and clipping the parent clips the shadow stack
   that makes it 3-D. Repainting a 22-46px box is cheaper than losing the depth.

   The duty cycle is deliberately mean: the sweep is 22% of a 7.5s cycle and
   every family is offset, so on a board of thirty tiles about five are lit at
   any moment. Thirty objects flashing in unison is a fairground; a few
   catching the light in turn is a surface. `--i` is already set for the
   stagger on most of these rows, so the delay rides on it where it exists.

   And it is DECORATION: `pointer-events: none` everywhere, so the band can
   never take a click from the thing underneath it — the App Map's own lesson,
   where a projection moved a card's hit area away from where it was painted.
   ═══════════════════════════════════════════════════════════════════════════ */

/* The geometry is worth stating, because getting it wrong is silent: with a
   background wider than its box, `background-position: p%` resolves to
   p × (boxW − imgW), so at 300% width the image travels −2·boxW as p runs
   0 → 100%. The bright part of the gradient sits at ~half the image, which
   puts it off the right edge at 0% and off the left edge at 100% — a full
   traverse, in units that do not care how big the shape is. The first
   version used −150% → 250% at 260% width and spent almost the whole sweep
   off the face: a 190ms blink every 7.5s rather than a glide. */
@keyframes pq-sheen {
  0%           { background-position:   0% 0; }
  22%          { background-position: 100% 0; }
  100%         { background-position: 100% 0; }
}

/* The buoyancy of a large decorative badge — one or two on a page, never a
   grid of them, because a floating LIST reads as a page that will not settle. */
@keyframes pq-buoy {
  0%, 100%     { transform: translateY(0) rotate(0deg); }
  50%          { transform: translateY(-4px) rotate(-.5deg); }
}

.ic3d, .sq-redcount, .sq-ov, .sq-ov-plus, .sqa-av, .gr-rag-red, .gr-rag-amber,
.gr-rag-green, .gr-part, .gr-burn, .gr-av, .docbtn .dbi, .tg-count, .tg-flag,
.ch-spark, .pqh-mark,
.cap-stat .ic, .cap-hc, .cs-k .ic, .cs-card-head .ic, .hc3d, .ac-ic,
.mx-cat-icon, .cmb-ic, .patab-ic, .cv-av, .esc, .al-ic, .pl-ic,
.m4ic-ok, .m4ic-late, .pab-count, .pa-act-coin, .pa-ic, .pa-rowic,
.cr-doc-ic, .tool .ic, .vp-badge,
.wl-tab.is-on, .tg-seg-btn.is-on, .patab.is-on, .csrnav a.on, .mtab.is-on,
.ctab.is-on, .fish-tab.is-on, .cmb-chip.is-on, .hp-chip.is-on, .mx-chip.on,
.ln-chip.on, .ff-chip.on {
  position: relative;
}

.ic3d::before, .sq-redcount::before, .sq-ov::before, .sq-ov-plus::before,
.sqa-av::before, .gr-rag-red::before, .gr-rag-amber::before,
.gr-rag-green::before, .gr-part::before, .gr-burn::before, .gr-av::before,
.docbtn .dbi::before, .tg-count::before, .tg-flag::before, .ch-spark::before,
.pqh-mark::before,
.cap-stat .ic::before, .cap-hc::before, .cs-k .ic::before,
.cs-card-head .ic::before, .hc3d::before, .ac-ic::before, .mx-cat-icon::before,
.cmb-ic::before, .patab-ic::before, .cv-av::before, .esc::before,
.al-ic::before, .pl-ic::before, .m4ic-ok::before, .m4ic-late::before,
.pab-count::before, .pa-act-coin::before, .pa-ic::before, .pa-rowic::before,
.cr-doc-ic::before, .tool .ic::before, .vp-badge::before,
.wl-tab.is-on::before, .tg-seg-btn.is-on::before, .patab.is-on::before,
.csrnav a.on::before, .mtab.is-on::before, .ctab.is-on::before,
.fish-tab.is-on::before, .cmb-chip.is-on::before, .hp-chip.is-on::before,
.mx-chip.on::before, .ln-chip.on::before, .ff-chip.on::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;      /* the clip — see the note above */
  pointer-events: none;        /* decoration never takes a click */
  background-image: linear-gradient(105deg,
      rgba(255,255,255,0)   38%,
      rgba(255,255,255,.55) 47%,
      rgba(255,255,255,.16) 54%,
      rgba(255,255,255,0)   62%);
  background-size: 300% 100%;
  background-repeat: no-repeat;
  background-position: 0% 0;
  animation: pq-sheen 7.5s var(--pq-sheen-delay, 0ms) infinite;
}

/* Families are offset from one another so a screen showing several kinds of
   object does not light them all at the same instant. Within a family the
   stagger rides on `--i`, which the rows already set for their entrance. */
.ic3d, .cap-stat .ic, .cs-k .ic          { --pq-sheen-delay: calc(var(--i, 0) * 380ms); }
.docbtn .dbi, .patab-ic, .tool .ic       { --pq-sheen-delay: calc(var(--i, 0) * 300ms + 900ms); }
.ac-ic, .pa-rowic, .cr-doc-ic, .cmb-ic   { --pq-sheen-delay: calc(var(--i, 0) * 260ms + 1800ms); }
.gr-rag-red, .gr-rag-amber, .gr-rag-green,
.gr-av, .gr-part, .gr-burn               { --pq-sheen-delay: calc(var(--i, 0) * 220ms + 2600ms); }
.tg-count, .tg-flag, .sqa-av, .cv-av     { --pq-sheen-delay: calc(var(--i, 0) * 200ms + 3400ms); }
/* The open tab is ONE object on the screen, so it leads rather than queues. */
.wl-tab.is-on, .tg-seg-btn.is-on, .patab.is-on, .csrnav a.on, .mtab.is-on,
.ctab.is-on, .fish-tab.is-on, .cmb-chip.is-on, .hp-chip.is-on, .mx-chip.on,
.ln-chip.on, .ff-chip.on                 { --pq-sheen-delay: 600ms; }

/* On a dark ground a white band is harsher, so Midnight gets a softer one. */
:root[data-theme="midnight"] .ic3d::before,
:root[data-theme="midnight"] .docbtn .dbi::before,
:root[data-theme="midnight"] .cap-stat .ic::before,
:root[data-theme="midnight"] .cs-k .ic::before,
:root[data-theme="midnight"] .ac-ic::before,
:root[data-theme="midnight"] .mx-cat-icon::before,
:root[data-theme="midnight"] .cmb-ic::before,
:root[data-theme="midnight"] .patab-ic::before,
:root[data-theme="midnight"] .pa-rowic::before,
:root[data-theme="midnight"] .cr-doc-ic::before,
:root[data-theme="midnight"] .tool .ic::before,
:root[data-theme="midnight"] .pqh-mark::before {
  background-image: linear-gradient(105deg,
      rgba(255,255,255,0)   38%,
      rgba(255,255,255,.34) 47%,
      rgba(255,255,255,.10) 54%,
      rgba(255,255,255,0)   62%);
}

/* The big decorative badges breathe. These are one-per-page objects — the
   hero mark, the module badge — never a grid, and never a click target. */
.cap-badge3d .face, .cs-badge3d .face, .mx-badge3d .face, .pqh-mark {
  animation: pq-buoy 6.5s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
  .ic3d::before, .sq-redcount::before, .sq-ov::before, .sq-ov-plus::before,
  .sqa-av::before, .gr-rag-red::before, .gr-rag-amber::before,
  .gr-rag-green::before, .gr-part::before, .gr-burn::before, .gr-av::before,
  .docbtn .dbi::before, .tg-count::before, .tg-flag::before, .ch-spark::before,
  .pqh-mark::before,
  .cap-stat .ic::before, .cap-hc::before, .cs-k .ic::before,
  .cs-card-head .ic::before, .hc3d::before, .ac-ic::before,
  .mx-cat-icon::before, .cmb-ic::before, .patab-ic::before, .cv-av::before,
  .esc::before, .al-ic::before, .pl-ic::before, .m4ic-ok::before,
  .m4ic-late::before, .pab-count::before, .pa-act-coin::before, .pa-ic::before,
  .pa-rowic::before, .cr-doc-ic::before, .tool .ic::before, .vp-badge::before,
  .wl-tab.is-on::before, .tg-seg-btn.is-on::before, .patab.is-on::before,
  .csrnav a.on::before, .mtab.is-on::before, .ctab.is-on::before,
  .fish-tab.is-on::before, .cmb-chip.is-on::before, .hp-chip.is-on::before,
  .mx-chip.on::before, .ln-chip.on::before, .ff-chip.on::before,
  .cap-badge3d .face, .cs-badge3d .face, .mx-badge3d .face {
    animation: none !important;
    background-image: none;
  }
}

@media (max-width: 991.98px) and (prefers-reduced-motion: reduce) {
  /* The phone bar's own highlight, switched off for the same reason as every
     other one. A separate query because the rule it turns off lives behind
     the phone breakpoint, and nothing naming that bar may sit outside it —
     the comment goes INSIDE the braces for the same reason, since the guard
     reads whatever precedes a brace as the selector. */
  .pq-mobtab-i::before { animation: none !important; background-image: none; }
}

/* ─────────────────────────────────────────────────────────────────────────
   The document hero on a phone.

   `.fmea-hero` is shared by the PFMEA, the Control Plan, PPAP, SPC, MSA,
   metrology, the handover audit and change management — so one row getting
   this wrong got it wrong on most of the detail screens in the product.

   `.fmea-hero-top` is a flex row of back · identity · actions, and the
   actions were sized by their content: seven buttons and a lifecycle stepper
   asked for ~600px and took it, leaving the identity column about two words
   wide. The title then wrapped to four lines UNDER the stepper, the status
   badges were squeezed into circles, and a subtitle reading "APQP-0002 ·
   part ACS-SH-4410 · due 19 Sep 2026" came out one word per line.

   Below the shell's own breakpoint the row becomes a stack: the identity
   keeps the first line with the back button, and the actions take a full
   line of their own underneath. Nothing here reaches a desktop.
   ───────────────────────────────────────────────────────────────────────── */
@media (max-width: 991.98px) {
  .fmea-hero { padding: 14px 16px 16px; }
  .fmea-hero-top { flex-wrap: wrap; gap: 10px; }
  .fmea-hero-back { order: 1; }
  .fmea-hero-id { order: 2; flex: 1 1 0; min-width: 0; }
  /* `margin-left:auto` is what pinned the actions to the right of a row they
     no longer share; on its own line it would push them off the left edge. */
  .fmea-hero-actions { order: 3; flex: 1 1 100%; margin-left: 0;
    justify-content: flex-start; row-gap: 8px; }
  .fmea-hero-title { font-size: 1.14rem; line-height: 1.25; }
  .fmea-hero-sub { font-size: .78rem; }
  /* Two up and filling the width. They were `min-width:148px` in a flex row
     and landed 6px short of fitting two, so every one took a line of its own
     and left half the card empty. */
  .fmea-hero-kpis { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px; }
  .fmea-kpi { min-width: 0; padding: 8px 10px; }
  .fk-ic { width: 30px; height: 30px; font-size: .92rem; border-radius: 9px; }
  .fk-val { font-size: 1.12rem; }
}

/* Below this the pair would clip their own labels — "APPROVER SIGNATURES"
   needs about 150px before it breaks mid-word. */
@media (max-width: 359.98px) {
  .fmea-hero-kpis { grid-template-columns: minmax(0, 1fr); }
}


/* Two stat labels were cut by a handful of pixels at phone width — wide
   letter-spacing on an uppercase string in a box sized for the figure beside
   it. "Overdue deliverables" wanted 83px and had 68; "Unassigned" wanted 81
   and had 77. The spacing is what is spent, since it is decoration and the
   word is not. */
@media (max-width: 767.98px) {
  .pl-stat-lbl, .kpi2-label { letter-spacing: .04em; overflow-wrap: anywhere; }
  .pl-stat { overflow: visible; }
}

/* ── The programme pyramid is a filter ────────────────────────────────────
   A click on a step lists the programmes in that phase. Two things stood in
   the way, both found by asking the browser what sits under each step's label
   (elementFromPoint), not by looking: the stage was `pointer-events: none`,
   built as pure decoration; and `.ch-hero-top` — the title row, z-index 1,
   the full width of the hero, 105→277px — lies over the whole ziggurat, so
   every one of the five labels landed on the title row.

   The row now lets a click through where it has nothing to click, and its
   own buttons and links take clicks back. Paint order is untouched, so the
   pyramid looks exactly as it did; only where a click lands has changed.
   Each step's link covers its lit top face and inherits that face's 3-D
   transform, so the hit area is the face as it is drawn. */
.pl-hero .ch-hero-top { pointer-events: none; }
.pl-hero .ch-hero-top a,
.pl-hero .ch-hero-top button,
.pl-hero .ch-hero-top form,
.pl-hero .ch-hero-top input,
.pl-hero .ch-hero-top select { pointer-events: auto; }
.pl-step-link { position: absolute; inset: 0; display: block;
  pointer-events: auto; cursor: pointer; }
.pl-step-link:focus-visible { outline: 2px solid rgba(255, 255, 255, .95);
  outline-offset: -3px; }

/* Program budget — the supporting documents on a cost line (paperclip button
   and the panel that opens under the line). Tokens only, for Midnight. */
.cost-doc-btn { display: inline-flex; align-items: center; gap: 3px; padding: 2px 8px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--card); color: var(--ink-soft); font-size: .74rem; font-weight: 600; }
.cost-doc-btn:hover { border-color: var(--accent); color: var(--accent); }
.cost-doc-btn.has-docs { color: var(--accent-600); background: var(--accent-soft); border-color: transparent; }
.cost-doc-btn.is-missing { color: color-mix(in srgb, var(--warn) 80%, var(--ink));
  border-color: color-mix(in srgb, var(--warn) 45%, var(--line)); }
tr.cost-docs > td { background: var(--bg); padding: .6rem .8rem; }
.cost-docs-panel { display: grid; gap: .5rem; }
.cost-docs-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: .4rem; font-size: .8rem; }
.cost-doc-list { list-style: none; margin: 0; padding: 0; display: grid; gap: .3rem; }
.cost-doc-list li { display: flex; flex-wrap: wrap; align-items: center; gap: .3rem .6rem; padding: .35rem .6rem;
  background: var(--card); border: 1px solid var(--line); border-radius: 8px; font-size: .8rem; }
.cost-doc-name { font-weight: 600; text-decoration: none; overflow-wrap: anywhere; }
.cost-doc-note, .cost-doc-meta { color: var(--ink-soft); font-size: .74rem; }
.cost-doc-empty { color: var(--ink-soft); font-size: .78rem; }
.cost-doc-form { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; }
.cost-doc-form .form-select { width: auto; max-width: 100%; }
.cost-doc-form .form-control { width: 16rem; max-width: 100%; }

/* ── Reassigning a signature ───────────────────────────────────────────────
   A <details> rather than a modal or a dropdown: the panel is included by a
   dozen screens and half of them are inside HTMX islands, so anything that
   needed JS to mount would have to be re-mounted on every swap. */
.ap-reroute { position: relative; display: inline-block; }
.ap-reroute > summary { list-style: none; cursor: pointer; }
.ap-reroute > summary::-webkit-details-marker { display: none; }
.ap-reroute-form { position: absolute; right: 0; top: calc(100% + .35rem);
  z-index: 20; width: 16rem; padding: .7rem; border-radius: 12px;
  background: var(--card); border: 1px solid var(--line);
  box-shadow: 0 14px 34px rgba(2, 8, 23, .22); }

/* ── Numbered steps on an import screen ───────────────────────────────────
   Two of these, and the order is the point: the file has to exist before it
   can be uploaded. Token-driven so it themes with everything else. */
.imp-step { flex: 0 0 auto; width: 1.75rem; height: 1.75rem; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  font-weight: 800; font-size: .85rem; line-height: 1;
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 34%, transparent); }

/* ── The 0.10 chip's popover: three checks, each with what is missing ─────── */
.help-popover .tp-chk { display: flex; gap: .45rem; align-items: baseline;
  padding: .25rem 0; font-size: .82rem; line-height: 1.35; }
.help-popover .tp-chk + .tp-chk { border-top: 1px solid var(--line); }
.help-popover .tp-chk b { flex: 0 0 auto; font-size: .9rem; }
.help-popover .tp-chk span { display: block; color: var(--ink-soft);
  font-size: .76rem; }

/* ── Rejecting, with the reason in the same press ─────────────────────────── */
.ap-reject { position: relative; display: inline-block; }
.ap-reject > summary { list-style: none; cursor: pointer; }
.ap-reject > summary::-webkit-details-marker { display: none; }
.ap-reject-form { position: absolute; right: 0; top: calc(100% + .35rem);
  z-index: 21; width: 19rem; padding: .7rem; border-radius: 12px;
  background: var(--card); border: 1px solid var(--line);
  box-shadow: 0 14px 34px rgba(2, 8, 23, .22); text-align: left; }

/* ── The requirement "?" now carries two voices ───────────────────────────
   what the standard asks, and what THIS plant attaches. They need telling
   apart at a glance, so the company's own list sits on its own ground. */
.help-popover .hp-std { font-size: .82rem; line-height: 1.45; }
.help-popover .hp-ours { margin-top: .55rem; padding: .5rem .6rem;
  border-radius: 8px; background: color-mix(in srgb, var(--accent) 9%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent); }
.help-popover .hp-ours b { display: block; font-size: .72rem;
  text-transform: uppercase; letter-spacing: .04em; color: var(--accent);
  margin-bottom: .2rem; }
.help-popover .hp-ours ul { margin: 0; padding-left: 1.1rem; font-size: .8rem;
  line-height: 1.4; }
.help-popover .hp-note { margin-top: .5rem; font-size: .78rem;
  color: var(--ink-soft); font-style: italic; }
/* A requirement whose documents the company has named reads as answered. */
.help-q.has-ours { color: var(--accent); }

/* ── How many months the phase timeline covers ────────────────────────────
   A segmented control in the chart's own legend bar: the reader is already
   looking there to decode the colours, and a chart control belongs on the
   chart rather than in a toolbar above it. */
.gantt-span { display: inline-flex; align-items: center; gap: .25rem; }
.gantt-span-label { margin-right: .15rem; font-size: .72rem;
  text-transform: uppercase; letter-spacing: .04em; color: var(--ink-soft); }
.gantt-span-btn { display: inline-flex; align-items: center; justify-content: center;
  min-width: 1.85rem; padding: .12rem .4rem; border-radius: 6px;
  border: 1px solid var(--line); background: var(--card);
  color: var(--ink-soft); font-size: .74rem; font-weight: 600;
  text-decoration: none; transition: background .14s, color .14s, border-color .14s; }
.gantt-span-btn:hover { color: var(--accent); border-color: var(--accent); }
.gantt-span-btn.is-on { background: var(--accent); border-color: var(--accent);
  color: #fff; }

/* ── A phase row opened into its requirements ─────────────────────────────
   A requirement is a POINT on this chart, not a bar: it has a due date and no
   duration. Drawing it as a span from the start of the phase would be a
   picture of something nobody planned. Where it has been released, the run
   from the actual close to the due date is drawn behind the dot, so planned
   and actual read as a distance. */
.gantt-toggle { flex: 0 0 auto; width: 1.15rem; height: 1.15rem; margin-right: .2rem;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; background: transparent; color: var(--ink-soft);
  border-radius: 4px; cursor: pointer; font-size: .7rem; line-height: 1;
  transition: transform .16s, color .16s, background .16s; }
.gantt-toggle:hover { color: var(--accent); background: var(--bg-2, rgba(0,0,0,.04)); }
.gantt-toggle.is-empty { cursor: default; }
.gantt-phase-row.is-open .gantt-toggle { transform: rotate(90deg); color: var(--accent); }
.gantt-phase-row .gantt-label-col { flex-direction: row; align-items: center;
  gap: .1rem; }
.gantt-phase-row .gantt-label-col > a { min-width: 0; }

.gantt-item-row { background: color-mix(in srgb, var(--accent) 3%, transparent); }
.gantt-item-row .gantt-label-col { padding-left: 1.7rem; }
.gantt-item-label { display: flex; align-items: baseline; gap: .35rem; min-width: 0; }
.gantt-item-code { flex: 0 0 auto; font-size: .72rem; font-weight: 700;
  color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.gantt-item-name { font-size: .74rem; color: var(--ink-soft);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gantt-item-dot { position: absolute; top: 50%; width: 11px; height: 11px;
  margin: -5.5px 0 0 -5.5px; border-radius: 50%;
  box-shadow: 0 0 0 2px var(--card); }
.gantt-item-run { position: absolute; top: 50%; height: 2px; margin-top: -1px;
  background: color-mix(in srgb, var(--ink-soft) 45%, transparent); }
/* Closed after it was due: the distance is the slip, so it reads as one. */
.gantt-item-run.is-late { background: color-mix(in srgb, #dc2626 45%, transparent); }
.gantt-item-note .gantt-body { display: flex; align-items: center;
  padding-left: .4rem; }

/* ── "Saved" beside a control that saves itself ───────────────────────────
   Empty until the server answers, so the screen is quiet until something has
   actually happened — a row of ticks on load would say nothing. */
.saved-dot { display: inline-flex; align-items: center; margin-left: .35rem;
  color: #16a34a; font-size: .85rem; line-height: 1;
  animation: savedIn .18s ease-out; }
.saved-dot:empty { display: none; }
@keyframes savedIn { from { opacity: 0; transform: scale(.7); } }
@media (prefers-reduced-motion: reduce) { .saved-dot { animation: none; } }

/* ── One tab per daily meeting ────────────────────────────────────────────
   A plant holds several stand-ups a morning and each answers to a letter on
   the tier board. The letter chip is on the tab, because which board a room
   feeds is the thing people forget. */
.mt-nav { display: flex; flex-wrap: wrap; gap: .4rem; margin-bottom: 1rem; }
.mt-tab { display: inline-flex; align-items: center; gap: .4rem;
  padding: .45rem .8rem; border-radius: 999px; text-decoration: none;
  border: 1px solid var(--line); background: var(--card);
  color: var(--ink-soft); font-size: .82rem; font-weight: 600;
  transition: background .16s, color .16s, border-color .16s, transform .16s; }
.mt-tab:hover { color: var(--accent); border-color: var(--accent);
  transform: translateY(-1px); }
.mt-tab.is-on { background: var(--accent); border-color: var(--accent);
  color: #fff; }
.mt-tab-letter { display: inline-flex; align-items: center; justify-content: center;
  width: 1.15rem; height: 1.15rem; border-radius: 5px; font-size: .66rem;
  font-weight: 800; color: #fff; }
.mt-tab.is-on .mt-tab-letter { box-shadow: 0 0 0 1px rgba(255,255,255,.55); }
.mt-safety   { background: #0d9488; }
.mt-quality  { background: #1e40af; }
.mt-delivery { background: #0284c7; }
.mt-cost     { background: #d97706; }
.mt-morale   { background: #312e81; }
.mt-tab-open { display: inline-flex; align-items: center; justify-content: center;
  min-width: 1.15rem; height: 1.15rem; padding: 0 .3rem; border-radius: 999px;
  background: color-mix(in srgb, #dc2626 16%, transparent); color: #dc2626;
  font-size: .68rem; font-weight: 800; }
.mt-tab.is-on .mt-tab-open { background: rgba(255,255,255,.25); color: #fff; }

/* The letter this meeting answers to, on the meeting itself. */
.mt-letter { border-left: 4px solid var(--mt-c, #64748b); }
.mt-letter-badge { display: inline-flex; align-items: center; justify-content: center;
  width: 2rem; height: 2rem; border-radius: 9px; background: var(--mt-c, #64748b);
  color: #fff; font-weight: 800; }

/* ── From a letter on the board back to the room it was discussed in ──── */
.sq-rooms { display: flex; flex-wrap: wrap; gap: .3rem; margin-top: .4rem; }
.sq-room { display: inline-flex; align-items: center; gap: .3rem;
  padding: .2rem .55rem; border-radius: 999px; text-decoration: none;
  font-size: .72rem; font-weight: 600; color: #fff;
  background: rgba(255, 255, 255, .18); border: 1px solid rgba(255, 255, 255, .28);
  transition: background .16s; }
.sq-room:hover { background: rgba(255, 255, 255, .3); color: #fff; }
/* Not held yet today — there, but quiet. */
.sq-room.is-idle { opacity: .6; }
.sq-room-n { display: inline-flex; align-items: center; justify-content: center;
  min-width: 1rem; height: 1rem; padding: 0 .25rem; border-radius: 999px;
  background: rgba(0, 0, 0, .28); font-size: .64rem; font-weight: 800; }

/* ── The daily-management board ────────────────────────────────────────────
   Read from the doorway: a letter, three or four trends coloured by their own
   verdict, and the actions against them. Token-driven so it themes, except
   the verdict colours, which are the board's own language and mean the same
   thing in both themes. */
.tb-head { display: flex; align-items: flex-start; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap; margin-bottom: 1rem; }
.tb-eyebrow { font-size: .7rem; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-soft); }
.tb-title { font-size: 1.6rem; font-weight: 800; margin: .1rem 0 .15rem;
  letter-spacing: -.02em; }
.tb-sub { color: var(--ink-soft); font-size: .85rem; }
.tb-head-right { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.tb-periods { display: inline-flex; border: 1px solid var(--line);
  border-radius: 999px; overflow: hidden; background: var(--card); }
.tb-period { padding: .3rem .85rem; font-size: .78rem; font-weight: 700;
  color: var(--ink-soft); text-decoration: none; }
.tb-period + .tb-period { border-left: 1px solid var(--line); }
.tb-period:hover { color: var(--accent); }
.tb-period.is-on { background: var(--accent); color: #fff; }

/* The letter, as it stands this month. */
.tb-hero { display: flex; align-items: center; gap: 1.1rem; flex-wrap: wrap;
  padding: 1rem 1.2rem; border-radius: 16px; margin-bottom: 1.2rem;
  color: #fff; background: linear-gradient(135deg,
    var(--tb, #334155), color-mix(in srgb, var(--tb, #334155) 62%, #0b1220));
  box-shadow: 0 14px 34px rgba(2, 8, 23, .22); }
.tb-hero-letter { flex: 0 0 auto; width: 4.2rem; height: 4.2rem; border-radius: 14px;
  display: flex; align-items: center; justify-content: center;
  font-size: 2.4rem; font-weight: 900; line-height: 1;
  background: rgba(255, 255, 255, .16); border: 1px solid rgba(255, 255, 255, .28); }
.tb-hero-label { font-size: 1.15rem; font-weight: 800; letter-spacing: -.01em; }
.tb-hero-stats { display: flex; gap: .9rem; flex-wrap: wrap; margin: .35rem 0 .2rem; }
.tb-stat { font-size: .78rem; opacity: .92; }
.tb-stat b { font-size: 1.05rem; font-weight: 800; margin-right: .25rem; }
.tb-stat.tb-green b { color: #86efac; }
.tb-stat.tb-red b { color: #fca5a5; }
.tb-hero-mark { font-size: .78rem; opacity: .85; }
.tb-hero-facts { margin-left: auto; max-width: 26rem; padding: .55rem .75rem;
  border-radius: 11px; background: rgba(255, 255, 255, .12); }
.tb-facts-head { font-size: .68rem; font-weight: 800; letter-spacing: .06em;
  text-transform: uppercase; opacity: .8; margin-bottom: .2rem; }
.tb-hero-facts ul { margin: 0; padding-left: 1rem; font-size: .78rem; line-height: 1.45; }

.tb-section { font-size: .76rem; font-weight: 800; letter-spacing: .07em;
  text-transform: uppercase; color: var(--ink-soft);
  margin: 1.3rem 0 .55rem; }
.tb-section span { text-transform: none; letter-spacing: 0; font-weight: 500;
  margin-left: .5rem; }

/* `min(320px, 100%)` rather than a bare 320px: a fixed minimum wider than the
   screen makes the PAGE scroll sideways on a phone, which is the one thing
   `check_responsive` exists to catch. */
.tb-grid { display: grid; gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr)); }
.tb-card { padding: .9rem 1rem 1rem; border-radius: 14px; background: var(--card);
  border: 1px solid var(--line); border-top: 3px solid var(--line); }
/* The latest period decides the card's top edge — the one thing somebody
   scanning a wall of charts actually reads first. */
.tb-card.is-met { border-top-color: #16a34a; }
.tb-card.is-risk { border-top-color: #d97706; }
.tb-card.is-behind { border-top-color: #dc2626; }
.tb-card-head { display: flex; align-items: flex-start; gap: .5rem; }
.tb-card-title { font-weight: 700; font-size: .92rem; line-height: 1.25; }
.tb-card-sub { font-size: .74rem; color: var(--ink-soft); }
.tb-card-link { margin-left: auto; color: var(--ink-soft); font-size: .8rem; }
.tb-card-link:hover { color: var(--accent); }
.tb-card-figure { display: flex; align-items: baseline; gap: .6rem; margin: .5rem 0 .3rem; }
.tb-card-now { font-size: 1.9rem; font-weight: 800; line-height: 1;
  font-variant-numeric: tabular-nums; }
.tb-card-goal { font-size: .74rem; color: var(--ink-soft); font-weight: 600; }
.tb-card-goal.tb-no-goal { font-style: italic; }
/* Not measured yet is a dash, never a zero: "0" is a claim about the month. */
.tb-card-now.tb-no-figure { color: var(--ink-soft); font-weight: 700; }
.tb-canvas { height: 170px; }

.tb-actions tr.tb-late td { background: color-mix(in srgb, #dc2626 6%, transparent); }

/* The month as it stands — one square a day, the strip painted on the wall.
   Unmarked is deliberately hollow: a day nobody looked at must not read as a
   day that held. */
.tb-strip { display: flex; flex-wrap: wrap; gap: 3px; margin-top: .5rem; }
.tb-day { width: 1.35rem; height: 1.35rem; border-radius: 5px; font-size: .6rem;
  font-weight: 700; display: flex; align-items: center; justify-content: center;
  color: rgba(255, 255, 255, .92); background: rgba(255, 255, 255, .13);
  border: 1px solid rgba(255, 255, 255, .18); }
.tb-day.tb-green { background: #16a34a; border-color: #16a34a; }
.tb-day.tb-red { background: #dc2626; border-color: #dc2626; }
.tb-day.is-today { outline: 2px solid rgba(255, 255, 255, .9); outline-offset: 1px; }

.tb-tally { margin-left: auto; float: right; }
.tb-tally b { font-weight: 800; margin: 0 .25rem 0 .6rem; }
.tb-tally .tb-t-open { color: var(--accent); }
.tb-tally .tb-t-late { color: #dc2626; }

/* One objective on its own is the board's headline trend, so it gets the
   height a headline needs rather than a full-width 150px ribbon. */
.tb-grid > .tb-card:only-child .tb-canvas { height: 250px; }

/* What a letter owes — the KPI deck's rule and the board's, read in the room
   where somebody can act on them. Owed now takes a red rail; already being
   worked takes a quiet one, because a list where everything shouts is a list
   nobody reads. */
.lw { border: 1px solid var(--line); border-radius: 14px; background: var(--card);
  overflow: hidden; margin-bottom: 1.1rem; }
.lw-head { padding: .5rem .85rem; font-size: .7rem; font-weight: 800;
  letter-spacing: .06em; text-transform: uppercase; color: var(--ink-soft);
  border-bottom: 1px solid var(--line); }
.lw-head i { margin-right: .35rem; }
.lw-head span { text-transform: none; letter-spacing: 0; font-weight: 500;
  margin-left: .45rem; }
.lw-row { display: flex; align-items: center; gap: .6rem; padding: .55rem .85rem;
  font-size: .86rem; border-left: 3px solid transparent; }
.lw-row + .lw-row { border-top: 1px solid var(--line); }
.lw-row > i { font-size: 1rem; }
.lw-do { border-left-color: #dc2626; background: color-mix(in srgb, #dc2626 5%, transparent); }
.lw-do > i { color: #dc2626; }
.lw-watch { border-left-color: var(--line); }
.lw-watch > i, .lw-watch .lw-text { color: var(--ink-soft); }
.lw-text { flex: 1 1 auto; }
.lw-cta { flex: 0 0 auto; font-size: .78rem; font-weight: 700; text-decoration: none;
  white-space: nowrap; }
.lw-owed { display: inline-block; min-width: 1.15rem; padding: 0 .3rem; margin-left: .4rem;
  border-radius: 999px; background: #dc2626; color: #fff; font-size: .68rem;
  font-weight: 800; text-align: center; }

/* ── A room's board: the letter beside what it owes ─────────────────────── */
.tb-top { display: grid; gap: 1rem; align-items: start; margin-bottom: .4rem;
  grid-template-columns: minmax(0, 300px) minmax(0, 1fr); }
@media (max-width: 991.98px) { .tb-top { grid-template-columns: minmax(0, 1fr); } }
/* The letter card is the SQDCM board's own `.sq-card`; here it is one card
   rather than five, so it does not need the row's width rules. */
.tb-letter { margin: 0; }
.tb-letter .sq-means { margin: .6rem .9rem 0; }
.tb-letter-mark { padding: .55rem .9rem .2rem; font-size: .8rem; }
.tb-mark { display: inline-flex; align-items: center; gap: .35rem; font-weight: 600; }
.tb-mark i { font-size: .95rem; }
.tb-mark-green { color: #16a34a; }
.tb-mark-red { color: #dc2626; }
.tb-mark-none { color: var(--ink-soft); font-weight: 500; }
.tb-facts { margin: .3rem .9rem .9rem; padding: .5rem .7rem; border-radius: 10px;
  background: var(--surface-2); }
.tb-facts .tb-facts-head { color: var(--ink-soft); }
.tb-facts ul { margin: 0; padding-left: 1rem; font-size: .78rem; line-height: 1.45;
  color: var(--ink); }
/* The launch room has no letter and does not pretend to: same tile, a glyph
   of its own, and the three numbers the programmes actually carry. */
/* The launch room's tile: the same gradient family the five letters use —
   `--g1`/`--g2` are what `.sq-hero` paints with, and a card that set only
   `--dim` rendered white text on a white ground. Indigo because it is the
   one hue no letter owns. */
.tb-launch { --dim: #4338ca; --g1: #6366f1; --g2: #3730a3; }
.tb-launch-glyph { display: flex; align-items: center; justify-content: center;
  height: 150px; font-size: 4.4rem; color: rgba(255, 255, 255, .92);
  text-shadow: 0 6px 18px rgba(2, 6, 23, .35); }
.tb-letterless { display: flex; align-items: center; justify-content: center;
  min-height: 190px; text-align: center; }
.tb-letterless-body { padding: 1.2rem; color: var(--ink-soft); }
.tb-letterless-body i { font-size: 2rem; display: block; margin-bottom: .5rem; }
.tb-grid-tight { grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr)); }
.tb-top-right .tb-section:first-child { margin-top: 0; }
