/* shared.css — Beyond Appliances Dashboard
   Loaded on every page. Page-specific CSS lives in each template's <style> block. */
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
:root{
  --sb:#0f0f0f;--sb-bd:#1e1e1e;
  --sb-t1:#fff;--sb-t2:#888;--sb-t3:#555;
  /* Controls sitting ON the dark chrome (topbar selects, date button, dark toggles):
     a step lighter than the bar so they read as raised. */
  --sb-ctl:#1a1a1a;--sb-ctl-bd:#333;
  --acc:#c8a96e;--sb-acc:var(--acc);
  /* Gold as TEXT on light surfaces: the accent itself is too light to read. */
  --acc-t:color-mix(in srgb, var(--acc) 62%, var(--t1));
  /* Topbar chrome — SAME black as the sidebar so the two read as one
     continuous L-shaped frame around the content, not two adjacent panels. */
  --top:var(--sb);--top-bd:var(--sb-bd);
  /* Warm paper canvas + borderless, shadow-elevated cards
     (border kept near-invisible so card layouts don't shift). */
  --page:#f3f1ec;--white:#fff;
  --bd:#eceae4;--card-bd:var(--bd);
  --sh:0 1px 2px rgba(60,50,30,.04),0 4px 10px rgba(60,50,30,.04),0 14px 36px rgba(60,50,30,.07);--card-sh:var(--sh);
  --sh-hover:0 2px 4px rgba(60,50,30,.05),0 10px 22px rgba(60,50,30,.07),0 22px 48px rgba(60,50,30,.09);
  --t1:#0f0f0f;--t2:#444;--t3:#999;
  --grn:#16a34a;--grn-bg:#f0fdf4;--grn-bd:#bbf7d0;
  --red:#dc2626;--red-bg:#fef2f2;--red-bd:#fecaca;
  --amb:#d97706;--amb-bg:#fffbeb;--amb-bd:#fde68a;
  --blue:#2171b5;--purple:#9333ea;
  /* Categorical chart palette — one fixed hue order, assigned by entity (never
     cycled). Validated for CVD separation + contrast (worst adjacent ΔE 24.2).
     Used via window.CHART_PALETTE / catColor() in dashutil.js so a category
     keeps the same colour on every page. */
  --cat1:#2a78d6;--cat2:#1baf7a;--cat3:#eda100;--cat4:#008300;
  --cat5:#4a3aa7;--cat6:#e34948;--cat7:#e87ba4;--cat8:#eb6834;
  --mp:#111;--mp-bd:#222;--mp-t1:#f5f5f5;--mp-t2:#999;--mp-t3:#555;
  --teal:#0e7490;--teal-bg:#ecfeff;
  --sw:168px;--r:14px;--radius:var(--r);
  /* Secondary light surfaces (table heads, hovers, footers). */
  --sub:#f8f9fa;--hover:#fafbfc;--foot:#f0f2f5;
}
html,body{height:100%;font-family:'Inter',sans-serif;background:var(--page);color:var(--t1);font-size:13px;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
/* Tabular figures everywhere numbers stack vertically — columns of amounts
   align digit-for-digit instead of wobbling with proportional widths. */
.main table td,.kpi-val,.kpi-sub,.kpi-comp-val{font-variant-numeric:tabular-nums}
/* Consistent, accessible focus ring on every interactive control. */
.main button:focus-visible,.main select:focus-visible,.main input:focus-visible,.main a:focus-visible{outline:2px solid var(--acc);outline-offset:2px;border-radius:6px}
/* Refined scrollbars (both themes) */
.main::-webkit-scrollbar{width:9px;height:9px}
.main::-webkit-scrollbar-thumb{background:rgba(127,130,140,.35);border-radius:5px;border:2px solid transparent;background-clip:content-box}
.main::-webkit-scrollbar-track{background:transparent}

/* ── LAYOUT ── */
.layout{display:flex;flex:1;min-height:0}

/* ── SIDEBAR ── */
.sidebar{width:var(--sw);min-width:var(--sw);background:var(--sb);display:flex;flex-direction:column;flex-shrink:0;overflow-y:auto;scrollbar-width:none}
.sidebar::-webkit-scrollbar{display:none}
.brand{padding:20px 18px 16px;border-bottom:1px solid var(--sb-bd)}
.brand-home{display:inline-block;border-radius:6px;transition:opacity .15s}
.brand-home:hover{opacity:.8}
.brand-home:focus-visible{outline:2px solid var(--acc);outline-offset:4px}
.brand-tag{font-size:11px;font-weight:500;display:flex;align-items:center;gap:4px}
.brand-tag .s1{color:var(--sb-t2)}.brand-tag .s2{color:var(--acc);font-weight:700}
/* Nav items are rounded pills (inset from the sidebar edges) with a small
   floating gold indicator bar on the active one — replaces the old flat
   full-width highlight + hard border-left. */
.nav{padding:8px;border-bottom:1px solid var(--sb-bd)}
.nav-item{display:block;position:relative;padding:8px 12px;margin:1px 0;font-size:12px;font-weight:500;color:#b9bcc2;cursor:pointer;text-decoration:none;transition:.15s;border-radius:8px;letter-spacing:.1px}
.nav-item:hover{color:var(--sb-t1);background:rgba(255,255,255,.05)}
.nav-item.active{color:var(--sb-t1);background:rgba(255,255,255,.08);font-weight:600}
.nav-item.active::before{content:'';position:absolute;left:0;top:50%;transform:translateY(-50%);width:3px;height:15px;border-radius:2px;background:var(--acc)}
/* ── OPS GROUP ── */
.nav-group{position:relative}
.nav-group-btn{display:flex;align-items:center;justify-content:space-between;position:relative;padding:8px 12px;margin:1px 0;font-size:12px;font-weight:500;color:#b9bcc2;cursor:pointer;text-decoration:none;transition:.15s;border-radius:8px;letter-spacing:.1px;user-select:none}
.nav-group-btn:hover{color:var(--sb-t1);background:rgba(255,255,255,.05)}
.nav-group-btn.active{color:var(--sb-t1);background:rgba(255,255,255,.08);font-weight:600}
.nav-group-btn.active::before{content:'';position:absolute;left:0;top:50%;transform:translateY(-50%);width:3px;height:15px;border-radius:2px;background:var(--acc)}
.nav-group-arrow{font-size:9px;opacity:.5;transition:transform .2s}
.nav-group.open .nav-group-arrow{transform:rotate(90deg)}
.nav-sub{display:none;overflow:hidden}
.nav-group.open .nav-sub{display:block}
.nav-sub-item{display:block;position:relative;padding:6px 12px 6px 24px;margin:1px 0;font-size:11px;font-weight:500;color:#a4a8af;text-decoration:none;transition:.15s;border-radius:8px;letter-spacing:.1px}
.nav-sub-item:hover{color:var(--sb-t1);background:rgba(255,255,255,.05)}
.nav-sub-item.active{color:var(--sb-t1);background:rgba(255,255,255,.07);font-weight:600}
.nav-sub-item.active::before{content:'';position:absolute;left:10px;top:50%;transform:translateY(-50%);width:3px;height:12px;border-radius:2px;background:var(--acc)}
/* The gold active-indicator grows in when a nav item becomes active, so
   switching pages feels responsive rather than a hard jump. */
@keyframes navBarIn{from{opacity:0;transform:translateY(-50%) scaleY(.35)}to{opacity:1;transform:translateY(-50%) scaleY(1)}}
.nav-item.active::before,.nav-group-btn.active::before,.nav-sub-item.active::before{animation:navBarIn .2s ease-out}

/* Respect the OS "reduce motion" setting: drop the decorative hover lifts and
   the nav-indicator/menu animations. The functional loading bar + spinner keep
   animating — they convey live state, not decoration. */
@media (prefers-reduced-motion: reduce){
  .card,.kpi,.kpi-drillable,.nav-item,.nav-group-btn,.nav-sub-item,.li,.btn-export,.date-btn,.mt-btn{transition:none!important}
  .kpi:hover,.kpi-drillable:hover{transform:none!important}
  .card:hover{box-shadow:var(--sh)!important}
  .nav-item.active::before,.nav-group-btn.active::before,.nav-sub-item.active::before{animation:none!important}
  .sidebar.nav-open .nav{animation:none!important}
}
.filters{padding:16px 14px 0;flex:1}
.fl{margin-bottom:14px}
.fl-label{font-size:9px;letter-spacing:1.2px;color:#8b9097;text-transform:uppercase;margin-bottom:5px;display:block;font-weight:600}
.fl-sel{width:100%;background:#1a1a1a;border:1px solid #2a2a2a;color:#aaa;font-size:11px;font-family:'Inter',sans-serif;padding:7px 24px 7px 10px;border-radius:8px;cursor:pointer;appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23666' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 8px center;transition:.15s}
.fl-sel:hover{border-color:#3a3a3a}
.fl-sel:focus{outline:none;border-color:var(--acc)}
.fl-sel option{background:#1a1a1a}
.reset-btn{display:block;width:calc(100% - 28px);margin:4px 14px 18px;padding:8px;background:transparent;border:1px solid #2a2a2a;color:var(--sb-t3);font-size:11px;font-family:'Inter',sans-serif;border-radius:8px;cursor:pointer;transition:.15s;font-weight:500;letter-spacing:.2px}
.reset-btn:hover{border-color:var(--acc);color:var(--acc);background:rgba(200,169,110,.06)}

/* ── MULTI-SELECT DROPDOWN ── */
.ms-wrap{position:relative;width:100%}
.ms-btn{width:100%;background:#1a1a1a;border:1px solid #2a2a2a;color:#aaa;font-size:11px;font-family:'Inter',sans-serif;padding:7px 24px 7px 10px;border-radius:8px;cursor:pointer;text-align:left;display:flex;align-items:center;justify-content:space-between;transition:.15s;box-sizing:border-box;gap:4px}
.ms-btn:hover{border-color:#3a3a3a}.ms-btn.open{border-color:var(--acc)}
.ms-arrow{opacity:.5;font-size:9px;flex-shrink:0}
.ms-label{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
.ms-badge{background:var(--acc);color:#000;font-size:9px;font-weight:700;padding:1px 5px;border-radius:10px;flex-shrink:0;vertical-align:middle;margin-left:3px}
.ms-dropdown{position:absolute;top:calc(100% + 4px);left:0;right:0;background:#1e1e1e;border:1px solid #2a2a2a;border-radius:8px;z-index:1000;max-height:200px;overflow-y:auto;box-shadow:0 8px 24px rgba(0,0,0,.5)}
.ms-dropdown::-webkit-scrollbar{width:3px}.ms-dropdown::-webkit-scrollbar-thumb{background:#3a3a3a;border-radius:2px}
.ms-item{display:flex;align-items:center;gap:8px;padding:7px 10px;cursor:pointer;transition:.1s;font-size:11px;color:#888;border-bottom:1px solid #252525}
.ms-item:last-child{border-bottom:none}.ms-item:hover{background:rgba(255,255,255,.05);color:#fff}
.ms-item.checked{color:#ddd}
.ms-check{width:13px;height:13px;border:1px solid #3a3a3a;border-radius:3px;flex-shrink:0;display:flex;align-items:center;justify-content:center;font-size:9px;transition:.1s;background:transparent}
.ms-item.checked .ms-check{background:var(--acc);border-color:var(--acc);color:#000}

/* ── MAIN ── */
.main{flex:1;min-width:0;display:flex;flex-direction:column;overflow-y:auto;height:100vh}

/* ── GLOBAL TABLE FORMATTING (consistent across every page) ──
   Header row bold, all data centred, first column left-aligned + bold.
   Scoped to .main and !important so each page's own table CSS stays uniform. */
.main table th{text-align:center!important;font-weight:700!important}
.main table th:first-child{text-align:left!important}
.main table td{text-align:center!important;vertical-align:middle}
.main table td:first-child{text-align:left!important;font-weight:700!important}

/* ── TOPBAR ── */
.topbar{background:var(--top);padding:10px 20px;display:flex;align-items:center;gap:12px;flex-shrink:0;position:sticky;top:0;z-index:100;border-bottom:1px solid var(--top-bd);box-shadow:0 6px 20px rgba(20,15,5,.08)}
.topbar-title{font-size:14px;font-weight:700;color:#fff;letter-spacing:-.2px}
.date-btn{display:flex;align-items:center;gap:8px;background:var(--sb-ctl);border:1px solid var(--sb-ctl-bd);color:#aaa;font-size:12px;font-family:'Inter',sans-serif;padding:7px 14px;border-radius:8px;cursor:pointer;transition:.15s;white-space:nowrap;font-weight:500}
.date-btn:hover{border-color:#555;color:#fff}
.date-btn .arr{color:#555;font-size:10px;margin-left:2px}
.metric-toggle{display:flex;background:#1a1a1a;border:1px solid #333;border-radius:8px;overflow:hidden;margin-left:auto}
.mt-btn{padding:6px 20px;font-size:11px;font-family:'Inter',sans-serif;font-weight:600;cursor:pointer;border:none;background:transparent;color:#555;transition:.15s;letter-spacing:.3px}
.mt-btn.active{background:var(--white);color:#111;border-radius:6px;margin:2px}
.mt-btn:not(.active):hover{color:#ccc}

/* ── DATE PICKER ── */
.date-panel{position:absolute;top:calc(100% + 6px);left:20px;z-index:999;background:var(--white);border:1px solid var(--bd);border-radius:14px;box-shadow:0 12px 40px rgba(0,0,0,.12);display:none;overflow:hidden;min-width:650px}
.date-panel.open{display:flex}
.dp-presets{width:145px;border-right:1px solid #f0f0f0;padding:10px 0;background:#fafafa;flex-shrink:0}
.dp-preset{padding:9px 18px;font-size:12px;color:#777;cursor:pointer;border-left:3px solid transparent;transition:.15s;font-weight:500}
.dp-preset:hover{color:var(--t1);background:#f0f0f0}
.dp-preset.active{color:#111;border-left-color:#111;background:#ebebeb;font-weight:600}
.dp-cals{flex:1;padding:16px 18px}
.dp-hdr{display:flex;justify-content:space-between;align-items:center;margin-bottom:14px}
.dp-range{font-size:12px;color:var(--t2);background:#f5f5f5;border:1px solid #eee;border-radius:8px;padding:6px 14px;display:flex;gap:10px;align-items:center}
.dp-range .dv{color:var(--t1);font-weight:700}
.dp-done{background:#111;color:#fff;border:none;border-radius:8px;padding:7px 22px;font-size:12px;font-weight:600;font-family:'Inter',sans-serif;cursor:pointer;transition:.15s}
.dp-done:hover{background:#333}
.dp-months{display:flex;gap:24px}
.dp-month{flex:1}
.dp-mnav{display:flex;align-items:center;justify-content:space-between;margin-bottom:10px}
.dp-mnav span{font-size:13px;font-weight:700;color:var(--t1)}
.dp-nbtn{background:none;border:1px solid #e8e8e8;color:#999;cursor:pointer;font-size:16px;padding:2px 8px;border-radius:6px;transition:.15s;line-height:1.4}
.dp-nbtn:hover{color:var(--t1);border-color:#bbb}
.dp-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}
.dp-dow{text-align:center;font-size:10px;color:#bbb;padding:3px 0 6px;font-weight:600;letter-spacing:.5px}
.dp-day{text-align:center;padding:6px 2px;border-radius:6px;cursor:pointer;font-size:12px;color:#666;transition:.1s;user-select:none;font-weight:500}
.dp-day:hover{background:#f0f0f0;color:var(--t1)}
.dp-day.dp-o{color:#ddd;cursor:default}
.dp-day.dp-today{color:#6366f1;font-weight:700}
.dp-day.dp-ir{background:#f0f0f0;border-radius:0;color:var(--t1)}
.dp-day.dp-s,.dp-day.dp-e{background:#111!important;color:#fff!important;font-weight:700;border-radius:6px!important}
.dp-day.dp-s{border-radius:6px 0 0 6px!important}
.dp-day.dp-e{border-radius:0 6px 6px 0!important}
.dp-day.dp-s.dp-e{border-radius:6px!important}

/* ── PILL BAR ── */
.pill-bar{background:#f8f8f8;border-bottom:1px solid #ebebeb;padding:6px 20px;display:flex;flex-wrap:wrap;gap:6px;align-items:center;min-height:34px;flex-shrink:0}
.pill{display:inline-flex;align-items:center;gap:5px;background:#111;color:#fff;font-size:10px;padding:4px 10px 4px 12px;border-radius:20px;font-weight:600;letter-spacing:.2px}
.pill-x{cursor:pointer;opacity:.5;font-size:11px;transition:.15s}.pill-x:hover{opacity:1}
.pill-hint{font-size:10px;color:#bbb;font-style:italic;font-weight:400}

/* ── LOADING & ERROR ── */
/* Non-blocking loading: a slim animated bar along the top plus a small corner
   spinner — content stays visible (no white blanket) so filter changes don't
   flash the whole page. */
.loading{position:fixed;top:0;left:0;right:0;height:3px;z-index:9999;opacity:0;pointer-events:none;transition:opacity .15s;overflow:hidden;background:rgba(99,102,241,.15)}
.loading.show{opacity:1}
.loading::after{content:'';position:absolute;top:0;left:-40%;width:40%;height:100%;background:linear-gradient(90deg,transparent,#6366f1,transparent);animation:loadbar 1s ease-in-out infinite}
@keyframes loadbar{0%{left:-40%}100%{left:100%}}
.spinner{position:fixed;top:12px;right:14px;width:18px;height:18px;border:2.5px solid rgba(224,224,224,.6);border-top-color:#6366f1;border-radius:50%;animation:spin .7s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
@keyframes fadeUp{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}
.err-banner{display:none;align-items:center;gap:12px;background:#fef2f2;border-bottom:1px solid #fecaca;padding:10px 20px;color:#991b1b;font-size:12px;font-weight:500;flex-shrink:0}
.err-banner.show{display:flex}
.err-banner .err-icon{font-size:15px;flex-shrink:0}
.err-banner .err-msg{flex:1;white-space:pre-line}
.err-banner .err-retry{background:#991b1b;color:#fff;border:none;border-radius:6px;padding:5px 14px;font-size:11px;font-weight:600;cursor:pointer;font-family:'Inter',sans-serif;flex-shrink:0;transition:.15s}
.err-banner .err-retry:hover{background:#7f1d1d}

/* ── SHARED CARD & CHART PRIMITIVES ── */
.card{background:var(--white);border:1px solid var(--bd);border-radius:var(--r);box-shadow:var(--sh);padding:14px 16px;display:flex;flex-direction:column;overflow:hidden;transition:box-shadow .18s ease}
/* Subtle hover elevation to match the KPI cards, giving the whole dashboard
   some tactile life. Shadow only — deliberately NO transform: a transformed
   ancestor becomes the containing block for position:fixed descendants, which
   would break the map tooltip / any popover that lives inside a card. */
.card:hover{box-shadow:var(--sh-hover)}
.ph{display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;flex-shrink:0;gap:8px}
.pt{font-size:13px;font-weight:700;color:var(--t1);letter-spacing:-.1px}
/* Card-header subtitle — the small muted caption next to a .pt title. Was
   inline-styled (font-size:10px;color:var(--t3)) on ~70 spans across the app;
   this is the single source so it can be retuned in one place. */
.ph-sub{font-size:10px;color:var(--t3)}
.cwrap{flex:1;position:relative;min-height:0}

/* ── PAGE COMPONENT LIBRARY (canonical — pages no longer redefine these) ──
   KPI cards, page shell, standard tables and empty-states. Grids use
   auto-fit so they are responsive by default and no page needs to hard-code
   a column count. A page may still add a SCOPED override (e.g. `.kpis2 .kpi-val`)
   for a genuine one-off. */
.page{padding:14px 16px 40px;display:flex;flex-direction:column;gap:14px}
.kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px}
/* ── KPI GUTTER (single source of truth) ──────────────────────────────────
   A KPI row placed directly inside .main sits OUTSIDE the padded .page /
   .content wrapper, so it has no gutter of its own and its cards would run
   flush into the sidebar. This gives every such strip the same 16px side
   gutter the content cards below already have, so the left edges line up on
   every page. Direct-child (>) on purpose: a .kpis nested inside .page
   (targets, pl, pl_analysis) already inherits the gutter and must not be
   double-padded. Horizontal only — each page keeps its own vertical rhythm. */
.main > .kpis,.main > .kpi-strip{padding-left:16px;padding-right:16px}
.kpi{background:var(--white);border:1px solid var(--bd);border-radius:12px;padding:12px 14px;position:relative;overflow:hidden;box-shadow:var(--sh);transition:transform .15s ease,box-shadow .15s ease}
.kpi:hover{transform:translateY(-2px);box-shadow:var(--sh-hover)}
.kpi-lbl{font-size:9px;font-weight:700;color:var(--t3);letter-spacing:.7px;text-transform:uppercase;margin-bottom:4px}
.kpi-val{font-size:20px;font-weight:800;color:var(--t1);line-height:1.05;letter-spacing:-.5px}
.kpi-sub{font-size:10px;color:var(--t3);margin-top:3px}
.kpi.good .kpi-val{color:var(--grn)}
.kpi.warn .kpi-val{color:var(--amb)}
.kpi.bad .kpi-val{color:var(--red)}
.row2{display:grid;grid-template-columns:1.3fr 1fr;gap:14px}
.tbl-card{background:var(--white);border:1px solid var(--bd);border-radius:var(--r);box-shadow:var(--sh);overflow:hidden}
.tbl-hd{display:flex;align-items:center;justify-content:space-between;padding:11px 16px;border-bottom:1px solid var(--bd);gap:10px;flex-wrap:wrap}
.tbl-wrap{max-height:520px;overflow:auto}
.empty{padding:24px;text-align:center;color:#bbb;font-size:12px}
.gran-sel{background:#f5f5f5;border:1px solid #eee;color:var(--t2);font-size:11px;font-family:'Inter',sans-serif;font-weight:500;padding:5px 24px 5px 10px;border-radius:7px;cursor:pointer;appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23999' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 7px center}
.gran-sel:focus{outline:none}
.up{color:var(--grn);font-weight:700}.dn{color:var(--red);font-weight:700}.nt{color:var(--t3)}
.sec-hd{font-size:9px;font-weight:700;color:var(--t3);letter-spacing:1.4px;text-transform:uppercase;display:flex;align-items:center;gap:8px}
.sec-hd::after{content:'';flex:1;height:1px;background:var(--bd)}
.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;color:#bbb;font-size:12px;gap:6px;text-align:center;padding:20px}
.empty-state .es-icon{font-size:26px;opacity:.5}

/* ── DATA-QUALITY BADGE ──
   Small "N% verified" trust signal (currently on the Geography map). The dot
   colour is set inline in JS from the live percentage (green/amber/red); the
   layout + muted text come from here so it matches the rest of the system. */
.dq-badge{display:none;align-items:center;gap:5px;margin-top:6px;font-size:10px;color:var(--t3);font-weight:600}
.dq-badge.show{display:flex}
.dq-badge .dq-dot{width:7px;height:7px;border-radius:50%;background:var(--grn);display:inline-block}

/* ── KPI COMPARISON ROWS (shared by index/sales/marketing) ── */
.kpi-comps{margin-top:8px;display:flex;flex-direction:column;gap:3px;border-top:1px solid var(--bd);padding-top:7px}
.kpi-comp-row{display:flex;align-items:center;justify-content:space-between;font-size:9.5px}
.kpi-comp-label{color:var(--t3);font-weight:500}
.kpi-comp-right{display:flex;align-items:center;gap:4px}
.kpi-comp-val{color:var(--t2);font-weight:600}

/* ── DONUT LEGEND (shared by index/marketing) ── */
.drow{flex:1;display:flex;align-items:center;gap:16px;margin-top:10px}
.dwrap{width:160px;height:160px;flex-shrink:0}
.dleg{flex:1}
.li{display:flex;align-items:center;gap:8px;margin-bottom:7px;font-size:11px;color:var(--t2);cursor:pointer;padding:4px 6px;border-radius:6px;transition:.15s;font-weight:500}
.li:hover{background:#f5f5f5;color:var(--t1)}
.li.act{background:#f0f0f0;font-weight:700;color:var(--t1)}
.li.dim{opacity:.3}
.ldot{width:10px;height:10px;border-radius:3px;flex-shrink:0}
.lpct{color:var(--t3);font-size:10px;margin-left:auto;font-weight:600}

/* ── EXPORT BUTTON ── */
.btn-export{display:inline-flex;align-items:center;gap:5px;font-size:11px;font-weight:600;color:#16a34a;background:#f0fdf4;border:1px solid #bbf7d0;border-radius:6px;padding:4px 10px;cursor:pointer;transition:.15s;white-space:nowrap;margin-left:auto}
.btn-export:hover{background:#dcfce7;border-color:#86efac}

/* ── NAV ALERT BADGE ── */
.nav-badge{display:inline-block;background:var(--red);color:#fff;font-size:9px;font-weight:700;min-width:16px;text-align:center;padding:1px 5px;border-radius:10px;margin-left:4px;vertical-align:middle}

/* ── DASHBOARD: DAILY BRIEFING LINK ── */
.briefing-link{margin-left:auto;display:inline-flex;align-items:center;gap:6px;background:linear-gradient(135deg,#c8a96e,#b8915a);color:#1a1a1a;font-size:12px;font-weight:700;font-family:'Inter',sans-serif;padding:8px 16px;border-radius:8px;text-decoration:none;white-space:nowrap;transition:.15s;border:1px solid rgba(255,255,255,.12)}
.briefing-link:hover{filter:brightness(1.08);transform:translateY(-1px)}

/* ── PROFILE / SETTINGS MENU (top-right corner) ── */
.profile{position:fixed;top:9px;right:14px;z-index:300}
.profile-btn{background:none;border:none;padding:0;cursor:pointer;display:block}
.profile-avatar{width:32px;height:32px;border-radius:50%;background:var(--acc);color:#1a1a1a;font-weight:800;font-size:13px;display:flex;align-items:center;justify-content:center;box-shadow:0 1px 4px rgba(0,0,0,.3);border:2px solid rgba(255,255,255,.15);transition:.15s}
.profile-btn:hover .profile-avatar{filter:brightness(1.08)}
.profile-avatar.gear{background:#2a2a2a;color:#bbb;font-size:15px}
.profile-avatar.lg{width:40px;height:40px;font-size:16px}
.profile-menu{position:absolute;top:42px;right:0;width:236px;background:var(--white);border:1px solid var(--bd);border-radius:14px;box-shadow:0 16px 48px rgba(0,0,0,.18);padding:8px;display:none;animation:fadeUp .14s ease}
.profile.open .profile-menu{display:block}
.profile-head{display:flex;align-items:center;gap:11px;padding:8px 9px 11px}
.profile-id{min-width:0}
.profile-name{font-size:13px;font-weight:700;color:var(--t1);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.profile-role{display:inline-block;margin-top:3px;font-size:8px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 7px;border-radius:8px}
.profile-role.role-admin{background:#eef2ff;color:#4f46e5}
.profile-role.role-member{background:#f1f5f9;color:#64748b}
.profile-sep{height:1px;background:var(--bd);margin:4px 2px}
.profile-item{display:flex;align-items:center;width:100%;text-align:left;background:none;border:none;padding:9px 10px;border-radius:9px;font-size:12px;font-weight:600;font-family:'Inter',sans-serif;color:var(--t2);cursor:pointer;text-decoration:none;transition:.12s}
.profile-item:hover{background:var(--page);color:var(--t1)}
.profile-item.active{background:var(--page);color:var(--t1)}
.profile-item.danger{color:var(--red)}
.profile-item.danger:hover{background:var(--red-bg)}
.profile-item:disabled{opacity:.6;cursor:default}
.profile-sync .sync-status{font-size:9.5px;color:var(--t3);padding:0 10px 4px;line-height:1.4}
.profile-sync .sync-status.running{color:var(--amb)}
.profile-sync .sync-status.err{color:var(--red)}
/* reserve room at the right of every page topbar for the floating profile */
.topbar{padding-right:58px}

/* ── VELOCITY SIGNAL ── */
.vel{font-size:11px;font-weight:700;display:inline-flex;align-items:center;gap:2px}
.vel-up{color:var(--red)}      /* demand rising = stockout risk */
.vel-down{color:var(--blue)}   /* demand falling = overstock risk */
.vel-flat{color:var(--t3)}

/* ── ALERTS PAGE ── */
.alert-tabs{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:14px}
.alert-tab{display:flex;align-items:center;gap:8px;background:var(--white);border:1px solid var(--bd);border-radius:10px;padding:10px 16px;cursor:pointer;transition:.15s;box-shadow:var(--sh)}
.alert-tab:hover{border-color:#cbd2da}
.alert-tab.active{border-color:var(--t1);box-shadow:0 0 0 1px var(--t1)}
.alert-tab .at-n{font-size:18px;font-weight:800;line-height:1}
.alert-tab .at-l{font-size:11px;color:var(--t2);font-weight:600}
.alert-tab.crit .at-n{color:var(--red)}
.alert-tab.warn .at-n{color:var(--amb)}
.alert-tab.info .at-n{color:var(--blue)}
.badge-pill{font-size:9px;font-weight:700;padding:2px 8px;border-radius:10px;text-transform:uppercase;letter-spacing:.3px}
.bp-crit{background:var(--red-bg);color:var(--red);border:1px solid var(--red-bd)}
.bp-high{background:var(--amb-bg);color:var(--amb);border:1px solid var(--amb-bd)}
.bp-plan{background:#eef2ff;color:#4f46e5;border:1px solid #c7d2fe}
.bp-ok{background:var(--grn-bg);color:var(--grn);border:1px solid var(--grn-bd)}

/* ── Toast notifications ── */
#toastWrap{position:fixed;bottom:20px;right:20px;z-index:9000;display:flex;flex-direction:column;gap:8px;align-items:flex-end}
.toast{display:flex;align-items:center;gap:10px;background:#1c1c1e;color:#eee;border-radius:11px;padding:11px 16px;font-size:12.5px;font-weight:500;font-family:'Inter',sans-serif;box-shadow:0 10px 30px rgba(0,0,0,.25);max-width:380px;opacity:0;transform:translateY(8px);transition:.25s;cursor:pointer}
.toast.show{opacity:1;transform:translateY(0)}
.toast-ico{width:19px;height:19px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:800;flex-shrink:0}
.toast-success .toast-ico{background:var(--grn);color:#fff}
.toast-error .toast-ico{background:var(--red);color:#fff}
.toast-info .toast-ico{background:#6366f1;color:#fff}

/* ── Styled confirm dialog (replaces native confirm) ── */
.confirm-back{position:fixed;inset:0;background:rgba(15,15,15,.5);z-index:9100;display:flex;align-items:center;justify-content:center;opacity:0;transition:.15s}
.confirm-back.open{opacity:1}
.confirm-card{background:var(--white);border-radius:14px;width:340px;max-width:90vw;padding:20px 22px;box-shadow:0 24px 64px rgba(0,0,0,.3);transform:translateY(6px);transition:.15s}
.confirm-back.open .confirm-card{transform:translateY(0)}
.confirm-msg{font-size:13px;color:var(--t1);line-height:1.55;margin-bottom:16px;font-weight:500;white-space:pre-line}
.confirm-actions{display:flex;gap:9px;justify-content:flex-end}
.confirm-cancel{background:none;border:1px solid var(--bd);color:var(--t2);padding:8px 15px;border-radius:8px;cursor:pointer;font-size:12.5px;font-weight:600;font-family:'Inter',sans-serif}
.confirm-ok{background:var(--acc,#c8a96e);border:none;color:#000;font-weight:700;padding:8px 17px;border-radius:8px;cursor:pointer;font-size:12.5px;font-family:'Inter',sans-serif}
.confirm-ok.danger{background:var(--red);color:#fff}

/* ── Sortable table headers ── */
.main table thead th{cursor:pointer;user-select:none}
.main table[data-nosort] thead th{cursor:default}
.main table thead th.sort-desc::after{content:' ▼';font-size:8px;color:#6366f1}
.main table thead th.sort-asc::after{content:' ▲';font-size:8px;color:#6366f1}

/* ── Command palette (Ctrl/Cmd+K) ── */
.cmdk-back{position:fixed;inset:0;background:rgba(10,10,12,.55);backdrop-filter:blur(2px);z-index:9200;display:none;align-items:flex-start;justify-content:center;padding-top:12vh}
.cmdk-back.open{display:flex}
.cmdk{width:560px;max-width:92vw;background:var(--white);border:1px solid var(--bd);border-radius:16px;box-shadow:0 32px 80px rgba(0,0,0,.4);overflow:hidden}
.cmdk-input{width:100%;border:none;outline:none;background:transparent;padding:16px 18px;font-size:15px;font-family:'Inter',sans-serif;color:var(--t1);border-bottom:1px solid var(--bd)}
.cmdk-list{max-height:340px;overflow-y:auto;padding:6px}
.cmdk-item{display:flex;align-items:center;gap:11px;padding:9px 12px;border-radius:9px;cursor:pointer;font-size:13px;color:var(--t2)}
.cmdk-item .ck-ico{width:24px;height:24px;border-radius:7px;background:var(--sub);display:flex;align-items:center;justify-content:center;font-size:12px;flex-shrink:0}
.cmdk-item .ck-kind{margin-left:auto;font-size:9px;font-weight:700;color:var(--t3);text-transform:uppercase;letter-spacing:.6px}
.cmdk-item.sel{background:var(--sub);color:var(--t1)}
.cmdk-item.sel .ck-ico{background:var(--acc);color:#000}
.cmdk-empty{padding:22px;text-align:center;color:var(--t3);font-size:12.5px}
.cmdk-foot{display:flex;gap:14px;padding:8px 16px;border-top:1px solid var(--bd);font-size:10px;color:var(--t3)}
.cmdk-foot kbd{background:var(--sub);border:1px solid var(--bd);border-radius:4px;padding:1px 5px;font-family:'Inter',sans-serif;font-size:9px;font-weight:700}
.cmdk-hint{display:none;align-items:center;gap:6px;background:#1a1a1a;border:1px solid #333;color:#777;font-size:10px;padding:5px 10px;border-radius:7px;cursor:pointer;font-family:'Inter',sans-serif;white-space:nowrap}
.cmdk-hint kbd{background:#242424;border:1px solid #3a3a3a;border-radius:4px;padding:1px 5px;font-size:9px;font-weight:700;color:#999;font-family:'Inter',sans-serif}
.cmdk-hint:hover{color:#bbb;border-color:#555}
@media (min-width:861px){.cmdk-hint{display:inline-flex}}

/* ── Topbar notification bell (reusable — see dashutil.js initBell) ──
   Any page can drop <div id="X-bell">...</div> markup matching this
   structure and call initBell({...}) to get a working bell with zero
   page-specific CSS. Used for page-specific "needs attention" lists —
   PL rate-coverage gaps, PO overdue, low-stock, etc. */
.bell-btn{position:relative;background:#1a1a1a;border:1px solid #333;color:#ccc;font-size:15px;padding:7px 11px;border-radius:8px;cursor:pointer;transition:.15s;line-height:1}
.bell-btn:hover{border-color:#555}
.bell-badge{position:absolute;top:-5px;right:-5px;background:var(--red);color:#fff;font-size:9px;font-weight:800;min-width:16px;height:16px;border-radius:9px;display:flex;align-items:center;justify-content:center;padding:0 3px}
.bell-panel{position:absolute;top:calc(100% + 8px);right:0;width:380px;max-height:440px;overflow-y:auto;background:var(--white);border:1px solid var(--bd);border-radius:12px;box-shadow:0 16px 48px rgba(0,0,0,.25);display:none;z-index:1000;padding:14px}
.bell-panel.open{display:block}
.bell-hd{font-size:13px;font-weight:800;color:var(--t1);margin-bottom:5px}
.bell-sub{font-size:10.5px;color:var(--t3);line-height:1.5;margin-bottom:12px}
.bell-group-hd{font-size:9px;font-weight:800;color:var(--t3);letter-spacing:.6px;text-transform:uppercase;margin:10px 0 6px}
.bell-list{display:flex;flex-direction:column;gap:4px}
.bell-item{display:flex;justify-content:space-between;align-items:center;padding:6px 9px;background:var(--sub,#f8f9fa);border-radius:7px;font-size:11px}
.bell-item .bi-name{font-weight:700;color:var(--t1)}
.bell-item .bi-plat{font-size:9.5px;color:var(--t3);margin-left:5px;font-weight:500}
.bell-item .bi-units{font-size:10px;color:var(--t3);font-weight:600;white-space:nowrap}
.bell-empty{font-size:11px;color:var(--grn);padding:6px 9px}
.bell-link{display:block;padding:7px 9px;border-radius:7px;font-size:11px;color:var(--t1);text-decoration:none;background:var(--sub,#f8f9fa)}
.bell-link:hover{background:var(--hover,#fafbfc)}

/* ── Centered modal (Change Password, etc.) ── */
.modal-back{position:fixed;inset:0;background:rgba(15,15,15,.5);z-index:600;opacity:0;pointer-events:none;transition:.15s;display:flex;align-items:center;justify-content:center}
.modal-back.open{opacity:1;pointer-events:all}
.modal-card{background:var(--white);border-radius:16px;width:360px;max-width:92vw;box-shadow:0 24px 64px rgba(0,0,0,.3);padding:22px 24px;transform:translateY(8px);transition:.15s}
.modal-back.open .modal-card{transform:translateY(0)}
.modal-title{font-size:15px;font-weight:800;color:var(--t1);margin-bottom:4px}
.modal-sub{font-size:11.5px;color:var(--t3);margin-bottom:18px}
.modal-fld{margin-bottom:13px}
.modal-fld label{display:block;font-size:9.5px;letter-spacing:.7px;text-transform:uppercase;color:var(--t3);font-weight:700;margin-bottom:6px}
.modal-fld input{width:100%;border:1px solid var(--bd);border-radius:8px;padding:9px 11px;font-size:13px;font-family:'Inter',sans-serif;box-sizing:border-box}
.modal-fld input:focus{outline:none;border-color:var(--acc,#c8a96e)}
.modal-err{display:none;background:var(--red-bg);color:var(--red);border:1px solid var(--red-bd);font-size:11px;padding:8px 10px;border-radius:7px;margin-bottom:13px}
.modal-err.show{display:block}
.modal-ok{display:none;background:var(--grn-bg);color:var(--grn);border:1px solid var(--grn-bd);font-size:11px;padding:8px 10px;border-radius:7px;margin-bottom:13px}
.modal-ok.show{display:block}
.modal-actions{display:flex;gap:9px;justify-content:flex-end;margin-top:4px}
.modal-cancel{background:none;border:1px solid var(--bd);color:var(--t2);padding:9px 16px;border-radius:8px;cursor:pointer;font-size:12.5px;font-weight:600;font-family:'Inter',sans-serif}
.modal-save{background:var(--acc,#c8a96e);border:none;color:#000;font-weight:700;padding:9px 18px;border-radius:8px;cursor:pointer;font-size:12.5px;font-family:'Inter',sans-serif}
.modal-save:disabled{opacity:.6;cursor:default}

/* ── APP FRAME (desktop) ──────────────────────────────────────────────────
   The black chrome (sidebar + topbar + a strip that closes the page at its
   end) reads as one continuous frame around the light content. The top-left
   junction gets an "inverse radius" piece: a small square filled black
   except a transparent quarter-circle, so the content appears to curve away
   from the chrome. Desktop only — the stacked mobile layout has no side
   chrome to frame against. */
@media (min-width:861px){
  /* Top-left curve, pinned under the sticky topbar at the sidebar junction */
  .topbar::before{content:'';position:absolute;top:100%;left:0;width:14px;height:14px;pointer-events:none;background:radial-gradient(circle 14px at 100% 100%,transparent 13px,var(--top) 13.5px)}
  /* Slim black strip closing the frame at the END of the page — it is a flex
     item in .main's flow, NOT position:fixed, so it appears only once you
     reach the bottom of the content instead of hovering over the page the
     whole time. margin-top:auto keeps it pinned to the bottom on short pages
     that don't fill the viewport; on long pages the auto margin collapses to
     0 and it simply follows the last card. */
  .main::after{content:'';flex-shrink:0;height:10px;background:var(--sb);margin-top:auto}
  /* Sidebar breathes open slightly on hover — a touch more room to read
     nav labels and filters while you're actually using them. */
  .sidebar{transition:width .25s ease,min-width .25s ease}
  .sidebar:hover{width:calc(var(--sw) + 18px);min-width:calc(var(--sw) + 18px)}
}
/* Nav pills nudge toward the content on hover (both breakpoints). */
.nav-item:hover,.nav-group-btn:hover,.nav-sub-item:hover{transform:translateX(2px)}

/* ── RESPONSIVE — compact hamburger nav on phones/narrow screens ── */
.nav-burger{display:none}
@media (max-width:860px){
  .layout{flex-direction:column}
  .sidebar{width:100%;min-width:0;height:auto;border-bottom:1px solid var(--sb-bd)}
  /* padding-right reserves room for .profile — the account avatar button is
     position:fixed at top:9/right:14 (viewport corner, not part of this bar's
     flow), and margin-left:auto on .nav-burger otherwise pushes it flush to
     the SAME corner: found by measuring their rects at 375px and finding the
     hamburger's box (x:324-361) almost exactly on top of the avatar's
     (x:329-361) — one button sitting on the other, both clickable in the same
     spot. 52px clears the avatar (32px circle + 14px offset) plus a gap. */
  .brand{display:flex;align-items:center;gap:12px;padding:10px 52px 10px 14px;border-bottom:none}
  .brand img{width:90px!important;margin-bottom:0!important}
  .brand-tag{margin-right:auto}
  .nav-burger{display:block;background:none;border:1px solid #333;color:#ddd;font-size:16px;line-height:1;padding:7px 11px;border-radius:8px;cursor:pointer;margin-left:auto}
  .nav-burger:hover{border-color:#666}
  /* Nav collapsed by default; hamburger toggles .nav-open on the sidebar. */
  .nav{display:none}
  .sidebar.nav-open .nav{display:block;border-bottom:none;padding:4px 8px 10px;animation:fadeUp .15s ease}
  .nav-group .nav-sub{display:block}
  .filters{display:none}
  .sidebar.nav-open .filters{display:block}
  .reset-btn{display:none}
  .main{height:auto}
  .topbar{flex-wrap:wrap;gap:8px}
  /* A page's own control group inside the topbar (e.g. Inventory's DRR toggle +
     date button, an inline-styled flex row) must wrap too — measured 16px past
     the screen edge at 375px when it didn't. */
  .topbar>div{flex-wrap:wrap;min-width:0;max-width:100%}
  /* Not pinned on phones: with its controls wrapped onto 2-3 lines the sticky
     topbar covered ~25% of a 812px screen on every scroll. It scrolls away
     with the page instead. */
  .topbar{position:relative}
  .date-btn{max-width:100%}
  .metric-toggle{margin-left:0}
  /* Stack every multi-column content grid into a single column on phones so
     nothing is crushed. Fixed-height chart rows keep their height and simply
     stack vertically. This list was built by loading every page at 375px and
     measuring real overflow (see .mpanel below for what one gap looked like)
     rather than by guessing from class names — grid classes not covered here
     were checked and are either single-column already or use auto-fit/
     auto-fill, which is already mobile-safe (hz-strip, p-grid, sync-grid,
     wow-row) and would only get WORSE if forced to a flat 1fr. */
  .row2,.row3-cat,.month-row,.row-top,.row-top-right,.bottom-row,.bottom-row-2,
  .kpis2,.content,.donut-row,.fgrid,.movers-grid,.row-2,.row-2c,.row-charts,
  .row-half,.row-three,.row-two,.row23,.row3,.sec,.tables-row,.charts-row,
  .charts-row-2{grid-template-columns:1fr!important;height:auto!important}
  /* !important because a page's own .kpis/.kpi-strip rule loads after
     shared.css and would otherwise win (media queries add no specificity). */
  .kpis,.kpi-strip,.kpis-r2,.kpis-r3,.kpis-row2,.kstrip,.po-kpis,.po-meta,
  .wh-cards{grid-template-columns:repeat(auto-fit,minmax(120px,1fr))!important}
  /* Model Detail's funnel side-panel: a fixed-width right column with a divider
     border, meant to sit beside its chart on desktop. Forced to 1fr above, but
     the fixed width + border-left need clearing too or it stays pinned narrow
     with a stray vertical rule down a full-width mobile stack. */
  .funnel-metrics{width:100%!important;border-left:0!important;padding-left:0!important}
  /* The dashboard's right-hand "Model Performance" list panel (.mpanel) sized
     itself to a viewport-relative height for its DESKTOP role as a sidebar
     that scrolls independently alongside .content's other column. Once
     .content stacks above, height:calc(100vh-200px) is no longer sized against
     the right thing and the panel — with its own overflow:hidden — silently
     clips most of the list instead of the page just scrolling past it. */
  .mpanel{height:auto!important;max-height:60vh}
  .page{padding:12px 12px 24px}
  .content{padding:12px}
  /* Any chart canvas row given a fixed pixel height still needs room once
     stacked — let those rows grow. */
  .cwrap{min-height:220px}

  /* Date picker: min-width:650px anchored at left:20px guarantees it runs off
     a phone screen no matter how narrow the button that opens it is — found by
     opening it at 375px and measuring (right edge landed at x=670, more than
     half the panel off-canvas). Anchoring by left+right instead of left+width
     makes it viewport-bounded by construction rather than by picking a number
     that happens to fit today. Presets become a horizontal scrolling chip row
     (a 10-item vertical list would make the panel taller than most phones);
     the two calendar months stack instead of sitting side by side. */
  .date-panel{position:fixed;top:64px;left:12px;right:12px;min-width:0;width:auto;
    max-height:80vh;overflow-y:auto;flex-direction:column}
  .date-panel.open{display:flex}
  .dp-presets{width:100%;display:flex;overflow-x:auto;white-space:nowrap;
    border-right:0;border-bottom:1px solid #f0f0f0;padding:8px 10px}
  .dp-preset{border-left:0;border-bottom:3px solid transparent;flex-shrink:0}
  .dp-preset.active{border-left-color:transparent;border-bottom-color:#111}
  .dp-months{flex-direction:column;gap:12px}

  /* Notification bell panel: same bug as the date picker, opposite direction.
     width:380px (420px on P&L, via an inline style — needs !important to beat
     it) anchored with right:0 to a wrapper near the topbar's right edge pushes
     the panel's LEFT edge off-screen instead of the right: measured -71px at
     375px, so the panel was two-thirds hidden past the left edge. Same
     left+right fix. */
  .bell-panel{position:fixed!important;top:64px;left:12px;right:12px;
    width:auto!important;max-width:none;max-height:70vh}
}

/* Tablet: collapse the widest 3-column and asymmetric layouts to 2/1 columns
   before the phone breakpoint kicks in. */
@media (min-width:861px) and (max-width:1200px){
  .row3-cat,.bottom-row-2{grid-template-columns:1fr 1fr!important}
  .row-top,.bottom-row{grid-template-columns:1fr!important}
  .kpis,.kpi-strip{grid-template-columns:repeat(auto-fit,minmax(140px,1fr))!important}
}

/* Wide tables never force the page to scroll sideways — they scroll inside
   their own card instead. */
.tbl-wrap,.tbl-card{overflow-x:auto}

/* ── DATA-HEALTH BANNER (admin, non-Data-Health pages) ──
   Sits between the topbar chrome and page content; amber, not red — the data
   is usable, just incomplete in a way worth knowing before reading the chart. */
.health-banner{display:flex;align-items:center;gap:10px;margin:14px 22px 0;
  padding:10px 14px;background:var(--amb-bg);border:1px solid var(--amb-bd);
  border-radius:9px;font-size:12.5px;color:var(--t1);line-height:1.45}
.health-banner::before{content:"⚠";color:var(--amb);font-size:14px;flex-shrink:0}
.health-banner a{color:var(--amb);font-weight:700;text-decoration:none;
  white-space:nowrap;flex-shrink:0}
.health-banner a:hover{text-decoration:underline}
.health-banner .hb-x{margin-left:auto;flex-shrink:0;background:none;border:0;
  cursor:pointer;color:var(--t3);font-size:17px;line-height:1;padding:0 2px}
.health-banner .hb-x:hover{color:var(--t1)}
@media(max-width:900px){.health-banner{margin:12px 14px 0}}

/* ── DRILL-THROUGH (shared: KPI cards and table rows) ──
   Markup is injected by dashutil.js openDrill(); pages only supply data. */
.drillable,.kpi-drillable{cursor:pointer}
.drillable:hover{background:var(--hover,rgba(127,130,140,.07))}
.drillable:focus-visible,.kpi-drillable:focus-visible{outline:2px solid var(--acc);outline-offset:-2px}
.drill-ico{margin-left:7px;font-size:10px;color:var(--t3);opacity:0;transition:opacity .12s}
.drillable:hover .drill-ico,.drillable:focus-visible .drill-ico{opacity:1}
/* KPI cards get a subtle lift + a corner glyph, so a clickable card is
   distinguishable from a static one without shouting. */
.kpi-drillable{transition:transform .12s,box-shadow .12s;position:relative}
.kpi-drillable:hover{transform:translateY(-2px);box-shadow:var(--sh-hover,0 8px 20px rgba(0,0,0,.09))}
.kpi-drillable::after{content:"⤢";position:absolute;top:9px;right:10px;font-size:10px;
  color:var(--t3);opacity:0;transition:opacity .12s}
.kpi-drillable:hover::after,.kpi-drillable:focus-visible::after{opacity:.75}

.sdrill-back{display:none;position:fixed;inset:0;z-index:120;background:rgba(0,0,0,.45);
  align-items:center;justify-content:center;padding:24px}
.sdrill-card{background:var(--white);border:1px solid var(--bd);border-radius:14px;
  box-shadow:0 24px 60px rgba(0,0,0,.28);width:min(1100px,100%);max-height:86vh;
  display:flex;flex-direction:column;overflow:hidden}
.sdrill-hd{display:flex;align-items:flex-start;justify-content:space-between;gap:14px;
  padding:15px 18px;border-bottom:1px solid var(--bd);flex-shrink:0}
.sdrill-title{font-size:14.5px;font-weight:700;color:var(--t1)}
.sdrill-sub{font-size:11.5px;color:var(--t3);margin-top:3px}
.sdrill-actions{display:flex;align-items:center;gap:8px;flex-shrink:0}
.sdrill-x{background:none;border:0;cursor:pointer;color:var(--t3);font-size:21px;line-height:1;padding:0 3px}
.sdrill-x:hover{color:var(--t1)}
.sdrill-body{overflow:auto;flex:1;min-height:0;padding:0 0 4px}
.sdrill-chartwrap{height:230px;padding:14px 18px 4px}
.sdrill-note{font-size:11px;color:var(--t3);padding:2px 18px 8px}
.sdrill-tblwrap{overflow-x:auto}
@media(max-width:700px){.sdrill-back{padding:10px}.sdrill-card{max-height:94vh}
  .sdrill-chartwrap{height:180px;padding:10px 12px 2px}}

/* The drill modal is opened from many pages, so it must not rely on a page
   stylesheet for its table: `.mtbl` happens to be defined in pl.css /
   pl_analysis.css / targets.css but NOT inventory.css, which left the
   Inventory drills rendering as unstyled plain text. Styling #sdrillTbl
   directly keeps the modal self-contained wherever it's opened from. */
#sdrillTbl{width:100%;border-collapse:collapse;font-size:11px}
#sdrillTbl thead th{font-size:9px;font-weight:700;color:var(--t3);letter-spacing:.5px;
  text-transform:uppercase;padding:9px 12px;border-bottom:2px solid var(--bd);
  background:var(--sub,#f8f9fa);position:sticky;top:0;z-index:2;text-align:right;white-space:nowrap}
#sdrillTbl thead th:first-child{text-align:left}
#sdrillTbl tbody tr{border-bottom:1px solid var(--bd)}
#sdrillTbl tbody tr:hover{background:var(--hover,#fafbfc)}
#sdrillTbl td{padding:7px 12px;text-align:right;white-space:nowrap}
#sdrillTbl td:first-child{text-align:left;font-weight:700}
#sdrillTbl tfoot td{padding:9px 12px;text-align:right;background:var(--foot,#f0f2f5);
  font-weight:800;border-top:2px solid var(--bd);position:sticky;bottom:0}
#sdrillTbl tfoot td:first-child{text-align:left}
#sdrillTbl .empty{text-align:center;color:var(--t3);padding:22px;font-weight:400}

/* mlink() lives in dashutil.js and is callable from any page, so its styling
   belongs here too — it was previously duplicated in alerts.css and po.css
   with diverging rules (po added font-weight, alerts animated the underline),
   so the same helper looked different depending on the page. */
.mlink{cursor:pointer;font-weight:600;border-bottom:1px dotted var(--t3)}
.mlink:hover{color:var(--blue);border-bottom-color:var(--blue)}

/* ── STANDARD DATA TABLE (.mtbl) ──
   Used by P&L, P&L Analysis and Targets. Was defined separately in each of
   those three page CSS files (already drifted — targets.css had 12px cell
   padding vs 10px elsewhere) and is what the shared drill-through modal
   (#sdrillTbl) was modeled on after those files caused two real bugs from the
   duplication: an unstyled drill table on a page that didn't define .mtbl, and
   inconsistent rules across pages. One definition here for all three. */
.mtbl{width:100%;border-collapse:collapse;font-size:11px}
.mtbl thead th{font-size:9px;font-weight:700;color:var(--t3);letter-spacing:.5px;text-transform:uppercase;padding:9px 10px;border-bottom:2px solid var(--bd);background:var(--sub);position:sticky;top:0;z-index:2;text-align:right;white-space:nowrap}
.mtbl thead th:first-child{text-align:left}
.mtbl tbody tr{border-bottom:1px solid #f3f3f3}
.mtbl tbody tr:hover{background:var(--hover)}
.mtbl td{padding:7px 10px;text-align:right;white-space:nowrap}
.mtbl td:first-child{text-align:left;font-weight:700}
.mtbl tfoot td{padding:9px 10px;text-align:right;background:var(--foot);font-weight:800;border-top:2px solid var(--bd)}
.mtbl tfoot td:first-child{text-align:left}

/* Thin scrollbar for a table's scroll wrapper — was copy-pasted (with the
   width drifting 4px vs 5px between copies) across Alerts, Display Ads,
   Inventory and PO. */
.tbl-wrap::-webkit-scrollbar{width:5px;height:5px}
.tbl-wrap::-webkit-scrollbar-thumb{background:#ddd;border-radius:2px}

/* ── SEGMENTED TOGGLE (.seg-group / .seg-btn) ──
   Two contexts, two looks — was three near-identical copies in page CSS, one
   of which (model.css) used the dark/topbar look on a control actually placed
   inside a light card, so the pill rendered as a near-black chip floating on
   white instead of matching its surroundings (visible on the Model Detail
   60-Day Trend toggle). Default here is the light/card look; .seg-group-dark
   is for a toggle embedded in the dark topbar chrome (e.g. Inventory's DRR
   selector), matched by actual placement, not by copying the class per page. */
.seg-group{display:flex;background:var(--sub);border:1px solid var(--bd);border-radius:8px;overflow:hidden}
.seg-btn{padding:6px 13px;font-size:10px;font-family:'Inter',sans-serif;font-weight:700;cursor:pointer;border:none;background:transparent;color:var(--t3);transition:.15s;white-space:nowrap}
.seg-btn.active{background:var(--white);color:var(--t1);border-radius:6px;margin:2px}
.seg-btn:not(.active):hover{color:var(--t1)}

.seg-group-dark{background:var(--sb-ctl);border:1px solid var(--sb-ctl-bd)}
.seg-group-dark .seg-btn{color:#555}
.seg-group-dark .seg-btn.active{background:var(--white);color:#111}
.seg-group-dark .seg-btn:not(.active):hover{color:#ccc}

/* ── HORIZONTAL FUNNEL BAR (.fn-row / .fn-track / .fn-fill / .fn-rate) ──
   Was three near-identical copies (Display ADs, Marketing Mix, PO) that only
   ever differed in .fn-name's width — which is real: it's sized to each
   page's longest label ("Impressions/Clicks" vs full channel names vs seller
   names), not decoration, so that one property stays a per-page override.
   NOT used by Model Detail's funnel, which is a different vertical/compact
   design, not a fourth copy of this one. */
.fn-row{display:flex;align-items:center;gap:13px}
.fn-name{width:120px;font-size:11px;font-weight:700;color:var(--t2);text-align:right;flex-shrink:0}
.fn-track{flex:1;background:var(--sub);border-radius:6px;height:27px;position:relative;overflow:hidden}
.fn-fill{height:100%;border-radius:6px;display:flex;align-items:center;padding:0 11px;color:var(--white);font-size:11px;font-weight:700;white-space:nowrap;transition:width .4s}
/* A bar too narrow for its number: leave .fn-fill empty and put the value in
   .fn-out right after it (fnBar() in dashutil.js picks which). */
.fn-out{position:absolute;top:0;bottom:0;display:flex;align-items:center;padding-left:7px;font-size:11px;font-weight:700;color:var(--t2);white-space:nowrap}
.fn-rate{font-size:10px;color:var(--t3);font-weight:600;width:74px;text-align:left;flex-shrink:0}

/* Section sub-navigation: a full-width bar pinned directly under the black
   topbar on every page (a script relocates it there — see base.html — so it
   sits in the same place regardless of where each page's KPIs render). */
.pl-tabs{display:flex;gap:2px;align-items:center;padding:0 20px;background:var(--white);border-bottom:1px solid var(--bd);flex-shrink:0;flex-wrap:wrap}
.pl-tab{padding:10px 15px;font-size:13px;font-weight:600;color:var(--t3);text-decoration:none;border-bottom:2px solid transparent;margin-bottom:-1px;white-space:nowrap}
.pl-tab:hover{color:var(--t1)}
.pl-tab.active{color:var(--acc);border-bottom-color:var(--acc)}

/* ── NOTE STRIP (.note-strip) — a quiet one-line explainer above a section ── */
.note-strip{background:var(--sub);border:1px solid var(--bd);color:var(--t2);font-size:11px;line-height:1.5;padding:8px 14px;border-radius:10px;display:flex;gap:10px;align-items:flex-start}
.note-strip b{color:var(--t1)}
.note-strip .ni{font-size:14px;color:var(--t3)}
.note-strip .ns-act{margin-left:auto;flex-shrink:0;align-self:center;background:var(--white);border:1px solid var(--bd);color:var(--t1);font:inherit;font-weight:700;font-size:10.5px;padding:4px 10px;border-radius:7px;cursor:pointer;white-space:nowrap}
.note-strip .ns-act:hover{border-color:var(--t3)}

/* ── EMPTY CHART CARD (chartEmpty()/chartFilled() in dashutil.js) ──
   A chart card with no data collapses to its header + one line instead of
   holding 300px of blank canvas; a row whose cards are ALL empty collapses too. */
.empty-msg{display:none}
.card.is-empty{height:auto!important;min-height:0}
.card.is-empty>.cwrap{display:none}
.card.is-empty>.empty-msg{display:block;font-size:11.5px;color:var(--t3);padding:8px 2px 2px}
.row2:has(>.card.is-empty):not(:has(>.card:not(.is-empty))){height:auto!important}

/* Password show/hide toggle (static/pweye.js wraps every password input) */
.pw-wrap{position:relative;display:block}
.pw-wrap input{padding-right:42px !important}
.pw-eye{position:absolute;right:5px;top:50%;transform:translateY(-50%);width:30px;height:30px;display:flex;
  align-items:center;justify-content:center;background:none;border:none;border-radius:7px;cursor:pointer;
  color:var(--t3);padding:0;transition:color .15s,background .15s}
.pw-eye:hover{color:var(--t1);background:var(--hover)}
.pw-eye:focus-visible{outline:2px solid var(--acc);outline-offset:-2px}
.pw-eye svg{width:17px;height:17px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.pw-eye .eye-off,.pw-eye.on .eye-on{display:none}
.pw-eye.on .eye-off{display:block}
