/* ==========================================================================
   VendorConnect — Enterprise Theme Layer
   --------------------------------------------------------------------------
   Loaded LAST, after app.css and app.enhancements.css.

   This layer does the visual elevation WITHOUT touching markup. It works by
   redefining the design tokens that app.css already consumes (--brand, --page,
   --radius, --shadow-*, …) and then refining the shared component classes
   (.card, .kpi, .btn, .badge, table, form controls) that all 70 templates
   already use. One file, every page upgraded.

   Sections
     1.  Typography
     2.  Light tokens
     3.  Dark tokens
     4.  Base / page furniture
     5.  Elevation + cards
     6.  KPI / stat cards + sparklines
     7.  Buttons
     8.  Badges + status pills
     9.  Data grid (tables)
     10. Forms
     11. Empty states
     12. Skeleton / loading
     13. Navigation (topbar + sidebar)
     14. Charts
     15. Tabs + segmented controls
     16. Notifications
     17. Timeline / workflow
     18. Animation + motion
     19. Utilities (replacing inline styles)
     20. Responsive
   ========================================================================== */

/* ------------------------------------------------------------ 1. Typography */
/* Inter is fetched with a system fallback that is metrically close, so a failed
   font request degrades to a near-identical stack rather than a layout shift. */
:root{
  --font-sans: "Inter", "Inter var", -apple-system, BlinkMacSystemFont, "Segoe UI",
               "Helvetica Neue", Arial, sans-serif;
  --font-mono: "JetBrains Mono", "SFMono-Regular", ui-monospace, Consolas,
               "Liberation Mono", monospace;

  /* Type scale — 1.200 minor third, 13px base (dense enterprise UI). */
  --fs-xs:   11.5px;
  --fs-sm:   12.5px;
  --fs-base: 13.5px;
  --fs-md:   15px;
  --fs-lg:   18px;
  --fs-xl:   22px;
  --fs-2xl:  28px;
  --fs-3xl:  34px;

  --lh-tight: 1.22;
  --lh-snug:  1.4;
  --lh-base:  1.55;

  --fw-normal: 400;
  --fw-medium: 500;
  --fw-semi:   600;
  --fw-bold:   700;
  --fw-black:  800;

  /* Spacing scale — 4px base. */
  --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px; --sp-4: 16px;
  --sp-5: 20px; --sp-6: 24px; --sp-8: 32px; --sp-10: 40px; --sp-12: 48px;
}

body{
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  line-height: var(--lh-base);
  font-feature-settings: "cv02","cv03","cv04","tnum";
  letter-spacing: -0.006em;
}

h1,h2,h3,h4,h5{
  font-family: var(--font-sans);
  line-height: var(--lh-tight);
  letter-spacing: -0.021em;
  font-weight: var(--fw-bold);
  margin: 0;
}
h1{ font-size: var(--fs-2xl); font-weight: var(--fw-black); }
h2{ font-size: var(--fs-xl); }
h3{ font-size: var(--fs-lg); }
h4{ font-size: var(--fs-md); }

.mono, code, kbd, pre, .tabular{
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.94em;
}

/* Numeric columns must never wobble as values change. */
.value, .kpi .value, td.num, .num, .money{
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
}

/* ---------------------------------------------------------- 2. Light tokens */
:root,
:root[data-theme="light"]{
  color-scheme: light;

  /* Brand — deep blue, desaturated for long working sessions. */
  --brand-50:  #eff5ff;
  --brand-100: #dbe8fe;
  --brand-200: #bfd7fe;
  --brand-300: #93bbfd;
  --brand-400: #6096fa;
  --brand-500: #3b76f6;
  --brand-600: #2557d6;
  --brand-700: #1d44ac;
  --brand-800: #1d3b88;
  --brand-900: #1c356c;

  --brand:      var(--brand-600);
  --brand-2:    #0e9488;
  --brand-ink:  var(--brand-700);
  --brand-soft: var(--brand-50);
  --brand-grad: linear-gradient(135deg, #2557d6 0%, #3b76f6 52%, #0ea5b7 130%);

  /* Neutrals — slate, cool enough to read as "software" not "document". */
  --slate-50:  #f8fafc;
  --slate-100: #f1f5f9;
  --slate-200: #e6ebf1;
  --slate-300: #cfd8e3;
  --slate-400: #97a3b6;
  --slate-500: #64748b;
  --slate-600: #475569;
  --slate-700: #334155;
  --slate-800: #1e293b;
  --slate-900: #0f172a;

  --surface-1: #ffffff;
  --surface-2: var(--slate-50);
  --surface-3: var(--slate-100);
  --page:      #f6f8fb;

  /* Text tones are pinned to WCAG AA (4.5:1) against every surface they land
     on, not just #fff. slate-500 measured 4.35:1 on the tinted pill background
     and 4.47:1 on --page, so secondary drops a step and muted sits between
     500 and 600 — dim enough to keep the three-level hierarchy readable, dark
     enough to pass on --page (5.1:1) and --surface-3. */
  --text-primary:   var(--slate-800);
  --text-secondary: var(--slate-600);
  --muted:          #5d6b80;

  --grid:     var(--slate-200);
  --baseline: var(--slate-300);
  --border:   #e3e8ef;
  --border-strong: var(--slate-300);

  /* Semantic */
  --good:     #15803d;
  --good-bg:  #ecfdf3;
  --good-bd:  #abefc6;
  --warning:    #b45309;
  --warning-bg: #fffaeb;
  --warning-bd: #fedf89;
  --serious:    #c2410c;
  --serious-bg: #fff4ed;
  --serious-bd: #f9c8a6;
  --critical:    #b42318;
  --critical-bg: #fef3f2;
  --critical-bd: #fecdc9;
  --info:    #026aa2;
  --info-bg: #f0f9ff;
  --info-bd: #b9e6fe;

  /* Chart series — hand-picked for categorical separation *and* for
     deuteranopia/protanopia distinguishability. */
  --series-1: #2557d6;
  --series-2: #0e9488;
  --series-3: #d97706;
  --series-4: #15803d;
  --series-5: #7c3aed;
  --series-6: #dc2626;
  --series-7: #db2777;
  --series-8: #ea580c;

  --seq-100: #dbe8fe;
  --seq-250: #93bbfd;
  --seq-450: #3b76f6;
  --seq-600: #1d44ac;

  /* Sidebar */
  --sidebar-bg:       #101828;
  --sidebar-bg-2:     #0c1421;
  --sidebar-text:     #cdd5e0;
  --sidebar-text-dim: #7f8ba1;
  --sidebar-active:   rgba(59,118,246,0.16);
  --sidebar-border:   rgba(255,255,255,0.06);

  /* Radii — 10–14px per brief. */
  --radius-xs: 6px;
  --radius-sm: 8px;
  --radius:    12px;
  --radius-lg: 14px;
  --radius-xl: 18px;
  --radius-pill: 999px;

  /* Elevation — layered, low-opacity; no hard drop shadows. */
  --shadow-1: 0 1px 2px rgba(16,24,40,0.05), 0 1px 3px rgba(16,24,40,0.04);
  --shadow-2: 0 2px 4px -2px rgba(16,24,40,0.06), 0 4px 12px -2px rgba(16,24,40,0.09);
  --shadow-3: 0 4px 8px -3px rgba(16,24,40,0.07), 0 14px 32px -6px rgba(16,24,40,0.13);
  --shadow-4: 0 8px 16px -6px rgba(16,24,40,0.09), 0 24px 56px -12px rgba(16,24,40,0.20);
  --ring: 0 0 0 3px rgba(59,118,246,0.22);

  --ease:     cubic-bezier(.4,0,.2,1);
  --ease-out: cubic-bezier(.16,1,.3,1);
  --dur-fast: .14s;
  --dur:      .2s;
  --dur-slow: .32s;
}

/* ----------------------------------------------------------- 3. Dark tokens */
:root[data-theme="dark"]{
  color-scheme: dark;

  --surface-1: #151b26;
  --surface-2: #1b222f;
  --surface-3: #222b3a;
  --page:      #0d1118;

  --text-primary:   #e8edf5;
  --text-secondary: #9aa7bd;
  --muted:          #6b7889;

  --grid:          #263041;
  --baseline:      #33405480;
  --border:        #253044;
  --border-strong: #334054;

  --brand:      #6096fa;
  --brand-ink:  #93bbfd;
  --brand-soft: rgba(59,118,246,0.14);
  --brand-grad: linear-gradient(135deg,#2557d6 0%,#3b76f6 55%,#0ea5b7 130%);

  --good:     #6ce9a6;
  --good-bg:  rgba(18,183,106,0.13);
  --good-bd:  rgba(18,183,106,0.30);
  --warning:    #fec84b;
  --warning-bg: rgba(247,144,9,0.13);
  --warning-bd: rgba(247,144,9,0.30);
  --serious:    #fda29b;
  --serious-bg: rgba(234,88,12,0.13);
  --serious-bd: rgba(234,88,12,0.30);
  --critical:    #fda29b;
  --critical-bg: rgba(240,68,56,0.13);
  --critical-bd: rgba(240,68,56,0.32);
  --info:    #7cd4fd;
  --info-bg: rgba(2,106,162,0.16);
  --info-bd: rgba(2,106,162,0.36);

  --series-1: #6096fa;
  --series-2: #2dd4bf;
  --series-3: #fbbf24;
  --series-4: #4ade80;
  --series-5: #a78bfa;
  --series-6: #f87171;
  --series-7: #f472b6;
  --series-8: #fb923c;

  --seq-100: #1d3b88;
  --seq-250: #2557d6;
  --seq-450: #6096fa;
  --seq-600: #bfd7fe;

  --sidebar-bg:       #0b0f17;
  --sidebar-bg-2:     #080c12;
  --sidebar-text:     #c3ccdb;
  --sidebar-text-dim: #6b7889;
  --sidebar-active:   rgba(96,150,250,0.16);
  --sidebar-border:   rgba(255,255,255,0.05);

  --shadow-1: 0 1px 2px rgba(0,0,0,0.40);
  --shadow-2: 0 2px 6px rgba(0,0,0,0.44), 0 6px 16px rgba(0,0,0,0.30);
  --shadow-3: 0 8px 28px rgba(0,0,0,0.52);
  --shadow-4: 0 16px 48px rgba(0,0,0,0.62);
  --ring: 0 0 0 3px rgba(96,150,250,0.30);
}

/* Follow the OS only until the user states a preference (html[data-theme]
   is stamped by theme.js before first paint, so this never flashes). */
@media (prefers-color-scheme: dark){
  :root:not([data-theme]){ color-scheme: dark; }
}

/* --------------------------------------------------- 4. Base page furniture */
body{
  background: var(--page);
  color: var(--text-primary);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}

::selection{ background: rgba(59,118,246,0.22); }

::-webkit-scrollbar{ width: 10px; height: 10px; }
::-webkit-scrollbar-track{ background: transparent; }
::-webkit-scrollbar-thumb{
  background: var(--slate-300, #cfd8e3);
  border: 2px solid transparent;
  background-clip: content-box;
  border-radius: var(--radius-pill);
}
::-webkit-scrollbar-thumb:hover{ background: var(--slate-400,#97a3b6); background-clip: content-box; }
:root[data-theme="dark"] ::-webkit-scrollbar-thumb{ background: #33405480; background-clip: content-box; }
* { scrollbar-width: thin; scrollbar-color: var(--baseline) transparent; }

/* Focus: one consistent, high-contrast ring everywhere. */
:where(a,button,input,select,textarea,[tabindex]):focus-visible{
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  border-radius: var(--radius-xs);
}

hr{ border: 0; border-top: 1px solid var(--border); margin: var(--sp-5) 0; }

/* Page header — replaces the heavy gradient "hero" with a calmer, denser
   enterprise header. The gradient block reads as marketing, not software. */
.hero{
  background: var(--surface-1) !important;
  color: var(--text-primary) !important;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-1);
  padding: var(--sp-6) var(--sp-6) !important;
  position: relative;
  overflow: hidden;
}
.hero::before,
.hero::after{
  /* Kill the decorative marketing circles; keep a single subtle brand wash. */
  content: none !important;
}
.hero h1{
  font-size: var(--fs-xl);
  font-weight: var(--fw-bold);
  color: var(--text-primary);
  margin-bottom: var(--sp-1);
}
.hero p{
  color: var(--text-secondary);
  font-size: var(--fs-base);
  margin: 0 0 var(--sp-4);
}
.hero .hero-icon{
  background: var(--brand-soft);
  color: var(--brand);
  border-radius: var(--radius-lg);
  width: 52px; height: 52px;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.hero .hero-icon .icon{ width: 24px; height: 24px; color: var(--brand); }

/* app.css styles hero children for a dark gradient background (#fff text on a
   translucent white fill). The header is now a light surface, so every one of
   those rules has to be reversed or the buttons render white-on-white. */
.hero .btn{
  backdrop-filter: none;
  background: var(--surface-1);
  color: var(--text-primary);
  border-color: var(--border-strong);
}
.hero .btn:hover{ background: var(--surface-2); }
.hero .btn.solid, .hero .btn.primary{
  background: var(--brand);
  color: #fff;
  border-color: var(--brand);
}
.hero .btn.solid:hover, .hero .btn.primary:hover{ background: var(--brand-700, #1d44ac); }
.hero .badge{ background: var(--surface-3); color: var(--text-secondary); }

/* ------------------------------------------------------ 5. Elevation + cards */
.card{
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-1);
  padding: var(--sp-5);
  transition: box-shadow var(--dur) var(--ease),
              transform var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
.card.hoverable:hover{
  box-shadow: var(--shadow-3);
  transform: translateY(-2px);
  border-color: var(--border-strong);
}

/* Card header convention: title left, actions right, hairline under. */
.card-head{
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-3);
  margin: calc(var(--sp-5) * -1) calc(var(--sp-5) * -1) var(--sp-4);
  padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--border);
}
.card-head h3, .card-head .card-title{
  font-size: var(--fs-md);
  font-weight: var(--fw-semi);
  letter-spacing: -0.014em;
}
.card-head .sub{ font-size: var(--fs-sm); color: var(--text-secondary); font-weight: var(--fw-normal); }
.card-flush{ padding: 0; }
.card-flush .card-head{ margin: 0; }

.grid{ gap: var(--sp-5); }

/* --------------------------------------- 6. KPI / stat cards + sparklines */
.kpi{
  padding: var(--sp-5);
  padding-left: var(--sp-5);
  border-radius: var(--radius-lg);
  display: flex;
  flex-direction: column;
  min-height: 132px;
}
/* Replace the full-height left accent bar with a top hairline — the bar reads
   as a template; the hairline reads as a product. */
.kpi::before{
  top: 0; left: 0; right: 0; bottom: auto;
  width: auto; height: 3px;
  background: var(--kpi-accent, var(--brand));
  opacity: .9;
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}
.kpi .label{
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--text-secondary);
  letter-spacing: 0;
  margin-bottom: var(--sp-3);
}
.kpi .ic-chip{
  width: 36px; height: 36px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
}
.kpi .value{
  font-size: var(--fs-2xl);
  font-weight: var(--fw-bold);
  letter-spacing: -0.028em;
  line-height: 1.1;
}
.kpi .delta{
  font-size: var(--fs-sm);
  color: var(--text-secondary);
  margin-top: auto;
  padding-top: var(--sp-3);
  font-weight: var(--fw-medium);
}
.kpi .delta.up{ color: var(--good); }
.kpi .delta.down{ color: var(--critical); }

/* Trend chip: "+12.4% vs last month" */
.trend-chip{
  display: inline-flex; align-items: center; gap: 3px;
  font-size: var(--fs-xs); font-weight: var(--fw-semi);
  padding: 2px 7px; border-radius: var(--radius-pill);
  background: var(--surface-3); color: var(--text-secondary);
}
.trend-chip.up{ background: var(--good-bg); color: var(--good); }
.trend-chip.down{ background: var(--critical-bg); color: var(--critical); }
.trend-chip.flat{ background: var(--surface-3); color: var(--text-secondary); }
.trend-chip .icon{ width: 12px; height: 12px; }
.trend-caption{ color: var(--muted); font-weight: var(--fw-normal); font-size: var(--fs-xs); }

/* Sparkline sits flush to the card floor. */
.sparkline{
  display: block; width: 100%; height: 34px;
  margin-top: var(--sp-2);
  overflow: visible;
}
.sparkline path.line{
  fill: none;
  stroke: var(--spark-color, var(--brand));
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
.sparkline path.area{ fill: var(--spark-color, var(--brand)); opacity: .10; stroke: none; }
.sparkline circle.tip{ fill: var(--spark-color, var(--brand)); }

/* ------------------------------------------------------------- 7. Buttons */
.btn{
  border-radius: var(--radius-sm);
  padding: 8px 14px;
  font-size: var(--fs-base);
  font-weight: var(--fw-semi);
  letter-spacing: -0.008em;
  border: 1px solid var(--border-strong);
  background: var(--surface-1);
  color: var(--text-primary);
  box-shadow: var(--shadow-1);
  transition: background var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease),
              box-shadow var(--dur-fast) var(--ease),
              transform var(--dur-fast) var(--ease);
}
.btn:hover{ background: var(--surface-2); border-color: var(--baseline); transform: none; box-shadow: var(--shadow-2); }
.btn:active{ background: var(--surface-3); box-shadow: none; transform: translateY(0.5px); }

.btn.primary, .btn.solid{
  background: var(--brand);
  background-image: none;
  color: #fff;
  border-color: var(--brand);
  box-shadow: 0 1px 2px rgba(16,24,40,0.10), 0 1px 3px rgba(37,87,214,0.20);
}
.btn.primary:hover, .btn.solid:hover{
  background: var(--brand-700, #1d44ac);
  border-color: var(--brand-700, #1d44ac);
  filter: none;
  box-shadow: 0 2px 6px rgba(37,87,214,0.28);
}
.btn.good{ background: var(--good); border-color: var(--good); color:#fff; }
.btn.critical{ background: var(--critical); border-color: var(--critical); color:#fff; }
.btn.ghost{ background: transparent; border-color: transparent; box-shadow: none; color: var(--text-secondary); }
.btn.ghost:hover{ background: var(--surface-3); color: var(--text-primary); box-shadow: none; }
.btn.sm{ padding: 5px 10px; font-size: var(--fs-sm); border-radius: var(--radius-xs); }
.btn.lg{ padding: 11px 20px; font-size: var(--fs-md); border-radius: var(--radius); }
.btn:disabled{ opacity: .5; box-shadow: none !important; }
.btn .icon{ width: 15px; height: 15px; }

/* Ripple origin is set by app.theme.js from the pointer position. */
.btn{ position: relative; overflow: hidden; }
.btn .ripple{
  position: absolute; border-radius: 50%; transform: scale(0);
  background: currentColor; opacity: .22; pointer-events: none;
  animation: ripple .5s var(--ease-out) forwards;
}
@keyframes ripple{ to{ transform: scale(2.6); opacity: 0; } }

/* --------------------------------------------- 8. Badges + status pills */
.badge{
  font-size: var(--fs-xs);
  font-weight: var(--fw-semi);
  padding: 3px 9px;
  border-radius: var(--radius-pill);
  border: 1px solid transparent;
  letter-spacing: 0;
  line-height: 1.5;
}
.badge .ic{ width: 6px; height: 6px; }
.badge.good{     background: var(--good-bg);     color: var(--good);     border-color: var(--good-bd); }
.badge.warning{  background: var(--warning-bg);  color: var(--warning);  border-color: var(--warning-bd); }
.badge.serious{  background: var(--serious-bg);  color: var(--serious);  border-color: var(--serious-bd); }
.badge.critical{ background: var(--critical-bg); color: var(--critical); border-color: var(--critical-bd); }
.badge.info{     background: var(--info-bg);     color: var(--info);     border-color: var(--info-bd); }
.badge.neutral{  background: var(--surface-3);   color: var(--text-secondary); border-color: var(--border); }
.badge.good .ic{ background: var(--good); }
.badge.warning .ic{ background: var(--warning); }
.badge.serious .ic{ background: var(--serious); }
.badge.critical .ic{ background: var(--critical); }
.badge.info .ic{ background: var(--info); }
.badge.neutral .ic{ background: var(--muted); }

/* ----------------------------------------------------- 9. Data grid (tables) */
.table-card{ padding: 0; overflow: hidden; }
.table-card .card-head{ margin: 0; }

table{ font-size: var(--fs-base); }
th{
  font-size: var(--fs-xs);
  font-weight: var(--fw-semi);
  text-transform: none;              /* uppercase micro-caps read as "admin template" */
  letter-spacing: 0;
  color: var(--text-secondary);
  background: var(--surface-2);
  padding: 10px var(--sp-4);
  border-bottom: 1px solid var(--border);
}
td{
  padding: 12px var(--sp-4);
  border-bottom: 1px solid var(--grid);
  color: var(--text-primary);
}
tbody tr{ transition: background var(--dur-fast) var(--ease); }
tbody tr:hover{ background: var(--surface-2); }
tbody tr:last-child td{ border-bottom: 0; }

/* Sticky header — works inside .table-scroll which owns the scrollport. */
.table-scroll{ max-height: var(--table-max-h, none); overflow: auto; }
.table-scroll thead th{
  position: sticky; top: 0; z-index: 2;
  background: var(--surface-2);
  box-shadow: inset 0 -1px 0 var(--border);
}
th.sortable:hover{ color: var(--brand); }
th.sortable.sorted{ color: var(--brand); }

td.num, th.num{ text-align: right; font-variant-numeric: tabular-nums; }
td.actions{ text-align: right; white-space: nowrap; }
/* Row actions stay out of the way until the row is engaged — but remain
   keyboard reachable, so visibility is opacity-based, never display:none. */
tbody tr .row-actions{ opacity: 0; transition: opacity var(--dur-fast) var(--ease); }
tbody tr:hover .row-actions,
tbody tr:focus-within .row-actions{ opacity: 1; }

/* Selection + bulk actions */
tbody tr.is-selected{ background: var(--brand-soft); }
.bulk-bar{
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  background: var(--brand-soft);
  border-bottom: 1px solid var(--border);
  font-size: var(--fs-sm); font-weight: var(--fw-medium);
}
.bulk-bar .count{ font-weight: var(--fw-bold); color: var(--brand-ink); }
.bulk-bar .spacer{ flex: 1; }

td.empty, .empty{
  color: var(--text-secondary);
  text-align: center;
  padding: var(--sp-8) var(--sp-4);
}

/* ---------------------------------------------------------------- 10. Forms */
label{
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--text-secondary);
}
input:not([type=checkbox]):not([type=radio]),
select, textarea{
  width: 100%;
  font-family: inherit;
  font-size: var(--fs-base);
  color: var(--text-primary);
  background: var(--surface-1);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: 9px 12px;
  transition: border-color var(--dur-fast) var(--ease),
              box-shadow var(--dur-fast) var(--ease),
              background var(--dur-fast) var(--ease);
}
input::placeholder, textarea::placeholder{ color: var(--muted); }
input:hover:not(:disabled), select:hover:not(:disabled), textarea:hover:not(:disabled){
  border-color: var(--baseline);
}
input:focus, select:focus, textarea:focus{
  outline: none;
  border-color: var(--brand);
  box-shadow: var(--ring);
}
input:disabled, select:disabled, textarea:disabled{
  background: var(--surface-3); color: var(--muted); cursor: not-allowed;
}
/* Held as a token so every select rule can restate it without duplicating the
   data URI — see .filter-field select below for why restating is necessary. */
:root{
  --select-caret: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
}
:root[data-theme="dark"]{
  --select-caret: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%239aa7bd' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
}
select{
  appearance: none;
  background-image: var(--select-caret);
  background-repeat: no-repeat;
  background-position: right 10px center;
  padding-right: 32px;
}
/* app.css sets the `background` *shorthand* on .filter-field select at (0,1,1),
   which resets background-image to none and erased the caret — so the filter
   selects on all ten list pages read as plain text inputs. Restated at matching
   weight rather than editing the prototype-derived rule. */
.filter-field select{
  background-image: var(--select-caret);
  background-repeat: no-repeat;
  background-position: right 10px center;
  padding-right: 32px;
}

/* Floating label — OPT-IN via .field--float, markup input-then-label.
   It must NOT apply to bare .field: every existing template renders .field as
   label-then-input in normal flow, so absolutely positioning the label there
   drops it on top of the input. Stacked labels stay the default; only fields
   built by components/form_field.html opt in. */
.field--float{ position: relative; }
.field--float > input,
.field--float > textarea,
.field--float > select{ padding-top: 18px; padding-bottom: 6px; }
.field--float > label{
  position: absolute; left: 12px; top: 13px;
  font-size: var(--fs-base); color: var(--muted);
  pointer-events: none;
  transform-origin: 0 0;
  margin: 0;
  transition: transform var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.field--float > input:focus + label,
.field--float > input:not(:placeholder-shown) + label,
.field--float > textarea:focus + label,
.field--float > textarea:not(:placeholder-shown) + label,
.field--float > select:focus + label,
.field--float > select:valid + label{
  transform: translateY(-9px) scale(0.82);
  color: var(--brand);
}

/* Default (stacked) field: label above control, which is what the app uses. */
.field > label{ display: block; margin-bottom: var(--sp-1); }

/* Inline validation */
.field-error, .errorlist{
  color: var(--critical);
  font-size: var(--fs-sm);
  margin-top: var(--sp-1);
  list-style: none; padding: 0;
}
input[aria-invalid="true"], select[aria-invalid="true"], textarea[aria-invalid="true"],
.has-error input, .has-error select, .has-error textarea{
  border-color: var(--critical);
}
input[aria-invalid="true"]:focus{ box-shadow: 0 0 0 3px rgba(180,35,24,0.18); }
.field-hint{ color: var(--text-secondary); font-size: var(--fs-sm); margin-top: var(--sp-1); }

/* Form section card + step progress */
.form-section{ margin-bottom: var(--sp-5); }
.form-section > .card-head .step{
  width: 24px; height: 24px; border-radius: 50%;
  background: var(--brand-soft); color: var(--brand-ink);
  font-size: var(--fs-xs); font-weight: var(--fw-bold);
  display: inline-flex; align-items: center; justify-content: center;
  margin-right: var(--sp-2);
}
.form-progress{ display: flex; align-items: center; gap: var(--sp-2); }
.form-progress .node{
  display: flex; align-items: center; gap: var(--sp-2);
  font-size: var(--fs-sm); color: var(--text-secondary); font-weight: var(--fw-medium);
}
.form-progress .node .dot{
  width: 22px; height: 22px; border-radius: 50%;
  border: 2px solid var(--border-strong); background: var(--surface-1);
  display: flex; align-items: center; justify-content: center;
  font-size: 10px; font-weight: var(--fw-bold);
}
.form-progress .node.done .dot{ background: var(--good); border-color: var(--good); color: #fff; }
.form-progress .node.active .dot{ border-color: var(--brand); color: var(--brand); }
.form-progress .node.active{ color: var(--text-primary); }
.form-progress .bar{ flex: 1; height: 2px; background: var(--border); border-radius: 2px; }
.form-progress .node.done + .bar{ background: var(--good); }

/* Autosave indicator */
.autosave{
  display: inline-flex; align-items: center; gap: 5px;
  font-size: var(--fs-xs); color: var(--text-secondary);
}
.autosave .dot{ width: 6px; height: 6px; border-radius: 50%; background: var(--muted); }
.autosave.saving .dot{ background: var(--warning); animation: pulse-dot 1s infinite; }
.autosave.saved .dot{ background: var(--good); }
@keyframes pulse-dot{ 50%{ opacity: .3; } }

/* Upload dropzone */
.dropzone{
  border: 1.5px dashed var(--border-strong);
  border-radius: var(--radius);
  background: var(--surface-2);
  padding: var(--sp-8) var(--sp-5);
  text-align: center;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.dropzone:hover, .dropzone.is-over{
  border-color: var(--brand);
  background: var(--brand-soft);
}
.dropzone .dz-icon{
  width: 44px; height: 44px; margin: 0 auto var(--sp-3);
  border-radius: var(--radius); background: var(--brand-soft); color: var(--brand);
  display: flex; align-items: center; justify-content: center;
}

/* -------------------------------------------------------- 11. Empty states */
.empty-state{
  display: flex; flex-direction: column; align-items: center;
  text-align: center;
  padding: var(--sp-12) var(--sp-5);
  gap: var(--sp-2);
}
.empty-state .es-art{
  width: 88px; height: 88px; margin-bottom: var(--sp-2);
  border-radius: var(--radius-xl);
  background: var(--surface-2);
  border: 1px solid var(--border);
  display: flex; align-items: center; justify-content: center;
  color: var(--muted);
}
.empty-state .es-art .icon{ width: 34px; height: 34px; stroke-width: 1.5; }
.empty-state h3{ font-size: var(--fs-md); font-weight: var(--fw-semi); }
.empty-state p{
  color: var(--text-secondary); font-size: var(--fs-base);
  max-width: 46ch; margin: 0 0 var(--sp-3);
}

/* ------------------------------------------------- 12. Skeleton / loading */
.skeleton{
  background: linear-gradient(90deg,
    var(--surface-3) 25%, var(--surface-2) 37%, var(--surface-3) 63%);
  background-size: 400% 100%;
  animation: shimmer 1.4s ease-in-out infinite;
  border-radius: var(--radius-xs);
  color: transparent !important;
  user-select: none;
}
@keyframes shimmer{ 0%{ background-position: 100% 0; } 100%{ background-position: -100% 0; } }
.skeleton-line{ height: 12px; margin-bottom: var(--sp-2); }
.skeleton-line.w-40{ width: 40%; } .skeleton-line.w-60{ width: 60%; }
.skeleton-line.w-80{ width: 80%; } .skeleton-line.w-100{ width: 100%; }
.skeleton-title{ height: 20px; width: 45%; margin-bottom: var(--sp-4); }
.skeleton-card{ height: 132px; border-radius: var(--radius-lg); }

.progress{
  height: 6px; background: var(--surface-3);
  border-radius: var(--radius-pill); overflow: hidden;
}
.progress > .bar{
  height: 100%; background: var(--brand);
  border-radius: inherit;
  transition: width var(--dur-slow) var(--ease);
}
.progress.indeterminate > .bar{ width: 35%; animation: indet 1.1s var(--ease) infinite; }
@keyframes indet{ 0%{ margin-left: -35%; } 100%{ margin-left: 100%; } }

/* ------------------------------------------ 13. Navigation (topbar/sidebar) */
#topbar{
  height: 58px;
  background: var(--surface-1);
  border-bottom: 1px solid var(--border);
  box-shadow: none;
  backdrop-filter: saturate(180%) blur(8px);
}
#topbar .brand{ font-size: var(--fs-md); font-weight: var(--fw-bold); }
#topbar .brand .mark{
  border-radius: var(--radius-sm);
  background: var(--brand);
  background-image: var(--brand-grad);
  box-shadow: 0 1px 3px rgba(37,87,214,0.35);
}
/* #topbar prefix is load-bearing: the generic form rule in section 10 is
   input:not([type=checkbox]):not([type=radio]), which scores (0,2,1) and would
   otherwise beat a plain .search-shell input (0,1,1) and collapse the left
   padding to 12px — putting the placeholder underneath the magnifier. */
#topbar .search-shell input{
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  border-color: var(--border);
  font-size: var(--fs-sm);
  padding: 8px 12px 8px 36px;
}
.search-shell input:focus{ background: var(--surface-1); box-shadow: var(--ring); }
/* Same trap as above, and the list filter search lost the same fight: app.css
   reserves 30px of left padding for the magnifier at (0,1,1), the generic form
   rule scores (0,2,1) and flattened it to 12px, so the placeholder rendered
   underneath the icon on every list page. Matched here at (0,2,1). */
.list-search input:not([type=checkbox]):not([type=radio]){ padding-left: 32px; }
.search-shell kbd{
  position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
  font-size: 10px; color: var(--muted);
  border: 1px solid var(--border); border-radius: var(--radius-xs);
  padding: 1px 5px; background: var(--surface-1);
}
.icon-btn{
  border-radius: var(--radius-sm);
  border-color: transparent; background: transparent;
  color: var(--text-secondary);
}
.icon-btn:hover{ background: var(--surface-3); color: var(--text-primary); box-shadow: none; }
.icon-btn[aria-expanded="true"]{ background: var(--brand-soft); color: var(--brand); }
/* The icon shows the theme you would switch *to*, matching the aria-label:
   light mode -> moon ("Switch to dark theme"); dark mode -> sun. */
.theme-ic-light{ display: none; }
.theme-ic-dark{ display: block; }
:root[data-theme="dark"] .theme-ic-light{ display: block; }
:root[data-theme="dark"] .theme-ic-dark{ display: none; }

.role-select{ border-radius: var(--radius-sm); background: var(--surface-2); font-size: var(--fs-sm); }
.avatar-chip{ border-radius: var(--radius-sm); border-color: transparent; background: transparent; }
.avatar-chip:hover{ background: var(--surface-3); box-shadow: none; }
.avatar-chip .av{ border-radius: var(--radius-sm); background: var(--brand-grad); font-size: var(--fs-sm); }

.dropdown-panel{
  border-radius: var(--radius); box-shadow: var(--shadow-4);
  border-color: var(--border);
  animation: dropIn var(--dur) var(--ease-out);
}
@keyframes dropIn{ from{ opacity:0; transform: translateY(-6px) scale(.98); } to{ opacity:1; transform:none; } }

#sidebar{ background: var(--sidebar-bg); border-right: 1px solid var(--sidebar-border); }
#sidebar .nav-group-label{
  font-size: 10.5px; font-weight: var(--fw-bold);
  letter-spacing: .07em; text-transform: uppercase;
  color: var(--sidebar-text-dim);
  padding: var(--sp-4) var(--sp-4) var(--sp-2);
}
#sidebar a, #sidebar .nav-item{
  border-radius: var(--radius-sm);
  margin: 1px var(--sp-2);
  font-size: var(--fs-base);
  font-weight: var(--fw-medium);
  color: var(--sidebar-text);
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
#sidebar a:hover, #sidebar .nav-item:hover{ background: rgba(255,255,255,0.06); color: #fff; }
#sidebar a.active, #sidebar .nav-item.active{
  background: var(--sidebar-active);
  color: #fff;
  font-weight: var(--fw-semi);
  position: relative;
}
#sidebar a.active::before{
  content: ''; position: absolute; left: -8px; top: 50%; transform: translateY(-50%);
  width: 3px; height: 18px; border-radius: 0 3px 3px 0; background: var(--brand-400,#6096fa);
}

/* --------------------------------------------------------------- 14. Charts */
.chart-card .card-head{ border-bottom: 1px solid var(--border); }
.bar-row{ transition: opacity var(--dur-fast) var(--ease); }
.chart-card:hover .bar-row:not(:hover){ opacity: .55; }
.bar-row:hover{ opacity: 1; }
.bar-track{ background: var(--surface-3); border-radius: var(--radius-pill); }
.bar-fill{
  border-radius: var(--radius-pill);
  transition: width .6s var(--ease-out);
}
.chart-legend{
  display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4);
  font-size: var(--fs-sm); color: var(--text-secondary);
}
.chart-legend .lg{ display: inline-flex; align-items: center; gap: 6px; }
.chart-legend .sw{ width: 9px; height: 9px; border-radius: 3px; }

/* ------------------------------------------- 15. Tabs + segmented controls */
.tabs{
  display: flex; gap: var(--sp-1);
  border-bottom: 1px solid var(--border);
  margin-bottom: var(--sp-5);
}
.tabs a, .tabs .tab{
  padding: 10px var(--sp-3);
  font-size: var(--fs-base); font-weight: var(--fw-medium);
  color: var(--text-secondary);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.tabs a:hover{ color: var(--text-primary); }
.tabs a.active, .tabs .tab.active{
  color: var(--brand); border-bottom-color: var(--brand); font-weight: var(--fw-semi);
}
.segmented{
  display: inline-flex; padding: 3px; gap: 2px;
  background: var(--surface-3); border-radius: var(--radius-sm);
}
.segmented a, .segmented button{
  padding: 5px 12px; border-radius: var(--radius-xs);
  font-size: var(--fs-sm); font-weight: var(--fw-medium);
  color: var(--text-secondary); border: 0; background: transparent;
}
.segmented .active{
  background: var(--surface-1); color: var(--text-primary);
  box-shadow: var(--shadow-1); font-weight: var(--fw-semi);
}

/* -------------------------------------------------------- 16. Notifications */
.notif-item{
  display: flex; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--border);
  transition: background var(--dur-fast) var(--ease);
}
.notif-item:hover{ background: var(--surface-2); }
.notif-item.unread{ background: var(--brand-soft); }
.notif-item.unread:hover{ background: var(--brand-100, #dbe8fe); }
.notif-item .n-ic{
  width: 32px; height: 32px; border-radius: var(--radius-sm); flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--surface-3); color: var(--text-secondary);
}
.notif-item.p-high .n-ic{ background: var(--critical-bg); color: var(--critical); }
.notif-item.p-med  .n-ic{ background: var(--warning-bg);  color: var(--warning); }
.notif-item.p-low  .n-ic{ background: var(--info-bg);     color: var(--info); }
.notif-item .n-title{ font-size: var(--fs-base); font-weight: var(--fw-semi); }
.notif-item .n-body{ font-size: var(--fs-sm); color: var(--text-secondary); }
.notif-item .n-time{ font-size: var(--fs-xs); color: var(--muted); margin-left: auto; white-space: nowrap; }
.notif-group-label{
  font-size: var(--fs-xs); font-weight: var(--fw-bold);
  text-transform: uppercase; letter-spacing: .06em; color: var(--muted);
  padding: var(--sp-3) var(--sp-4) var(--sp-1);
  background: var(--surface-2);
}

/* ---------------------------------------------------- 17. Timeline/workflow */
.timeline{ position: relative; padding-left: var(--sp-6); }
.timeline::before{
  content: ''; position: absolute; left: 9px; top: 6px; bottom: 6px;
  width: 2px; background: var(--border);
}
.tl-item{ position: relative; padding-bottom: var(--sp-5); }
.tl-item:last-child{ padding-bottom: 0; }
.tl-item::before{
  content: ''; position: absolute; left: calc(var(--sp-6) * -1 + 4px); top: 3px;
  width: 12px; height: 12px; border-radius: 50%;
  background: var(--surface-1); border: 2px solid var(--border-strong);
}
.tl-item.done::before{ background: var(--good); border-color: var(--good); }
.tl-item.active::before{
  background: var(--surface-1); border-color: var(--brand);
  box-shadow: 0 0 0 4px var(--brand-soft);
}
.tl-item.rejected::before{ background: var(--critical); border-color: var(--critical); }
.tl-item .tl-title{ font-size: var(--fs-base); font-weight: var(--fw-semi); }
.tl-item .tl-meta{ font-size: var(--fs-sm); color: var(--text-secondary); }

/* SLA countdown */
.sla{
  display: inline-flex; align-items: center; gap: 5px;
  font-size: var(--fs-xs); font-weight: var(--fw-semi);
  padding: 2px 8px; border-radius: var(--radius-pill);
  background: var(--surface-3); color: var(--text-secondary);
}
.sla.ok{ background: var(--good-bg); color: var(--good); }
.sla.warn{ background: var(--warning-bg); color: var(--warning); }
.sla.breach{ background: var(--critical-bg); color: var(--critical); }

/* -------------------------------------------------- 18. Animation + motion */
#main-inner > *{ animation: pageIn var(--dur-slow) var(--ease-out) both; }
@keyframes pageIn{ from{ opacity: 0; transform: translateY(6px); } to{ opacity: 1; transform: none; } }

.modal-panel, .dialog{ animation: modalIn var(--dur) var(--ease-out); }
@keyframes modalIn{ from{ opacity: 0; transform: translateY(10px) scale(.985); } to{ opacity:1; transform:none; } }

.check-pop{ animation: checkPop .42s var(--ease-out) both; }
@keyframes checkPop{
  0%{ transform: scale(.5); opacity: 0; }
  60%{ transform: scale(1.12); opacity: 1; }
  100%{ transform: scale(1); }
}

/* Honour the OS setting — this is an accessibility requirement, not a nicety. */
@media (prefers-reduced-motion: reduce){
  *, *::before, *::after{
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

/* --------------------------------------- 19. Utilities (kill inline styles) */
.u-mb-0{ margin-bottom: 0; }      .u-mb-1{ margin-bottom: var(--sp-1); }
.u-mb-2{ margin-bottom: var(--sp-2); } .u-mb-3{ margin-bottom: var(--sp-3); }
.u-mb-4{ margin-bottom: var(--sp-4); } .u-mb-5{ margin-bottom: var(--sp-5); }
.u-mb-6{ margin-bottom: var(--sp-6); }
.u-mt-0{ margin-top: 0; }         .u-mt-2{ margin-top: var(--sp-2); }
.u-mt-3{ margin-top: var(--sp-3); }    .u-mt-4{ margin-top: var(--sp-4); }
.u-mt-5{ margin-top: var(--sp-5); }    .u-mt-6{ margin-top: var(--sp-6); }

.u-flex{ display: flex; }          .u-inline-flex{ display: inline-flex; }
.u-col{ flex-direction: column; }  .u-wrap{ flex-wrap: wrap; }
.u-center{ align-items: center; }  .u-start{ align-items: flex-start; }
.u-end-align{ align-items: flex-end; }
.u-between{ justify-content: space-between; }
.u-end{ justify-content: flex-end; }
.u-gap-1{ gap: var(--sp-1); } .u-gap-2{ gap: var(--sp-2); }
.u-gap-3{ gap: var(--sp-3); } .u-gap-4{ gap: var(--sp-4); }
.u-gap-5{ gap: var(--sp-5); }
.u-grow{ flex: 1; }

.u-span-2{ grid-column: span 2; }  .u-span-3{ grid-column: span 3; }
.u-full{ width: 100%; }
.u-right{ text-align: right; }  .u-center-text{ text-align: center; }
.u-nowrap{ white-space: nowrap; }
.u-upper{ text-transform: uppercase; }
.u-truncate{ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.u-muted{ color: var(--text-secondary); }
.u-dim{ color: var(--muted); }
.u-good{ color: var(--good); } .u-warn{ color: var(--warning); }
.u-bad{ color: var(--critical); } .u-brand{ color: var(--brand); }
.u-xs{ font-size: var(--fs-xs); } .u-sm{ font-size: var(--fs-sm); }
.u-lg{ font-size: var(--fs-lg); }
.u-semi{ font-weight: var(--fw-semi); } .u-bold{ font-weight: var(--fw-bold); }
.u-hidden{ display: none !important; }
.u-cursor{ cursor: pointer; }

/* --- spacing (extends the set above; snapped to the 4px scale) --- */
.u-mt-05{ margin-top: 2px; }      .u-mb-05{ margin-bottom: 2px; }
.u-mt-1{ margin-top: var(--sp-1); }
.u-mb-8{ margin-bottom: var(--sp-8); }
.u-mt-8{ margin-top: var(--sp-8); }
/* Negative pull-ups: subtitles sitting tight under a heading. */
.u-pull-1{ margin-top: -4px; }     .u-pull-2{ margin-top: -8px; }
.u-m-0{ margin: 0; }
.u-ml-2{ margin-left: var(--sp-2); }   .u-mr-1{ margin-right: var(--sp-1); }
.u-ml-auto{ margin-left: auto; }
.u-p-0{ padding: 0; }
.u-py-3{ padding-top: var(--sp-3); padding-bottom: var(--sp-3); }
.u-pl-5{ padding-left: var(--sp-5); }

/* --- display / layout --- */
.u-inline{ display: inline; }
.u-block{ display: block; }
.u-scroll-x{ overflow-x: auto; }
.u-scroll-y{ overflow-y: auto; }
.u-maxh-sm{ max-height: 230px; }   .u-maxh-md{ max-height: 260px; }
.u-measure{ max-width: 540px; }
.u-w-100{ width: 100%; }
.u-shrink-0{ flex-shrink: 0; }

/* --- type --- */
.u-11{ font-size: var(--fs-xs); }
.u-13{ font-size: var(--fs-base); }
.u-20{ font-size: var(--fs-xl); }
.u-inherit{ color: inherit; }
.u-pre{ white-space: pre-wrap; }
.u-tnum{ font-variant-numeric: tabular-nums; }
.u-num{ text-align: right; font-variant-numeric: tabular-nums; }
.u-num-strong{ text-align: right; font-weight: var(--fw-bold); font-variant-numeric: tabular-nums; }

/* --- opacity --- */
.u-o-50{ opacity: .5; }  .u-o-75{ opacity: .75; }

/* --- recurring composites --- */
/* Definition row: label left, value right, dashed rule under. Used across the
   vendor, PO, invoice and gate detail panels. */
.kv-row{
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--sp-3) 0;
  border-bottom: 1px dashed var(--grid);
}
.kv-row:last-child{ border-bottom: 0; }
.kv-row .k{ color: var(--text-secondary); font-size: var(--fs-sm); }
.kv-row .v{ font-weight: var(--fw-semi); text-align: right; }

/* Section heading inside a card. */
.section-title{ margin-top: var(--sp-5); }
.section-title:first-child, .section-title.u-mt-0{ margin-top: 0; }

/* Icon chips, previously written as inline rgba() pairs on every KPI.
   .dp-ic (dropdown item icons) share the same palette. */
.ic-chip.good,     .dp-ic.good{     background: var(--good-bg);     color: var(--good); }
.ic-chip.info,     .dp-ic.info{     background: var(--brand-soft);  color: var(--series-1); }
.ic-chip.critical, .dp-ic.critical{ background: var(--critical-bg); color: var(--critical); }
.ic-chip.warning,  .dp-ic.warning{  background: var(--warning-bg);  color: var(--warning); }
.ic-chip.violet,   .dp-ic.violet{   background: var(--surface-3);   color: var(--series-5); }
.ic-chip.teal,     .dp-ic.teal{     background: rgba(14,148,136,.12); color: var(--series-2); }
.ic-chip.amber,    .dp-ic.amber{    background: var(--warning-bg);  color: var(--series-3); }

/* A <button> that must look and flow like a plain block (menu items, table
   row triggers) without inheriting any button chrome. */
.btn-reset{
  background: none; border: none; box-shadow: none;
  text-align: left; font: inherit; color: inherit;
  padding: 0; border-radius: 0;
}
.btn-reset:hover{ background: none; box-shadow: none; transform: none; }

.u-center-justify{ justify-content: center; }
.u-self-center{ align-self: center; }

/* Inset scroll panel — bordered well inside a card. */
.panel-inset{
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: var(--sp-2);
  background: var(--surface-2);
}

/* Very wide report grids scroll inside .table-scroll rather than the page. */
.table-ultrawide{ min-width: 1500px; }

/* Totals row at the foot of a report table. */
.row-total td, td.row-total, .row-total{
  border-top: 2px solid var(--border-strong);
  font-weight: var(--fw-bold);
}

/* Labelled meter row: caption | track | value (scorecards, risk breakdowns). */
.meter-row{ display: flex; align-items: center; gap: var(--sp-3); margin-bottom: var(--sp-2); }
.meter-row .m-label{ width: 120px; flex-shrink: 0; font-size: var(--fs-sm); color: var(--text-secondary); }
.meter-row .m-track{ flex: 1; height: 18px; background: var(--surface-3); border-radius: var(--radius-xs); overflow: hidden; }
.meter-row .m-value{ width: 90px; text-align: right; font-size: var(--fs-sm); font-variant-numeric: tabular-nums; }

/* Donut centre label. */
.donut-hole{
  position: absolute; inset: 14px; border-radius: 50%;
  background: var(--surface-1);
  display: flex; align-items: center; justify-content: center;
  font-size: var(--fs-md); font-weight: var(--fw-bold);
}

/* Sidebar-embedded card (vendor module list). */
.card-on-sidebar{
  background: rgba(255,255,255,0.05);
  border-color: var(--sidebar-border);
  padding: var(--sp-3);
  box-shadow: none;
}
.sidebar-label{
  font-size: var(--fs-xs); color: var(--sidebar-text-dim);
  font-weight: var(--fw-bold); text-transform: uppercase;
  letter-spacing: .04em; margin-bottom: var(--sp-1);
}
.sidebar-value{ font-size: var(--fs-sm); color: var(--sidebar-text); }

.card.is-warning{ border-color: var(--warning); }
/* Stage pills sit inline in a table cell; spacing belongs here, not on each span. */
.stage-pill{ margin-right: 3px; }
.card-accent{ border-left: 4px solid var(--brand); }
.card-accent-bad{ border-left: 4px solid var(--critical); }
.row-tint{ background: var(--brand-soft); }
.row-tint-good{ background: var(--good-bg); }
.u-normal{ font-weight: var(--fw-normal); }
.u-mr-4{ margin-right: var(--sp-4); }
.w-60{ width: 60%; } .w-75{ width: 75%; } .w-85{ width: 85%; } .w-90{ width: 90%; }
.icon-sm{ width: 14px; height: 14px; }
.icon-xs{ width: 13px; height: 13px; }
.u-w-240{ width: 240px; }

/* KPI accent, previously inline --kpi-accent custom properties. */
.kpi.a-good{ --kpi-accent: var(--good); --spark-color: var(--good); }
.kpi.a-info{ --kpi-accent: var(--series-1); --spark-color: var(--series-1); }
.kpi.a-critical{ --kpi-accent: var(--critical); --spark-color: var(--critical); }
.kpi.a-warning{ --kpi-accent: var(--warning); --spark-color: var(--warning); }
.kpi.a-violet{ --kpi-accent: var(--series-5); --spark-color: var(--series-5); }

/* Bare inline filter input in a few list headers. */
.input-inline{
  width: 100%; padding: 8px 10px;
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  font-size: var(--fs-base);
}

/* Screen-reader-only, for icon-only controls. */
.sr-only{
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}

/* ----------------------------------------------------------- 20. Responsive */
@media (max-width: 1280px){
  .grid-4{ grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 1024px){
  .grid-3{ grid-template-columns: repeat(2, 1fr); }
  .u-span-2, .u-span-3{ grid-column: span 2; }
}
@media (max-width: 768px){
  :root{ --fs-2xl: 24px; --fs-3xl: 28px; }
  .grid-2, .grid-3, .grid-4{ grid-template-columns: 1fr; }
  .u-span-2, .u-span-3{ grid-column: span 1; }
  .card{ padding: var(--sp-4); border-radius: var(--radius); }
  .card-head{
    margin: calc(var(--sp-4) * -1) calc(var(--sp-4) * -1) var(--sp-3);
    padding: var(--sp-3) var(--sp-4);
  }
  .hero{ padding: var(--sp-5) var(--sp-4) !important; }
  .hero h1{ font-size: var(--fs-lg); }
  /* .filter-fields is `flex:1` with `min-width:0`, so instead of wrapping onto
     its own line it collapsed to ~76px next to .filter-actions and left every
     filter select cramped beside a band of dead space. A 100% basis makes it
     take the full row and pushes the actions below. */
  .filter-fields{ flex: 1 1 100%; }
  /* app.css already hid this below 900px, but `.hero .hero-icon` here outranks
     its single-class selector, so the decorative tile reappeared and stranded
     itself under the action buttons. Restated at matching specificity. */
  .hero .hero-icon{ display: none; }
  .kpi{ min-height: 0; }
  .tabs{ overflow-x: auto; scrollbar-width: none; }
  .tabs::-webkit-scrollbar{ display: none; }
  /* The strip is scrollable, but the tabs still defaulted to flex-shrink:1, so
     they compressed below their content width instead of letting the container
     scroll. With white-space:nowrap the labels then spilled out of their boxes
     and overlapped the next tab ("Approved (4)" needed 97px in a 66px box).
     Holding their natural width restores the intended horizontal scroll. */
  .tabs .tab{ flex-shrink: 0; }
  /* Row actions can't rely on hover on touch devices. */
  tbody tr .row-actions{ opacity: 1; }
}
@media (max-width: 480px){
  .empty-state{ padding: var(--sp-8) var(--sp-4); }
  .empty-state .es-art{ width: 68px; height: 68px; }

  /* WCAG 2.5.5 — every standalone control gets a 44px touch target on phones.
     These all measured 30–40px. Padding, not height, so the label stays
     vertically centred and nothing below it shifts more than the delta. */
  .icon-btn,
  .avatar-chip,
  #topbar .brand,
  #sidebar-collapse-btn,
  .skip-link,
  .navlink,
  .nav-group-head,
  .btn,
  .tab{ min-height: 44px; }
  .icon-btn,
  #sidebar-collapse-btn,
  .app-alert__close,
  [data-close-console],
  [data-close-ai]{ min-width: 44px; min-height: 44px; }
  /* Short labels ("All") were tall enough but only 41px wide. Icon-only
     buttons ("+", "✕") hit the same problem at 30-32px. */
  .tab,
  .btn{ min-width: 44px; }
  /* Column sort links are 18px tall from line-height alone. The anchor is
     already inline-flex, so a min-height grows the hit area without changing
     where the label sits. */
  th.sortable a{ min-height: 44px; min-width: 44px; }
  /* A checkbox wrapped in a label is activated by the whole label, so the row
     is the target — these were 365px wide but only 34px tall. */
  label.check-row{ min-height: 44px; }
  /* Breadcrumb "Home" is a real navigation target but only 14px tall from
     line-height; inline-flex so min-height applies to the inline anchor. */
  .crumb a{ display: inline-flex; align-items: center; min-height: 44px;
            min-width: 44px; }
  /* Assistant suggestion chips are built in chat.js but styled from CSS, so
     the hit area can be fixed here without touching the script. */
  .chat-suggest button{ min-height: 44px; }
  /* Bare checkboxes (no wrapping label) render at the 13px browser default.
     24px is the WCAG 2.2 AA 2.5.8 floor; see the report for why the stricter
     44px bar needs a markup change rather than CSS. */
  input[type=checkbox], input[type=radio]{ width: 24px; height: 24px; }
  /* .tgl hides its real input (width/height 0) and draws the switch with .sl.
     The rule above has equal specificity and loads later, so it would inflate
     that hidden input and push the slider around. Put it back. */
  .tgl input{ width: 0; height: 0; }

  /* Growing the controls above costs ~15px of topbar width, which pushed the
     row 5px past a 375px viewport. Tightening the gutter and gaps buys back
     more than that without hiding anything. */
  #topbar{ padding: 0 8px; gap: 6px; }
}

@media print{
  #topbar, #sidebar, .btn, .row-actions, #ai-fab{ display: none !important; }
  .card{ box-shadow: none; border-color: #ccc; break-inside: avoid; }
}
