/* ═══════════════════════════════════════════════════════════════════════
   20-components.css — COMPONENT CLASSES (semantic primitives)
   ═══════════════════════════════════════════════════════════════════════
   Every class here consumes ONLY var() tokens from 00-tokens.css.
   No hard-coded hex / rgba / px-for-spacing. If you need a new color or
   size, add a token in 00-tokens.css first, then use it here.

   Organization:
     1. Reset / base                  (normalize)
     2. Typography                    (heading, paragraph, text-*)
     3. Surfaces                      (surface-*)
     4. Borders                       (border-*)
     5. Buttons                       (btn + variants)
     6. Inputs                        (input, select, textarea, checkbox, switch)
     7. Pills / Chips / Badges        (pill, chip, badge)
     8. Cards                         (card + header/body/footer)
     9. Labels / Stats                (label, stat)
    10. Tables                        (table-*)
    11. Nav / Tabs                    (nav-*, tab-*)
    12. Modals / Popovers             (modal, popover, tooltip)
    13. Alert banners                 (alert-*)
    14. Dividers / separators         (divider)
    15. Lifecycle pills               (pill-lifecycle-*)       — 13 May 2026
    16. Metric strip                  (metric-strip-*)         — 13 May 2026
    17. Score bar                     (score-bar)              — 13 May 2026
   ═══════════════════════════════════════════════════════════════════════ */

@layer reset {
  *, *::before, *::after { box-sizing: border-box; }
}

@layer components {

/* ─────────────────────────────────────────────────────────────────────
   1. BASE / RESET
   ───────────────────────────────────────────────────────────────────── */
body {
  font-family: var(--font-family-base);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  color: var(--color-text-body);
  background: var(--color-bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* ─────────────────────────────────────────────────────────────────────
   2. TYPOGRAPHY
   ───────────────────────────────────────────────────────────────────── */
/* Semantic heading classes — use instead of relying on h1/h2/h3 defaults */
.heading          { color: var(--color-text-heading); font-weight: var(--weight-semibold); line-height: 1.3; margin: 0; }
.heading-page     { font-size: var(--text-2xl); font-weight: var(--weight-bold); letter-spacing: var(--tracking-tight); }
.heading-section  { font-size: var(--text-xl); font-weight: var(--weight-semibold); }
.heading-card     { font-size: var(--text-lg); font-weight: var(--weight-semibold); }
.heading-sub      { font-size: var(--text-md); font-weight: var(--weight-medium); color: var(--color-text-muted); }
.heading-hero     { font-size: var(--text-3xl); font-weight: var(--weight-bold); letter-spacing: var(--tracking-tight); }

/* Paragraph / body */
.paragraph        { font-size: var(--text-base); line-height: var(--leading-normal); color: var(--color-text-body); margin: 0; }
.paragraph-sm     { font-size: var(--text-sm); line-height: var(--leading-normal); }
.paragraph-lg     { font-size: var(--text-md); line-height: var(--leading-relaxed); }
.paragraph-reading{ max-width: 65ch; line-height: var(--leading-relaxed); }

/* Text color utilities (role-based, theme-aware) */
.text-heading     { color: var(--color-text-heading); }
.text-body        { color: var(--color-text-body); }
.text-muted       { color: var(--color-text-muted); }
.text-dim         { color: var(--color-text-dim); }
.text-soft        { color: var(--color-text-soft); }
.text-brand       { color: var(--color-text-brand); }
.text-link        { color: var(--color-text-link); text-decoration: none; }
.text-link:hover  { color: var(--color-text-link-hover); text-decoration: underline; }
.text-on-solid    { color: var(--color-text-on-solid); }
.text-disabled    { color: var(--color-text-disabled); }

/* Semantic text colors */
.text-success     { color: var(--color-success-fg); }
.text-warn        { color: var(--color-warn-fg); }
.text-danger      { color: var(--color-danger-fg); }
.text-info        { color: var(--color-info-fg); }
.text-neutral     { color: var(--color-neutral-fg); }

/* Text size classes */
.text-xs          { font-size: var(--text-xs); }
.text-sm          { font-size: var(--text-sm); }
.text-base        { font-size: var(--text-base); }
.text-md          { font-size: var(--text-md); }
.text-lg          { font-size: var(--text-lg); }
.text-xl          { font-size: var(--text-xl); }
.text-2xl         { font-size: var(--text-2xl); }
.text-3xl         { font-size: var(--text-3xl); }

/* Weight */
.font-thin        { font-weight: var(--weight-thin); }
.font-regular     { font-weight: var(--weight-regular); }
.font-medium      { font-weight: var(--weight-medium); }
.font-semibold    { font-weight: var(--weight-semibold); }
.font-bold        { font-weight: var(--weight-bold); }
.font-extrabold   { font-weight: var(--weight-extrabold); }

/* Transform / style */
.text-uppercase   { text-transform: uppercase; letter-spacing: var(--tracking-wider); }
.text-lowercase   { text-transform: lowercase; }
.text-capitalize  { text-transform: capitalize; }
.text-italic      { font-style: italic; }
.text-underline   { text-decoration: underline; }
.text-strike      { text-decoration: line-through; }
.text-nowrap      { white-space: nowrap; }
.text-wrap        { white-space: normal; }
.text-break       { word-break: break-word; overflow-wrap: anywhere; }

/* Alignment */
.text-left        { text-align: left; }
.text-center      { text-align: center; }
.text-right       { text-align: right; }
.text-justify     { text-align: justify; }

/* Truncate / clamp */
.text-truncate    { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.text-clamp-2     { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.text-clamp-3     { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }

/* Micro-caption label (replaces old .g24-stat-label / stat-label) */
.label            { display: block; font-size: var(--text-sm); font-weight: var(--weight-medium); color: var(--color-text-body); }
.label-tiny       { font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--color-text-muted); text-transform: uppercase; letter-spacing: var(--tracking-wider); }
.label-muted      { color: var(--color-text-muted); }

/* Monospace */
.font-mono        { font-family: var(--font-family-mono); }

/* ─────────────────────────────────────────────────────────────────────
   3. SURFACES (backgrounds)
   ───────────────────────────────────────────────────────────────────── */
.surface-page        { background: var(--color-bg); }
.surface-page-alt    { background: var(--color-bg-alt); }
.surface-card        { background: var(--color-surface-card); }
.surface-section     { background: var(--color-surface-section); }
.surface-elevated    { background: var(--color-surface-elevated); }
.surface-input       { background: var(--color-surface-input); }
.surface-hover       { background: var(--color-surface-hover); }

/* Soft tonal surfaces (combine with .border-* + text) */
.surface-brand-soft   { background: var(--color-brand-soft); }
.surface-success-soft { background: var(--color-success-bg); }
.surface-warn-soft    { background: var(--color-warn-bg); }
.surface-danger-soft  { background: var(--color-danger-bg); }
.surface-info-soft    { background: var(--color-info-bg); }
.surface-neutral-soft { background: var(--color-neutral-bg); }

/* ─────────────────────────────────────────────────────────────────────
   4. BORDERS
   ───────────────────────────────────────────────────────────────────── */
.border-default   { border: 1px solid var(--color-border-default); }
.border-subtle    { border: 1px solid var(--color-border-subtle); }
.border-strong    { border: 1px solid var(--color-border-strong); }
.border-input     { border: 1px solid var(--color-border-input); }
.border-accent    { border: 1px solid var(--color-border-accent); }
.border-success   { border: 1px solid var(--color-success-border); }
.border-warn      { border: 1px solid var(--color-warn-border); }
.border-danger    { border: 1px solid var(--color-danger-border); }
.border-info      { border: 1px solid var(--color-info-border); }
.border-neutral   { border: 1px solid var(--color-neutral-border); }
.border-dashed    { border-style: dashed; }
.border-dotted    { border-style: dotted; }
.border-none      { border: none; }

/* Directional borders */
.border-t         { border-top: 1px solid var(--color-border-default); }
.border-r         { border-right: 1px solid var(--color-border-default); }
.border-b         { border-bottom: 1px solid var(--color-border-default); }
.border-l         { border-left: 1px solid var(--color-border-default); }

/* Radius */
.radius-none      { border-radius: var(--radius-none); }
.radius-xs        { border-radius: var(--radius-xs); }
.radius-sm        { border-radius: var(--radius-sm); }
.radius-md        { border-radius: var(--radius-md); }
.radius-lg        { border-radius: var(--radius-lg); }
.radius-xl        { border-radius: var(--radius-xl); }
.radius-2xl       { border-radius: var(--radius-2xl); }
.radius-pill      { border-radius: var(--radius-pill); }
.radius-full      { border-radius: var(--radius-full); }

/* ─────────────────────────────────────────────────────────────────────
   5. BUTTONS
   ───────────────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  min-height: 36px;
  font-family: inherit;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: 1;
  color: var(--color-text-body);
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  user-select: none;
  transition: background var(--transition-fast) var(--ease-out),
              border-color var(--transition-fast) var(--ease-out),
              color var(--transition-fast) var(--ease-out),
              box-shadow var(--transition-fast) var(--ease-out);
}
.btn:focus-visible { outline: none; box-shadow: var(--shadow-focus); }
.btn:disabled, .btn.is-disabled { opacity: var(--opacity-disabled); cursor: not-allowed; pointer-events: none; }

/* Size variants */
.btn-xxs { padding: 2px var(--space-1); font-size: var(--text-xs); border-radius: var(--radius-sm); line-height: 1.2; }
.btn-xs { padding: var(--space-1) var(--space-2); font-size: var(--text-xs); border-radius: var(--radius-sm); }
.btn-sm { padding: var(--space-1) var(--space-3); font-size: var(--text-sm); }
.btn-md { padding: var(--space-2) var(--space-4); font-size: var(--text-sm); }
.btn-lg { padding: var(--space-3) var(--space-5); font-size: var(--text-md); }
.btn-xl { padding: var(--space-4) var(--space-6); font-size: var(--text-lg); }
.btn-block { width: 100%; }
.btn-icon  { padding: var(--space-2); width: 32px; height: 32px; }
.btn-icon-sm { padding: var(--space-1); width: 24px; height: 24px; }
.btn-icon-lg { padding: var(--space-3); width: 40px; height: 40px; }

/* Solid fills (primary action / semantic)
   Primary uses --color-primary-solid (+ hover/active) so a THEME can retune
   the brand button without touching this file. All fall back to the brand
   tokens, so the light theme is byte-for-byte unchanged; the dark theme sets
   --color-primary-solid to a saturated indigo that reads on near-black.
   NOTE: an unlayered .btn-primary in component-pipeline-view.css currently
   wins the REST background globally — it is tokenised the same way, so this
   stays consistent. */
.btn-primary        { background: var(--color-primary-solid, var(--color-accent)); color: var(--color-text-on-solid); border-color: var(--color-primary-solid, var(--color-accent)); }
.btn-primary:hover  { background: var(--color-primary-solid-hover, var(--color-brand-hover)); border-color: var(--color-primary-solid-hover, var(--color-brand-hover)); color: var(--color-text-on-solid); }
.btn-primary:active { background: var(--color-primary-solid-active, var(--color-brand-active)); border-color: var(--color-primary-solid-active, var(--color-brand-active)); color: var(--color-text-on-solid); }

.btn-success        { background: var(--color-success-solid); color: var(--color-text-on-solid); border-color: var(--color-success-solid); }
.btn-success:hover  { background: var(--color-success-solid-hover); border-color: var(--color-success-solid-hover); }

.btn-warn           { background: var(--color-warn-solid); color: var(--color-text-on-solid); border-color: var(--color-warn-solid); }
.btn-warn:hover     { background: var(--color-warn-solid-hover); border-color: var(--color-warn-solid-hover); }

.btn-danger         { background: var(--color-danger-solid); color: var(--color-text-on-solid); border-color: var(--color-danger-solid); }
.btn-danger:hover   { background: var(--color-danger-solid-hover); border-color: var(--color-danger-solid-hover); }

.btn-info           { background: var(--color-info-solid); color: var(--color-text-on-solid); border-color: var(--color-info-solid); }
.btn-info:hover     { background: var(--color-info-solid-hover); border-color: var(--color-info-solid-hover); }

.btn-violet         { background: var(--color-violet-solid); color: var(--color-text-on-solid); border-color: var(--color-violet-solid); }
.btn-violet:hover   { background: var(--color-violet-solid-hover); border-color: var(--color-violet-solid-hover); }

.btn-cyan           { background: var(--color-cyan-solid); color: var(--color-text-on-solid); border-color: var(--color-cyan-solid); }
.btn-cyan:hover     { background: var(--color-cyan-solid-hover); border-color: var(--color-cyan-solid-hover); }

/* Outline (bordered, transparent fill) */
.btn-outline          { background: transparent; color: var(--color-text-body); border-color: var(--color-border-default); }
.btn-outline:hover    { background: var(--color-surface-hover); border-color: var(--color-border-strong); }
.btn-outline-brand    { color: var(--color-brand); border-color: var(--color-brand-soft-border); }
.btn-outline-brand:hover { background: var(--color-brand-soft); }
.btn-outline-danger   { color: var(--color-danger-fg); border-color: var(--color-danger-border); }
.btn-outline-danger:hover { background: var(--color-danger-bg); }

/* Ghost — defined in 60-dashboard-base.css (with visible border). */

/* Soft (tonal bg, same-color text) */
.btn-soft-brand     { background: var(--color-brand-soft); color: var(--color-brand); }
.btn-soft-brand:hover { background: var(--color-brand-soft); filter: brightness(0.96); }
.btn-soft-success   { background: var(--color-success-bg); color: var(--color-success-fg); }
.btn-soft-warn      { background: var(--color-warn-bg); color: var(--color-warn-fg); }
.btn-soft-danger    { background: var(--color-danger-bg); color: var(--color-danger-fg); }
.btn-soft-info      { background: var(--color-info-bg); color: var(--color-info-fg); }

/* Link-style (looks like a text link) */
.btn-link           { background: transparent; color: var(--color-text-link); border: none; padding: 0; height: auto; }
.btn-link:hover     { color: var(--color-text-link-hover); text-decoration: underline; }

/* Shape */
.btn-pill           { border-radius: var(--radius-pill); }
.btn-square         { border-radius: var(--radius-none); }

/* ─────────────────────────────────────────────────────────────────────
   6. INPUTS
   ───────────────────────────────────────────────────────────────────── */
.input, .select, .textarea {
  display: block;
  width: 100%;
  padding: var(--space-2) var(--space-3);
  font-family: inherit;
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  color: var(--color-text-body);
  background: var(--color-surface-input);
  border: 1px solid var(--color-border-input);
  border-radius: var(--radius-md);
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}
.input:hover, .select:hover, .textarea:hover      { border-color: var(--color-border-input-hover); }
.input:focus, .select:focus, .textarea:focus      { outline: none; border-color: var(--color-border-input-focus); box-shadow: var(--shadow-focus); }
.input:disabled, .select:disabled, .textarea:disabled { opacity: var(--opacity-disabled); cursor: not-allowed; background: var(--color-surface-disabled); }
.input::placeholder, .textarea::placeholder       { color: var(--color-text-soft); }

.input-sm { padding: var(--space-1) var(--space-2); font-size: var(--text-xs); }
.input-lg { padding: var(--space-3) var(--space-4); font-size: var(--text-md); }

.input-error   { border-color: var(--color-danger-border); }
.input-error:focus { box-shadow: 0 0 0 var(--color-focus-ring-width) var(--color-danger-bg); }
.input-success { border-color: var(--color-success-border); }

.textarea      { min-height: 80px; resize: vertical; line-height: var(--leading-relaxed); }

.checkbox, .radio { width: 16px; height: 16px; accent-color: var(--color-brand); cursor: pointer; }

/* Switch (iOS-style toggle) */
.switch { position: relative; display: inline-block; width: 36px; height: 20px; }
.switch input { opacity: 0; width: 0; height: 0; }
.switch-slider { position: absolute; cursor: pointer; inset: 0; background: var(--color-neutral-solid); border-radius: var(--radius-pill); transition: background var(--transition-base); }
.switch-slider::before { content: ''; position: absolute; height: 16px; width: 16px; left: 2px; top: 2px; background: var(--color-text-on-solid); border-radius: var(--radius-full); transition: transform var(--transition-base); }
.switch input:checked + .switch-slider { background: var(--color-brand); }
.switch input:checked + .switch-slider::before { transform: translateX(16px); }

/* Form layout helpers */
.form-row    { display: flex; align-items: center; gap: var(--space-3); margin-bottom: var(--space-3); }
.form-group  { margin-bottom: var(--space-4); }
.form-label  { display: block; font-size: var(--text-sm); font-weight: var(--weight-medium); margin-bottom: var(--space-1); color: var(--color-text-body); }
.form-help   { display: block; font-size: var(--text-xs); color: var(--color-text-muted); margin-top: var(--space-1); }
.form-error  { display: block; font-size: var(--text-xs); color: var(--color-danger-fg); margin-top: var(--space-1); }

/* ─────────────────────────────────────────────────────────────────────
   7. PILLS / CHIPS / BADGES
   ───────────────────────────────────────────────────────────────────── */
.pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 2px var(--space-3);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wider);
  border-radius: var(--radius-pill);
  border: 1px solid transparent;
  line-height: 1.5;
}
.pill-sm { padding: 1px var(--space-2); font-size: var(--text-3xs); border-radius: 9px; }
.pill-lg { padding: var(--space-1) var(--space-3); font-size: var(--text-xs); border-radius: 13px; }

.pill-brand   { background: var(--color-brand-soft);    color: var(--color-text-brand);   border-color: var(--color-brand-soft-border); }
.pill-success { background: var(--color-success-bg);    color: var(--color-success-fg);   border-color: var(--color-success-border); }
.pill-warn    { background: var(--color-warn-bg);       color: var(--color-warn-fg);      border-color: var(--color-warn-border); }
.pill-danger  { background: var(--color-danger-bg);     color: var(--color-danger-fg);    border-color: var(--color-danger-border); }
.pill-info    { background: var(--color-info-bg);       color: var(--color-info-fg);      border-color: var(--color-info-border); }
.pill-neutral { background: var(--color-neutral-bg);    color: var(--color-neutral-fg);   border-color: var(--color-neutral-border); }

/* Chip — removable tag */
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-1) var(--space-3);
  font-size: var(--text-sm);
  background: var(--color-brand-soft);
  color: var(--color-text-brand);
  border: 1px solid var(--color-brand-soft-border);
  border-radius: var(--radius-pill);
}
.chip-close {
  cursor: pointer;
  opacity: 0.7;
  padding-left: var(--space-1);
  line-height: 1;
}
.chip-close:hover { opacity: 1; }

/* Badge (numeric / dot) */
.badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px; height: 20px;
  padding: 0 var(--space-2);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  border-radius: var(--radius-pill);
  background: var(--color-danger-solid);
  color: var(--color-text-on-solid);
}
.badge-dot { width: 8px; height: 8px; min-width: 8px; padding: 0; }

/* ─────────────────────────────────────────────────────────────────────
   8. CARDS
   ───────────────────────────────────────────────────────────────────── */
.card {
  background: var(--color-surface-card);
  border: 1px solid var(--color-border-default);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
  box-shadow: var(--shadow-sm);
}
.card-compact  { padding: var(--space-3); }
.card-spacious { padding: var(--space-6); }
.card-flat     { box-shadow: none; }
.card-elevated { box-shadow: var(--shadow-md); }
.card-bordered { border-width: 1px; }
/* Empty/centered content inside a .card — used for "no items" / "all healthy" inline states.
   Promoted from page-scoped .fkss-card--empty-center (Wave 13, 18 May 2026). */
.card-empty-center { text-align: center; padding: var(--space-6, 2rem); }
.card-hover {
  transition: transform var(--transition-base) var(--ease-out),
              border-color var(--transition-base) var(--ease-out),
              box-shadow var(--transition-base) var(--ease-out);
}
.card-hover:hover {
  transform: translateY(-1px);
  border-color: var(--color-border-accent);
  box-shadow: var(--shadow-md);
}

.card-header { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); padding-bottom: var(--space-3); border-bottom: 1px solid var(--color-border-subtle); margin-bottom: var(--space-3); }
.card-body   { /* no extra padding; card already has it */ }
.card-footer { padding-top: var(--space-3); border-top: 1px solid var(--color-border-subtle); margin-top: var(--space-3); }
.card-title  { font-size: var(--text-lg); font-weight: var(--weight-semibold); color: var(--color-text-heading); margin: 0; }
.card-subtitle { font-size: var(--text-sm); color: var(--color-text-muted); margin-top: var(--space-1); }
.card-actions { display: flex; gap: var(--space-2); margin-left: auto; }

/* ─────────────────────────────────────────────────────────────────────
   9. STATS
   ───────────────────────────────────────────────────────────────────── */
.stat {
  font-size: var(--text-2xl);
  font-weight: var(--weight-bold);
  color: var(--color-text-heading);
  line-height: var(--leading-tight);
}
.stat-sm { font-size: var(--text-xl); }
.stat-lg { font-size: var(--text-3xl); }
.stat-brand   { color: var(--color-text-brand); }
.stat-success { color: var(--color-success-fg); }
.stat-warn    { color: var(--color-warn-fg); }
.stat-danger  { color: var(--color-danger-fg); }
.stat-info    { color: var(--color-info-fg); }

/* ─────────────────────────────────────────────────────────────────────
   10. TABLES
   ───────────────────────────────────────────────────────────────────── */
.table          { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
.table th, .table td { padding: var(--space-2) var(--space-3); text-align: left; vertical-align: middle; border-bottom: 1px solid var(--color-border-subtle); }
.table th       { font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--color-text-muted); text-transform: uppercase; letter-spacing: var(--tracking-wider); background: var(--color-bg-alt); }
.table-striped tbody tr:nth-child(odd)  { background: var(--color-bg-alt); }
.table-hover tbody tr:hover             { background: var(--color-surface-hover); }
.table-compact th, .table-compact td    { padding: var(--space-1) var(--space-2); font-size: var(--text-xs); }
.table-wrap     { overflow-x: auto; }

/* ─────────────────────────────────────────────────────────────────────
   10b. PAGE HEADER (.sc-header) — title block (left) + actions (right)
   Promoted to the universal design-system 9 Jun 2026 so pages that do NOT
   load stock_central.css (e.g. /po-manager/smart-reorder) still get the flex
   header instead of a stacked block. Title typography (.sc-title / .sc-subtitle)
   stays in stock_central.css.
   ───────────────────────────────────────────────────────────────────── */
.sc-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.25rem;
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--card-border);
}
.sc-header__text { flex: 1; min-width: 240px; }
.sc-header__actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}

/* Universal sticky-head — added 17 May 2026 UX-Responsive Wave A.
   Replaces per-blueprint sticky implementations. Apply to any <table>. */
.g24-table-sticky-head thead th {
  position: sticky; top: 0;
  z-index: var(--z-sticky, 100);
  background: var(--color-surface-card, #fff);
}

/* ─────────────────────────────────────────────────────────────────────
   11. NAV / TABS
   ───────────────────────────────────────────────────────────────────── */
.nav            { display: flex; gap: var(--space-1); align-items: center; }
.nav-item       { display: inline-flex; }
.nav-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--color-text-muted);
  text-decoration: none;
  border-radius: var(--radius-md);
  transition: background var(--transition-fast), color var(--transition-fast);
}
.nav-link:hover      { background: var(--color-surface-hover); color: var(--color-text-body); }
.nav-link-active, .nav-link.is-active { background: var(--color-brand-soft); color: var(--color-text-brand); }

.tab-list       { display: flex; gap: 0; border-bottom: 1px solid var(--color-border-default); }
.tab-item {
  padding: var(--space-2) var(--space-4);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--color-text-muted);
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  cursor: pointer;
  margin-bottom: -1px;
  transition: color var(--transition-fast), border-color var(--transition-fast);
}
.tab-item:hover  { color: var(--color-text-body); }
.tab-item.is-active, .tab-active { color: var(--color-text-brand); border-bottom-color: var(--color-brand); }

/* ---------------------------------------------------------------------
   UNIVERSAL COMPONENT CONTRACT
   ---------------------------------------------------------------------
   This is the default UI language every page should inherit. Blueprint CSS
   should add layout and domain-specific states only; common primitives
   should use these classes or the aliases below.
------------------------------------------------------------------------ */

/* Native controls inside dashboard content get the same baseline as .btn/.input
   without forcing hidden/toggle inputs into visible controls. */
.g24-main :where(button:not(.g24-star):not(.g24p-close):not(.switch input):not(.toggle-switch input):not([class*="close"])) {
  font-family: inherit;
  min-height: 36px;
  border-radius: var(--radius-md);
}

.g24-main :where(input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]):not([type="hidden"]),
                 select,
                 textarea) {
  font-family: inherit;
  color: var(--color-text-body);
  background: var(--color-surface-input);
  border: 1px solid var(--color-border-input);
  border-radius: var(--radius-md);
}

.g24-main :where(input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]):not([type="hidden"]),
                 select,
                 textarea):focus-visible {
  outline: none;
  border-color: var(--color-border-input-focus);
  box-shadow: var(--shadow-focus);
}

.g24-main :where(textarea) {
  resize: vertical;
  min-height: 80px;
}

.g24-main :where(table) {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
}

.g24-main :where(th, td) {
  padding: var(--space-2) var(--space-3);
  text-align: left;
  vertical-align: middle;
  border-bottom: 1px solid var(--color-border-subtle);
}

.g24-main :where(th) {
  color: var(--color-text-muted);
  background: var(--color-bg-alt);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wider);
}

.g24-main :where(tbody tr:hover) {
  background: var(--color-surface-hover);
}

/* Universal tabs. Supports both new .tab-list/.tab-item and common legacy
   .tabs/.tab-btn/.tab-pane naming used by older blueprint pages. */
.tabs,
.tab-list,
.g24-tabs {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  border-bottom: 1px solid var(--color-border-default);
  overflow-x: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--color-border-default) transparent;
}

.tab-btn,
.g24-tab,
.tabs > button,
.tabs > a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 36px;
  padding: var(--space-2) var(--space-4);
  margin-bottom: -1px;
  border: 0;
  border-bottom: 2px solid transparent;
  border-radius: var(--radius-md) var(--radius-md) 0 0;
  background: transparent;
  color: var(--color-text-muted);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--transition-fast) var(--ease-out),
              border-color var(--transition-fast) var(--ease-out),
              color var(--transition-fast) var(--ease-out),
              box-shadow var(--transition-fast) var(--ease-out);
}

.tab-btn:hover,
.g24-tab:hover,
.tabs > button:hover,
.tabs > a:hover {
  background: var(--color-surface-hover);
  color: var(--color-text-body);
}

.tab-btn.active,
.tab-btn.is-active,
.g24-tab.active,
.g24-tab.is-active,
.tabs > button.active,
.tabs > button.is-active,
.tabs > a.active,
.tabs > a.is-active {
  color: var(--color-text-brand);
  border-bottom-color: var(--color-brand);
  background: var(--color-brand-soft);
}

.tab-btn:focus-visible,
.g24-tab:focus-visible,
.tabs > button:focus-visible,
.tabs > a:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
}

.tab-pane { display: none; }
.tab-pane.active,
.tab-pane.is-active { display: block; }

/* Canonical aliases for page authors. */
.g24-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 36px;
  padding: var(--space-2) var(--space-4);
  font-family: inherit;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: 1;
  color: var(--color-text-body);
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  user-select: none;
  transition: background var(--transition-fast) var(--ease-out),
              border-color var(--transition-fast) var(--ease-out),
              color var(--transition-fast) var(--ease-out),
              box-shadow var(--transition-fast) var(--ease-out);
}
.g24-button:focus-visible { outline: none; box-shadow: var(--shadow-focus); }
.g24-card { background: var(--color-surface-card); border: 1px solid var(--color-border-default); border-radius: var(--radius-lg); padding: var(--space-4); box-shadow: var(--shadow-sm); }
.g24-table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
.g24-input,
.g24-select,
.g24-textarea { display: block; width: 100%; padding: var(--space-2) var(--space-3); font-family: inherit; font-size: var(--text-sm); line-height: var(--leading-normal); color: var(--color-text-body); background: var(--color-surface-input); border: 1px solid var(--color-border-input); border-radius: var(--radius-md); }
.g24-input:focus,
.g24-select:focus,
.g24-textarea:focus { outline: none; border-color: var(--color-border-input-focus); box-shadow: var(--shadow-focus); }

/* ─────────────────────────────────────────────────────────────────────
   12. MODALS / POPOVERS / TOOLTIPS
   ───────────────────────────────────────────────────────────────────── */
.modal-backdrop {
  position: fixed; inset: 0;
  background: var(--color-surface-overlay);
  z-index: var(--z-modal-backdrop);
  display: flex; align-items: center; justify-content: center;
}
/* Wave 13-C [hidden] guard — display:flex above overrides UA-default; restore it.
   Universal rule in 40-states.css is the net; this is targeted intent doc. */
.modal-backdrop[hidden] { display: none !important; }
.modal {
  background: var(--color-surface-elevated);
  border: 1px solid var(--color-border-default);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-2xl);
  max-width: 600px; width: 92%;
  max-height: 90vh; overflow-y: auto;
  z-index: var(--z-modal);
}
.modal-sm { max-width: 400px; }
.modal-lg { max-width: 800px; }
.modal-header { padding: var(--space-4) var(--space-5); border-bottom: 1px solid var(--color-border-subtle); }
.modal-body   { padding: var(--space-5); }
.modal-footer { padding: var(--space-4) var(--space-5); border-top: 1px solid var(--color-border-subtle); display: flex; justify-content: flex-end; gap: var(--space-2); }

/* Mobile safety caps — added 17 May 2026 UX-Responsive Wave A.
   Prevents .modal-lg (800px) from overflowing 320–414px mobile viewports.
   Desktop dimensions of .modal / .modal-sm / .modal-lg above are untouched. */
@media (max-width: 640px) {
  .modal,
  .modal-sm,
  .modal-lg {
    width: 95vw !important;
    max-width: 95vw !important;
  }
}

.popover {
  background: var(--color-surface-elevated);
  border: 1px solid var(--color-border-default);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  padding: var(--space-3);
  z-index: var(--z-popover);
}

.tooltip {
  background: var(--color-text-heading);
  color: var(--color-text-on-solid);
  font-size: var(--text-xs);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  z-index: var(--z-tooltip);
}

/* ─────────────────────────────────────────────────────────────────────
   13. ALERT BANNERS (inline notices — not the alert-engine system)
   ───────────────────────────────────────────────────────────────────── */
.alert {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  border: 1px solid transparent;
  font-size: var(--text-sm);
}
.alert-success { background: var(--color-success-bg); color: var(--color-success-fg); border-color: var(--color-success-border); }
.alert-warn    { background: var(--color-warn-bg);    color: var(--color-warn-fg);    border-color: var(--color-warn-border); }
.alert-danger  { background: var(--color-danger-bg);  color: var(--color-danger-fg);  border-color: var(--color-danger-border); }
.alert-info    { background: var(--color-info-bg);    color: var(--color-info-fg);    border-color: var(--color-info-border); }
.alert[hidden] { display: none; }

/* ─── .input-naked — borderless inline-edit field (Wave 13, 18 May 2026) ───
   Universal pattern for inline-edit inputs that look like text until focused.
   Replaces FBA cat-key-input inline-styled `background:transparent;border:none;
   border-bottom:1px solid …` pattern. Pairs with .text-warn / .font-bold size
   utilities for variants. */
.input-naked {
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--color-border-subtle, var(--card-border, #e5e7eb));
  padding: 2px 4px;
  font-family: inherit;
  color: inherit;
}
.input-naked:focus {
  outline: none;
  border-bottom-color: var(--color-border-accent, var(--brand-accent, #3b82f6));
}

/* ─── .callout-stripe — accent-bordered info block (Wave 13, 18 May 2026) ───
   Replaces inline `background:var(--input-bg);border-left:3px solid …;
   padding:12px;border-radius:6px` pattern. Tone-soft body with a coloured
   left edge to highlight a section. Default = brand-accent. */
.callout-stripe {
  padding: var(--space-3, 12px);
  background: var(--input-bg, var(--color-surface-2, #f3f4f6));
  border-radius: var(--radius-md, 6px);
  border-left: 3px solid var(--brand-accent, var(--color-brand-solid, #3b82f6));
  margin-top: var(--space-4, 14px);
}
.callout-stripe-heading {
  font-size: var(--text-sm, 12px);
  font-weight: var(--weight-semibold, 600);
  color: var(--brand-accent, var(--color-brand-solid, #3b82f6));
  margin-bottom: var(--space-2, 8px);
}
.callout-stripe.is-warn   { border-left-color: var(--color-warn-border,   var(--tone-warn-fg)); }
.callout-stripe.is-warn .callout-stripe-heading   { color: var(--color-warn-fg, var(--tone-warn-fg)); }
.callout-stripe.is-danger { border-left-color: var(--color-danger-border, var(--tone-danger-fg)); }
.callout-stripe.is-danger .callout-stripe-heading { color: var(--color-danger-fg, var(--tone-danger-fg)); }

/* ─── .detail-block — meta-detail section under a card (Wave 13, 18 May 2026) ─
   Used to render a small block of helper-text below a card body separated by
   a dashed/dotted hairline. Default = dashed top border; nested .detail-row
   stacks meta lines with a dotted top hairline. */
.detail-block {
  margin-top: var(--space-2, 8px);
  padding-top: var(--space-2, 8px);
  border-top: 1px dashed var(--card-border, var(--color-border-default, #e5e7eb));
  font-size: var(--text-xs, 11px);
  color: var(--color-text-muted, var(--text-muted));
}
.detail-block-row {
  margin-top: var(--space-1, 6px);
  padding-top: var(--space-1, 6px);
  border-top: 1px dotted var(--card-border, var(--color-border-default, #e5e7eb));
}

/* ─── .checkbox-row — inline checkbox + label pattern (Wave 13, 18 May 2026) ───
   Universal "label wrapping a checkbox" — replaces inline-styled
   `display:flex;align-items:center;gap:6px;cursor:pointer;…` labels. */
.checkbox-row {
  display: flex;
  align-items: center;
  gap: var(--space-2, 6px);
  cursor: pointer;
  font-size: var(--text-base, 13px);
  color: var(--color-text-body, var(--text));
  font-weight: var(--weight-medium, 500);
}
.checkbox-row > input[type="checkbox"] {
  width: 16px;
  height: 16px;
  cursor: pointer;
}

/* ─── .stat-strip — horizontal stats summary row (Wave 13, 18 May 2026) ───
   Tokenised replacement for inline `display:flex;flex-wrap:wrap;gap:14px;
   padding:12px;background:var(--input-bg);border-radius:8px;…` headers. */
.stat-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4, 14px);
  padding: var(--space-3, 12px);
  margin-bottom: var(--space-3, 14px);
  background: var(--input-bg, var(--color-surface-2, #f3f4f6));
  border-radius: var(--radius-lg, 8px);
}
.stat-strip-compact {
  padding: var(--space-2, 10px);
  background: var(--input-bg, var(--color-surface-2, #f3f4f6));
  border-radius: var(--radius-md, 6px);
}

/* ─── .tr-total — emphasised grand-total row inside tables (Wave 13, 18 May 2026) ───
   Replaces `<tr style="background:var(--input-bg);font-weight:700">` pattern. */
.tr-total > td {
  background: var(--input-bg, var(--color-surface-2, #f3f4f6));
  font-weight: var(--weight-bold, 700);
}

/* ─── .row-tile — single soft-surface row card (Wave 13, 18 May 2026) ───
   Replaces inline `padding:6px 10px;background:var(--input-bg);
   border-radius:4px;margin-bottom:6px;font-size:12px` recipe used for
   per-item audit rows inside alerts/banners. */
.row-tile {
  padding: var(--space-1, 6px) var(--space-2, 10px);
  background: var(--input-bg, var(--color-surface-2, #f3f4f6));
  border-radius: var(--radius-sm, 4px);
  margin-bottom: var(--space-1, 6px);
  font-size: var(--text-sm, 12px);
}

/* ─── .summary-table — compact label:value rows for analytics summaries ───
   Wave 13 universal extract — replaces inline-styled <table> recipes that
   showed a single column of muted labels next to bold values, with
   optional row-top hairlines. */
.summary-card {
  padding: var(--space-3, 12px) var(--space-4, 16px);
  background: var(--surface-raised, var(--color-surface-elevated, var(--card-bg)));
  border: 1px solid var(--border-subtle, var(--color-border-subtle, var(--card-border, #e5e7eb)));
  border-radius: var(--radius-md, 6px);
  margin-bottom: var(--space-4, 16px);
}
.summary-table {
  border-collapse: collapse;
  width: 100%;
  font-size: var(--text-base, 13px);
}
.summary-table > tbody > tr.summary-divide { border-top: 1px solid var(--border-subtle, var(--color-border-subtle, var(--card-border, #e5e7eb))); }
.summary-table > tbody > tr > td:first-child { padding: var(--space-1, 4px) 0; color: var(--color-text-muted, var(--text-muted)); width: 220px; }
.summary-table > tbody > tr > td:last-child  { font-weight: var(--weight-semibold, 600); }
.summary-table .summary-final > td  { padding-top: var(--space-1, 6px); padding-bottom: var(--space-1, 4px); font-weight: var(--weight-bold, 700); }
.summary-table .summary-final > td:last-child { font-size: var(--text-md, 16px); color: var(--color-success-fg, var(--tone-success-fg)); }

/* ─────────────────────────────────────────────────────────────────────
   14. DIVIDERS
   ───────────────────────────────────────────────────────────────────── */
.divider         { border: none; border-top: 1px solid var(--color-border-default); margin: var(--space-4) 0; }
.divider-subtle  { border-top-color: var(--color-border-subtle); }
.divider-strong  { border-top-color: var(--color-border-strong); }
.divider-dashed  { border-top-style: dashed; }
.divider-vertical { display: inline-block; width: 1px; height: 1em; background: var(--color-border-default); margin: 0 var(--space-2); vertical-align: middle; }

/* ─────────────────────────────────────────────────────────────────────
   STAGE PROGRESS (pip bar — used by rollout experiments, gradual flows)
   ───────────────────────────────────────────────────────────────────── */
.pip-bar, .ro-pip-bar { display: flex; gap: var(--space-1); margin-top: var(--space-2); }
.pip, .ro-pip {
  flex: 1;
  height: 6px;
  background: var(--color-border-default);
  border-radius: var(--radius-xs);
  position: relative;
  overflow: hidden;
}
.pip.is-done, .ro-pip.is-done       { background: var(--color-brand); }
.pip.is-current, .ro-pip.is-current { background: linear-gradient(90deg, var(--color-brand) 50%, var(--color-border-default) 50%); }

/* ─────────────────────────────────────────────────────────────────────
   ICONS (sizing helpers for inline SVG or font icons)
   ───────────────────────────────────────────────────────────────────── */
.icon         { width: 16px; height: 16px; flex-shrink: 0; }
.icon-sm      { width: 12px; height: 12px; }
.icon-lg      { width: 20px; height: 20px; }
.icon-xl      { width: 24px; height: 24px; }
.icon-muted   { color: var(--color-text-muted); }
.icon-brand   { color: var(--color-brand); }

/* ─────────────────────────────────────────────────────────────────────
   LIFECYCLE PILLS  (.pill-lifecycle-*)
   13 May 2026 — Added for A+ Queue system; reusable across blueprints.
   Usage: <span class="pill pill-lifecycle-queued">Queued</span>
   Extends the base .pill class — always pair with .pill.
   ───────────────────────────────────────────────────────────────────── */
.pill-lifecycle-queued     { background: var(--color-info-bg);    color: var(--color-info-fg);    border-color: var(--color-info-border); }
.pill-lifecycle-inprogress { background: var(--color-warn-bg);    color: var(--color-warn-fg);    border-color: var(--color-warn-border); }
.pill-lifecycle-done       { background: var(--color-success-bg); color: var(--color-success-fg); border-color: var(--color-success-border); }
.pill-lifecycle-failed     { background: var(--color-danger-bg);  color: var(--color-danger-fg);  border-color: var(--color-danger-border); }
.pill-lifecycle-unknown    { background: var(--color-neutral-bg); color: var(--color-neutral-fg); border-color: var(--color-neutral-border); }

/* ─────────────────────────────────────────────────────────────────────
   METRIC STRIP  (.metric-strip)
   13 May 2026 — Generic horizontal metric card row (queue stats, report
   summaries, dashboard KPIs). Replaces one-off flex metric rows in
   blueprints. Blueprint-specific spacing can override via selector.
   ───────────────────────────────────────────────────────────────────── */
.metric-strip {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

.metric-strip-item {
  flex: 1 1 100px;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-3) var(--space-4);
  background: var(--color-surface-card);
  border: 1px solid var(--color-border-default);
  border-radius: var(--radius-md);
  min-width: 80px;
}

.metric-strip-value {
  font-size: var(--text-xl);
  font-weight: var(--weight-bold);
  color: var(--color-text-base);
  line-height: 1.1;
}

.metric-strip-label {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  line-height: 1.3;
}

/* Tone variants — apply to .metric-strip-item */
.metric-strip-item--success .metric-strip-value { color: var(--color-success-fg); }
.metric-strip-item--warn    .metric-strip-value { color: var(--color-warn-fg); }
.metric-strip-item--danger  .metric-strip-value { color: var(--color-danger-fg); }
.metric-strip-item--info    .metric-strip-value { color: var(--color-info-fg); }
.metric-strip-item--brand   .metric-strip-value { color: var(--color-brand); }

/* ─────────────────────────────────────────────────────────────────────
   SCORE BAR  (.score-bar)
   13 May 2026 — Inline horizontal progress bar for 0-100 scores
   (opportunity scores, quality scores, CVR lifts, etc.).
   Usage:
     <div class="score-bar">
       <div class="score-bar-fill" style="width:72%"></div>
     </div>
   Pair with .score-bar--success / --warn / --danger for color.
   ───────────────────────────────────────────────────────────────────── */
.score-bar {
  position: relative;
  height: 6px;
  border-radius: var(--radius-pill);
  background: var(--color-border-default);
  overflow: hidden;
  min-width: 48px;
}

.score-bar-fill {
  position: absolute;
  inset: 0 auto 0 0;
  height: 100%;
  border-radius: var(--radius-pill);
  background: var(--color-brand);
  transition: width 0.3s ease;
}

.score-bar--success .score-bar-fill { background: var(--color-success-solid); }
.score-bar--warn    .score-bar-fill { background: var(--color-warn-solid); }
.score-bar--danger  .score-bar-fill { background: var(--color-danger-solid); }

/* ─────────────────────────────────────────────────────────────────────
   18. ERROR-PAGE LAYOUT  (.error-page-*)
   17 May 2026 (Wave 1 Agent H) — promoted from inline <style> in
   templates/404.html + 500.html. Centralized so future error pages
   (403, 410, 503) reuse the same shape.
   ───────────────────────────────────────────────────────────────────── */
.error-page {
  max-width: 600px;
  margin: var(--space-20) auto;
  padding: var(--space-10) var(--space-6);
  text-align: center;
}
.error-page-code {
  font-size: var(--text-icon);
  font-weight: var(--weight-extrabold);
  line-height: 1;
  margin-bottom: var(--space-4);
  color: var(--color-border-strong);
}
.error-page-code--neutral { color: var(--color-border-strong); }
.error-page-code--danger  { color: var(--color-danger-fg); opacity: 0.35; }
.error-page-title {
  margin: 0 0 var(--space-3) 0;
  color: var(--color-text-heading);
}
.error-page-msg {
  color: var(--color-text-muted);
  font-size: var(--text-base);
  line-height: var(--leading-relaxed);
  margin: 0 0 var(--space-8) 0;
}
.error-page-actions {
  display: flex;
  gap: var(--space-3);
  justify-content: center;
  flex-wrap: wrap;
}

/* ─────────────────────────────────────────────────────────────────────
   19. STUB / COMING-SOON LAYOUT  (.stub-*)
   17 May 2026 (Wave 1 Agent H) — promoted from inline <style> in
   templates/stub.html. Shared by all "under construction" routes.
   ───────────────────────────────────────────────────────────────────── */
.stub-wrap {
  max-width: 520px;
  margin: var(--space-12) auto;
  padding: 0 var(--space-4);
  text-align: center;
}
.stub-card {
  padding: var(--space-10) var(--space-8);
}
.stub-icon {
  font-size: 48px;
  margin-bottom: var(--space-3);
}
.stub-title {
  font-size: var(--text-display);
  margin: 0 0 var(--space-3) 0;
  color: var(--color-text-heading);
  font-weight: var(--weight-semibold);
}
.stub-badge {
  display: inline-block;
  padding: var(--space-1) var(--space-4);
  border-radius: var(--radius-pill);
  background: var(--color-warn-bg);
  color: var(--color-warn-fg);
  border: 1px solid var(--color-warn-border);
  font-size: var(--text-compact);
  font-weight: var(--weight-semibold);
  margin-bottom: var(--space-2);
}
.stub-schedule {
  font-size: var(--text-compact);
  color: var(--color-text-muted);
  margin: var(--space-1) 0 var(--space-4) 0;
}
.stub-desc {
  color: var(--color-text-muted);
  line-height: var(--leading-relaxed);
  margin: 0 0 var(--space-6) 0;
  font-size: var(--text-base);
}
.stub-actions {
  display: flex;
  gap: var(--space-2);
  justify-content: center;
  flex-wrap: wrap;
  margin-top: var(--space-2);
}
.stub-back { margin-top: var(--space-2); }

/* ─────────────────────────────────────────────────────────────────────
   20. SEARCH INPUT  (.search-input)
   17 May 2026 (Wave 1 Agent H) — Bible §3.13 search primitive.
   Pair with leading 🔍 icon (use Unicode or inline SVG). Debounce 150ms
   in JS. Use across blueprints instead of bespoke .xy-search variants.
   ───────────────────────────────────────────────────────────────────── */
.search-input-wrap {
  position: relative;
  display: inline-block;
  min-width: 220px;
}
.search-input-wrap .search-input-icon {
  position: absolute;
  left: var(--space-3);
  top: 50%;
  transform: translateY(-50%);
  font-size: var(--text-base);
  color: var(--color-text-muted);
  pointer-events: none;
}
.search-input {
  display: block;
  width: 100%;
  padding: var(--space-2) var(--space-3) var(--space-2) var(--space-8);
  font-family: inherit;
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  color: var(--color-text-body);
  background: var(--color-surface-input);
  border: 1px solid var(--color-border-input);
  border-radius: var(--radius-md);
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}
.search-input:focus {
  outline: none;
  border-color: var(--color-border-input-focus);
  box-shadow: var(--shadow-focus);
}
.search-input::placeholder { color: var(--color-text-soft); }
.search-input-clear {
  position: absolute;
  right: var(--space-2);
  top: 50%;
  transform: translateY(-50%);
  background: transparent;
  border: none;
  cursor: pointer;
  color: var(--color-text-muted);
  font-size: var(--text-base);
  padding: var(--space-1);
  line-height: 1;
}
.search-input-clear:hover { color: var(--color-text-body); }

/* ─────────────────────────────────────────────────────────────────────
   21. INPUT WITH COUNTER  (.input-counter-*)
   17 May 2026 (Wave 1 Agent H) — Bible §3.6 char/byte counter variant.
   Keyword Intelligence consumes this for India 200-byte UTF-8 limit;
   Listings Editor consumes it for title/bullet character caps. JS lives
   in the consuming blueprint, but the visual contract is here.
   Pattern:
     <div class="input-counter-wrap">
       <textarea class="input input-counter-input" maxlength="200"></textarea>
       <div class="input-counter-meta">
         <span class="input-counter-text" data-counter>0 / 200 bytes</span>
       </div>
     </div>
   States:
     .input-counter-text.is-warn   — ≥ 80% of limit
     .input-counter-text.is-danger — ≥ 100% of limit (server will reject)
   ───────────────────────────────────────────────────────────────────── */
.input-counter-wrap {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}
.input-counter-meta {
  display: flex;
  align-items: center;
  justify-content: flex-end;
}
.input-counter-text {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
  font-family: var(--font-family-mono);
}
.input-counter-text.is-warn   { color: var(--color-warn-fg); }
.input-counter-text.is-danger { color: var(--color-danger-fg); font-weight: var(--weight-semibold); }

/* ─────────────────────────────────────────────────────────────────────
   22. KPI TILE  (.kpi-tile / .kpi-tile-*)
   17 May 2026 (Wave 1 Agent H) — Bible §3.16 dashboard KPI primitive.
   Eyebrow-label / value / sub-label / optional delta + tooltip slot.
   Use for finance, returns, stock central headline numbers — replaces
   per-blueprint .xy-stat-card duplicates.
   ───────────────────────────────────────────────────────────────────── */
.kpi-tile {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-4) var(--space-5);
  background: var(--color-surface-card);
  border: 1px solid var(--color-border-default);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
  min-width: 140px;
}
.kpi-tile-label {
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wider);
  display: flex;
  align-items: center;
  gap: var(--space-1);
}
.kpi-tile-value {
  font-size: var(--text-stat);
  font-weight: var(--weight-bold);
  color: var(--color-text-heading);
  line-height: var(--leading-tight);
  font-variant-numeric: tabular-nums;
}
.kpi-tile-sub {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}
.kpi-tile-delta {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  font-variant-numeric: tabular-nums;
}
.kpi-tile-delta--up   { color: var(--color-success-fg); }
.kpi-tile-delta--down { color: var(--color-danger-fg); }
.kpi-tile-delta--flat { color: var(--color-text-muted); }

/* Tone variants — colour the value to reflect status of the metric. */
.kpi-tile--success .kpi-tile-value { color: var(--color-success-fg); }
.kpi-tile--warn    .kpi-tile-value { color: var(--color-warn-fg); }
.kpi-tile--danger  .kpi-tile-value { color: var(--color-danger-fg); }
.kpi-tile--info    .kpi-tile-value { color: var(--color-info-fg); }
.kpi-tile--brand   .kpi-tile-value { color: var(--color-text-brand); }

/* Currency variant — locks tabular numerals + tightens letter-spacing. */
.kpi-tile-value--currency {
  font-feature-settings: 'tnum', 'lnum';
  letter-spacing: var(--tracking-tight);
}

/* ─────────────────────────────────────────────────────────────────────
   23. ACTION MENU (kebab dropdown)  (.action-menu-*)
   17 May 2026 (Wave 1 Agent H) — Bible §3.16 row-scoped action menu.
   Pair with a kebab button. Group destructive actions at the bottom,
   separated by .action-menu-divider.
   ───────────────────────────────────────────────────────────────────── */
.action-menu-trigger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  color: var(--color-text-muted);
  cursor: pointer;
  font-size: var(--text-lg);
  line-height: 1;
  transition: background var(--transition-fast), color var(--transition-fast);
}
.action-menu-trigger:hover {
  background: var(--color-surface-hover);
  color: var(--color-text-body);
}
.action-menu-trigger:focus-visible { outline: none; box-shadow: var(--shadow-focus); }
.action-menu {
  position: absolute;
  min-width: 200px;
  padding: var(--space-1) 0;
  background: var(--color-surface-elevated);
  border: 1px solid var(--color-border-default);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  z-index: var(--z-dropdown);
}
.action-menu[hidden] { display: none; }
.action-menu-item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-sm);
  color: var(--color-text-body);
  background: transparent;
  border: 0;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
}
.action-menu-item:hover {
  background: var(--color-surface-hover);
  color: var(--color-text-heading);
}
.action-menu-item--danger        { color: var(--color-danger-fg); }
.action-menu-item--danger:hover  { background: var(--color-danger-bg); color: var(--color-danger-fg); }
.action-menu-item:disabled, .action-menu-item.is-disabled {
  opacity: var(--opacity-disabled);
  cursor: not-allowed;
}
.action-menu-divider {
  height: 1px;
  margin: var(--space-1) 0;
  background: var(--color-border-subtle);
}

/* ─────────────────────────────────────────────────────────────────────
   24. FILTER CHIP  (.filter-chip / .filter-chip-bar)
   17 May 2026 (Wave 1 Agent H) — Bible §3.13 multi-select removable
   filter chip pattern. Distinct from .chip (which is a generic tag) by
   including a clear-all affordance and a chip-bar container with wrap.
   ───────────────────────────────────────────────────────────────────── */
.filter-chip-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}
.filter-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-1) var(--space-3);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  background: var(--color-brand-soft);
  color: var(--color-text-brand);
  border: 1px solid var(--color-brand-soft-border);
  border-radius: var(--radius-pill);
}
.filter-chip-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  margin-left: var(--space-1);
  padding: 0;
  background: transparent;
  border: 0;
  border-radius: var(--radius-full);
  color: inherit;
  cursor: pointer;
  font-size: var(--text-sm);
  line-height: 1;
  opacity: 0.7;
}
.filter-chip-close:hover { opacity: 1; background: var(--color-surface-hover); }
.filter-chip-clear-all {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  background: transparent;
  border: 0;
  cursor: pointer;
  padding: var(--space-1) var(--space-2);
}
.filter-chip-clear-all:hover { color: var(--color-text-body); text-decoration: underline; }

/* ─────────────────────────────────────────────────────────────────────
   25. PAGINATION  (.pagination-*)
   17 May 2026 (Wave 1 Agent H) — Bible §3.13 standalone pagination
   primitive. Use only when SCTable is not applicable (card grids etc.).
   SCTable already ships pagination — DO NOT roll your own.
   ───────────────────────────────────────────────────────────────────── */
.pagination {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
  color: var(--color-text-body);
}
.pagination-info {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}
.pagination-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 32px;
  height: 32px;
  padding: 0 var(--space-2);
  background: var(--color-surface-card);
  color: var(--color-text-body);
  border: 1px solid var(--color-border-default);
  border-radius: var(--radius-md);
  cursor: pointer;
  font-size: var(--text-sm);
  transition: background var(--transition-fast);
}
.pagination-btn:hover:not(:disabled):not(.is-active) {
  background: var(--color-surface-hover);
  border-color: var(--color-border-strong);
}
.pagination-btn.is-active {
  background: var(--color-brand-soft);
  border-color: var(--color-brand-soft-border);
  color: var(--color-text-brand);
  font-weight: var(--weight-semibold);
}
.pagination-btn:disabled, .pagination-btn.is-disabled {
  opacity: var(--opacity-disabled);
  cursor: not-allowed;
}

/* ─────────────────────────────────────────────────────────────────────
   26. SIDE PANEL / DRAWER  (.drawer / .drawer-backdrop)
   17 May 2026 (Wave 1 Agent H) — Bible §3.14 context-preserving detail
   panel. Slides in from the right on desktop, from the bottom on mobile.
   Use for listing/SKU/order detail flows — NOT a modal (use .modal for
   blocking dialogs). Pair with .drawer-backdrop for the dim layer.
   ───────────────────────────────────────────────────────────────────── */
.drawer-backdrop {
  position: fixed;
  inset: 0;
  background: var(--color-surface-overlay);
  z-index: var(--z-modal-backdrop);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--transition-base) var(--ease-out);
}
.drawer-backdrop.is-open {
  opacity: 1;
  pointer-events: auto;
}
.drawer {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: 480px;
  max-width: calc(100vw - var(--scrollbar-w, 0px));
  background: var(--color-surface-elevated);
  border-left: 1px solid var(--color-border-default);
  box-shadow: var(--shadow-2xl);
  z-index: var(--z-modal);
  display: flex;
  flex-direction: column;
  /* Wave B7 (17 May 2026): safe-area-inset — top notch, right landscape-cutout,
     bottom home-indicator. Defensive ", 0" fallback. */
  padding-top: env(safe-area-inset-top, 0);
  padding-right: env(safe-area-inset-right, 0);
  padding-bottom: env(safe-area-inset-bottom, 0);
  transform: translateX(100%);
  transition: transform var(--transition-slow) var(--ease-out);
}
.drawer.is-open { transform: translateX(0); }
.drawer-sm { width: 360px; }
.drawer-lg { width: 640px; }
/* Wave 13-C [hidden] guard — display:flex above overrides UA-default. */
.drawer[hidden] { display: none !important; }
/* Mobile safety cap — added 17 May 2026 UX-Responsive Wave A.
   Belt-and-suspenders alongside the bottom-sheet block below; ensures
   .drawer-lg (640px) never overflows on narrow viewports. Existing
   desktop widths above are untouched. */
.drawer { max-width: min(480px, 100%); }
.drawer-lg { max-width: min(640px, 100%); }
.drawer-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--color-border-subtle);
}
.drawer-title {
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  color: var(--color-text-heading);
  margin: 0;
}
.drawer-body {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: var(--space-5);
}
.drawer-footer {
  padding: var(--space-4) var(--space-5);
  border-top: 1px solid var(--color-border-subtle);
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
}
.drawer-close {
  background: transparent;
  border: 0;
  cursor: pointer;
  font-size: var(--text-xl);
  line-height: 1;
  color: var(--color-text-muted);
  padding: var(--space-1);
}
.drawer-close:hover { color: var(--color-text-body); }
/* Mobile — full-height bottom sheet style. */
@media (max-width: 640px) {
  .drawer,
  .drawer-sm,
  .drawer-lg {
    top: auto;
    left: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    max-height: 92vh;
    border-left: 0;
    border-top: 1px solid var(--color-border-default);
    border-top-left-radius: var(--radius-xl);
    border-top-right-radius: var(--radius-xl);
    transform: translateY(100%);
  }
  .drawer.is-open { transform: translateY(0); }
}

/* ─────────────────────────────────────────────────────────────────────
   27. CONFIRMATION DIALOG (type-to-confirm)  (.confirm-dialog-*)
   17 May 2026 (Wave 1 Agent H) — Bible §3.15 nuclear-action confirm.
   Required for: deleting > 50 records, live price push > 5% delta,
   suspending accounts, mass-archiving. Type-to-confirm input must match
   an exact identifier before the primary button enables (JS contract).
   Pair with .modal + .modal-sm; this is the body content shape.
   ───────────────────────────────────────────────────────────────────── */
.confirm-dialog-icon {
  font-size: var(--text-icon);
  line-height: 1;
  color: var(--color-danger-fg);
  text-align: center;
  margin-bottom: var(--space-3);
}
.confirm-dialog-title {
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  color: var(--color-text-heading);
  text-align: center;
  margin: 0 0 var(--space-2) 0;
}
.confirm-dialog-body {
  font-size: var(--text-sm);
  color: var(--color-text-body);
  line-height: var(--leading-relaxed);
  margin-bottom: var(--space-4);
}
.confirm-dialog-scope {
  display: block;
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  background: var(--color-bg-alt);
  border-radius: var(--radius-md);
  padding: var(--space-2) var(--space-3);
  margin-bottom: var(--space-3);
}
.confirm-dialog-type-label {
  display: block;
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  margin-bottom: var(--space-1);
}
.confirm-dialog-type-input {
  display: block;
  width: 100%;
  padding: var(--space-2) var(--space-3);
  font-family: var(--font-family-mono);
  font-size: var(--text-sm);
  background: var(--color-surface-input);
  border: 1px solid var(--color-border-input);
  border-radius: var(--radius-md);
  color: var(--color-text-body);
}
.confirm-dialog-type-input:focus {
  outline: none;
  border-color: var(--color-border-input-focus);
  box-shadow: var(--shadow-focus);
}
.confirm-dialog-type-input.is-match {
  border-color: var(--color-success-border);
  background: var(--color-success-bg);
}

/* ─────────────────────────────────────────────────────────────────────
   28. PROGRESS WIDGET (async background job)  (.progress-widget)
   17 May 2026 (Wave 1 Agent H) — Bible §3.10 floating background-task
   monitor. Lives bottom-right desktop / full-width bottom on mobile.
   Stack max 3 widgets; manage via JS (consumer blueprint or core/platform
   job_queue). Page remains usable while widget shows.
   ───────────────────────────────────────────────────────────────────── */
.progress-widget {
  position: fixed;
  bottom: var(--space-4);
  right: var(--space-4);
  width: 320px;
  max-width: calc(100vw - var(--space-4) * 2);
  background: var(--color-surface-elevated);
  border: 1px solid var(--color-border-default);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: var(--space-3) var(--space-4);
  z-index: var(--z-toast);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.progress-widget-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}
.progress-widget-title {
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--color-text-heading);
  margin: 0;
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.progress-widget-cancel {
  background: transparent;
  border: 0;
  cursor: pointer;
  font-size: var(--text-base);
  color: var(--color-text-muted);
  line-height: 1;
  padding: var(--space-1);
}
.progress-widget-cancel:hover { color: var(--color-danger-fg); }
.progress-widget-bar {
  position: relative;
  height: 6px;
  background: var(--color-border-default);
  border-radius: var(--radius-pill);
  overflow: hidden;
}
.progress-widget-bar-fill {
  position: absolute;
  inset: 0 auto 0 0;
  height: 100%;
  background: var(--color-brand);
  border-radius: var(--radius-pill);
  transition: width var(--transition-base) var(--ease-out);
}
.progress-widget-bar.is-indeterminate .progress-widget-bar-fill {
  width: 35%;
  animation: progress-indeterminate 1.2s linear infinite;
}
@keyframes progress-indeterminate {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(286%); }
}
.progress-widget-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}
.progress-widget--success .progress-widget-bar-fill { background: var(--color-success-solid); }
.progress-widget--warn    .progress-widget-bar-fill { background: var(--color-warn-solid); }
.progress-widget--danger  .progress-widget-bar-fill { background: var(--color-danger-solid); }
@media (max-width: 640px) {
  .progress-widget {
    bottom: 0;
    right: 0;
    left: 0;
    width: 100%;
    max-width: 100%;
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  }
}

/* ─────────────────────────────────────────────────────────────────────
   29. TOAST (undo variant)  (.toast-undo)
   17 May 2026 (Wave 1 Agent H) — Bible §3.8 + §17 undo-toast pattern.
   Companion to existing .toast in 60-dashboard-base.css. Use for
   reversible destructives — soft-delete, soft-archive, etc.
   ───────────────────────────────────────────────────────────────────── */
.toast-undo-action {
  background: transparent;
  border: 0;
  color: inherit;
  cursor: pointer;
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wider);
  font-size: var(--text-xs);
  margin-left: var(--space-3);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  text-decoration: underline;
}
.toast-undo-action:hover { background: var(--color-surface-hover); text-decoration: none; }

/* Toast slide-in / slide-out (used by g24-popup.js or any toast engine). */
@keyframes toast-slide-in {
  from { opacity: 0; transform: translateX(24px); }
  to   { opacity: 1; transform: translateX(0); }
}
@keyframes toast-slide-out {
  from { opacity: 1; transform: translateX(0); }
  to   { opacity: 0; transform: translateX(24px); }
}
.toast-animate-in  { animation: toast-slide-in  var(--transition-slow) var(--ease-out) both; }
.toast-animate-out { animation: toast-slide-out var(--transition-base) var(--ease-in) both; }

/* ─────────────────────────────────────────────────────────────────────
   30. BANNER  (.banner / .banner-*)
   17 May 2026 (Wave 1 Agent H) — full-width informational strip.
   Distinct from .alert (inline card) and .toast (transient). Use for
   trial countdown, demo notice, system maintenance, sticky reminders.
   ───────────────────────────────────────────────────────────────────── */
.banner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-4);
  font-size: var(--text-sm);
  background: var(--color-neutral-bg);
  color: var(--color-neutral-fg);
  border-bottom: 1px solid var(--color-neutral-border);
}
.banner-success { background: var(--color-success-bg); color: var(--color-success-fg); border-bottom-color: var(--color-success-border); }
.banner-warn    { background: var(--color-warn-bg);    color: var(--color-warn-fg);    border-bottom-color: var(--color-warn-border); }
.banner-danger  { background: var(--color-danger-bg);  color: var(--color-danger-fg);  border-bottom-color: var(--color-danger-border); }
.banner-info    { background: var(--color-info-bg);    color: var(--color-info-fg);    border-bottom-color: var(--color-info-border); }
.banner-brand   { background: var(--color-brand-soft); color: var(--color-text-brand); border-bottom-color: var(--color-brand-soft-border); }
/* Wave 13-C [hidden] guard — display:flex above overrides UA-default. */
.banner[hidden] { display: none !important; }
.banner-action {
  margin-left: var(--space-3);
  font-weight: var(--weight-semibold);
  text-decoration: underline;
}

/* ─── .progress-inline — inline progress bar with --icon-tint accent ──
   Used in dense tables where a % fill renders inline next to a numeric
   label. Inner `<i style="--w:75%">` sets the fill width.

   Example: <span class="progress-inline"><i style="--w:75%"></i></span>
─────────────────────────────────────────────────────────────────── */
.progress-inline {
  position: relative;
  display: inline-block;
  width: 100%;
  min-width: 80px;
  height: 6px;
  background: var(--color-surface-2, var(--color-surface-section));
  border-radius: 999px;
  overflow: hidden;
  vertical-align: middle;
}
.progress-inline > i {
  display: block;
  width: var(--w, 0%);
  height: 100%;
  background: var(--icon-tint, var(--color-brand-solid, #4f46e5));
  border-radius: 999px;
  transition: width var(--motion-duration-1, .25s) var(--motion-ease-out, ease-out);
}

/* ─── .text-pre-json — preformatted JSON / log text ────────────────────
   Inline `<pre>` for JSON payloads, stack traces, etc. Wraps on break-all
   so long ids don't overflow. Pair with `.surface-input` / `.surface-section`
   for the background plate.

   Example: <pre class="text-pre-json surface-input p-3">{...}</pre>
─────────────────────────────────────────────────────────────────── */
.text-pre-json {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, monospace);
  font-size: var(--text-xs);
  white-space: pre-wrap;
  word-break: break-all;
  line-height: var(--leading-snug, 1.4);
  color: var(--color-text-body);
  margin: 0;
}

/* ─── .tone-row — composite tonal-section row ──────────────────────────
   Used in admin tables / Feature Flags / Quota where a row needs a subtle
   band of colour without a full banner. Pair with .is-success/.is-warn/
   .is-danger/.is-info modifiers.

   Example: <tr class="tone-row is-warn">…</tr>
─────────────────────────────────────────────────────────────────── */
.tone-row              { background: transparent; transition: background var(--motion-duration-1, .15s) var(--motion-ease-out, ease-out); }
.tone-row.is-success   { background: var(--color-success-bg); }
.tone-row.is-warn      { background: var(--color-warn-bg); }
.tone-row.is-danger    { background: var(--color-danger-bg); }
.tone-row.is-info      { background: var(--color-info-bg); }

/* ─── .icon-tint — dynamic per-feature card-icon tint ─────────────────
   Replaces inline `style="background:#abc"` JS sites where the tint
   value is data-driven (e.g. /scheduler per-feature category colours).
   The class supplies the box; JS sets the `--icon-tint` CSS variable
   inline — this is the Bible §11 documented exception for "dynamic
   colour passed from JS data" (variable-only, not a full inline-style).

   Example:
     <div class="icon-tint" style="--icon-tint: #4f46e5">⚙</div>
     // or in JS template-literal:
     '<div class="icon-tint" style="--icon-tint:' + tint + '">…</div>'

   Reusable beyond /scheduler — Auto-Ship, Auto-PO, Smart Reorder, any
   feature-grid with data-driven category tints.
─────────────────────────────────────────────────────────────────── */
.icon-tint {
  background: var(--icon-tint, var(--color-surface-2, var(--color-surface-section)));
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-md);
}

} /* @layer components */

/* ════════════════════════════════════════════════════════════════════════
   === Migrated 17 May 2026 — UNLAYERED ===
   Rules below are intentionally OUTSIDE @layer components so they retain
   the same cascade tier the per-blueprint CSS files had pre-migration
   (unlayered). This is required because 60-dashboard-base.css ships an
   unlayered "* { margin: 0; padding: 0 }" reset on line 26 — layered rules
   ALWAYS lose to unlayered rules regardless of specificity, so a layered
   ".rt-quick-icon { margin-left: 0.3rem }" would be overridden by the "*"
   reset. Keeping these unlayered preserves the original blueprint cascade.

   Class names retained as-is (JS template literals reference them);
   cross-blueprint dedup of .rt-asin-link / .sos-asin / .lr-table-asin
   into a unified .asin-link is a deferred opportunistic step.
   ════════════════════════════════════════════════════════════════════════ */

/* ── Rank Tracker (was in blueprints/rank_tracker/static/rank_tracker.css) ── */

/* Inline ASIN deep-link inside cards / lists (color inherit, dotted underline). */
.rt-asin-link {
  color: inherit;
  text-decoration: underline dotted;
}
.rt-asin-link:hover { text-decoration: underline; }

/* Quick-action icon links beside ASIN id (sales, buy-box). */
.rt-quick-icon {
  margin-left: 0.3rem;
  text-decoration: none;
  font-size: 0.78rem;
}
.rt-quick-icon--tight { margin-left: 0.15rem; }

/* A+ badge slot rendered next to ASIN id — JS fills text + title. */
.rt-aplus-slot {
  font-size: 0.7rem;
  margin-left: 0.35rem;
}

/* Click-share inline chip inside ASIN keyword row. */
.rt-kw-cs {
  font-size: 0.75rem;
  color: var(--text-secondary);
}

/* Priority pill on opportunity rows (slightly smaller than rt-stat-chip). */
.rt-opp-priority { font-size: 0.72rem; }

/* Totals footer under opportunity list. */
.rt-opp-totals {
  font-size: 0.83rem;
  color: var(--success-text);
  font-weight: 600;
  margin-top: 0.5rem;
}

/* Ghost-search subhead inside opportunity panel. */
.rt-opp-ghost-head {
  font-size: 0.85rem;
  font-weight: 600;
  margin-bottom: 0.4rem;
}

/* Scenario simulator cards — was inline grid + paddings. */
.rt-scenario-card { margin-bottom: 0.8rem; }
.rt-scenario-top  { flex-wrap: wrap; gap: 0.4rem; }
.rt-scenario-meta {
  font-size: 0.8rem;
  color: var(--text-secondary);
}
.rt-scenario-success {
  font-size: 0.75rem;
  color: var(--text-muted);
}
.rt-scenario-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.5rem;
  margin-top: 0.6rem;
}
.rt-scenario-tile {
  text-align: center;
  padding: 0.5rem;
}
.rt-scenario-tile-head {
  font-size: 0.72rem;
  font-weight: 700;
  margin-bottom: 0.2rem;
}
.rt-scenario-tile-head--muted { color: var(--text-muted); }
.rt-scenario-tile-num {
  font-size: 1rem;
  font-weight: 700;
}
.rt-scenario-tile-sub { font-size: 0.8rem; }
.rt-scenario-tile-conf {
  font-size: 0.72rem;
  color: var(--text-muted);
}
.rt-scenario-summary {
  font-size: 0.78rem;
  color: var(--text-muted);
  margin-top: 0.4rem;
}

/* Alert-channel inline chips inside super-admin status row. */
.rt-alert-channel-chip { margin-left: 0.6rem; }

/* Verifier accuracy big-number tints. */
.rt-verifier-num {
  font-size: 1.6rem;
  font-weight: 800;
}
.rt-verifier-num--success { color: var(--tone-success-fg); }
.rt-verifier-num--warn    { color: var(--tone-warn-fg); }
.rt-verifier-num--danger  { color: var(--tone-danger-fg); }

/* Voice summary stat variants (was inline tone bg/border/fg). */
.rkt-voice-stat--success {
  background: var(--tone-success-bg);
  border-color: var(--tone-success-border);
}
.rkt-voice-stat--success strong { color: var(--tone-success-fg); }
.rkt-voice-stat--danger {
  background: var(--tone-danger-bg);
  border-color: var(--tone-danger-border);
}
.rkt-voice-stat--danger strong { color: var(--tone-danger-fg); }
.rkt-voice-stat strong.rkt-voice-tracked-num {
  color: var(--text-muted);
  font-size: 1.2rem;
}

/* Forecast error + ASIN code cell helpers. */
.rt-forecast-error { color: var(--tone-danger-fg); }
.rt-forecast-asin-code { font-size: 0.78rem; }

/* ── Buy Box Intelligence (was in blueprints/buy_box_intelligence/static/buy_box_intelligence.css) ── */

/* Clickable health card (Not Winning -> scroll to detail) — replaces inline
   onclick + cursor:pointer style (UX Bible §11 anti-pattern #1) */
.bb-health-card--clickable {
  cursor: pointer;
}
.bb-health-card--clickable:focus,
.bb-health-card--clickable:hover {
  box-shadow: 0 4px 16px rgba(0, 0, 0, .22);
}

/* Inline meta inside card label (e.g. "Winning . N tracked") */
.bb-health-card__label-meta {
  font-weight: var(--weight-regular, 400);
  font-size: var(--text-sm);
  color: var(--text-muted);
}

/* Lost-detail table column tints — replaces inline style="color:..." */
.bb-lost-table__gap {
  color: var(--tone-danger-fg);
  font-weight: var(--weight-semibold);
}
.bb-lost-table__competitor {
  font-size: var(--text-xs);
  color: var(--text-muted);
}

/* No-Buy-Box section variant — replaces inline background + border styles */
.bb-lost-section--nobb {
  background: var(--tone-neutral-bg, rgba(108, 117, 125, .08));
  border-color: var(--tone-neutral-border, rgba(108, 117, 125, .25));
}
.bb-lost-section__title--nobb {
  color: var(--tone-warn-fg);
}

/* History total footer — replaces inline padding style */
.bb-history-total {
  padding: 0.5rem 0.875rem;
}

/* ── Launch Radar (was in blueprints/launch_radar/static/launch_radar.css) ── */

/* ASIN cell — monospace, slightly smaller (replaces inline style) */
.lr-table-asin {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--text-xs);
  color: var(--text-dim);
  letter-spacing: 0.01em;
}

/* Trend bar (per-keyword threat trajectory) — width fed via --lr-bar-w custom prop set by JS.
   Migrated 17 May 2026 (Pass 2) — was in launch_radar.css. */
.lr-trend-bar {
  height: 14px;
  width: var(--lr-bar-w, 2px);
  background: var(--brand-accent);
  border-radius: var(--radius-sm);
  min-width: 2px;
  max-width: 200px;
  transition: width 0.3s;
}

/* Threat-history sparkline bar — height fed via --lr-spark-h custom prop set by JS.
   Migrated 17 May 2026 (Pass 2) — was in launch_radar.css. */
.lr-time-spark-bar {
  flex: 1;
  height: var(--lr-spark-h, 2px);
  background: var(--brand-accent);
  border-radius: 2px 2px 0 0;
  min-width: 6px;
  transition: height 0.3s ease;
}

/* ── PPC Intelligence (was in blueprints/ppc_intelligence/static/ppc_intelligence.css) ── */

/* Bid Advisor reason cell — was inline style="max-width:260px;font-size:.78rem;" */
.ppc-bid-reason-cell {
  max-width: 260px;
  font-size: .78rem;
}
/* Campaign-comparison type label — was inline style="color:var(--color-text-muted)" */
.ppc-comparison-type-label {
  color: var(--color-text-muted);
}
/* Margin-ACoS footnote — was inline style="margin-top:.6rem;font-size:.78rem;color:var(--color-text-muted);" */
.ppc-margin-footnote {
  margin-top: .6rem;
  font-size: .78rem;
  color: var(--color-text-muted);
}

/* ── Share of Search (was in blueprints/share_of_search/static/share_of_search.css) ── */

/* ASIN column compact text (replaces inline style="font-size:.8rem") */
.sos-asin {
  font-size: .8rem;
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
}
/* Export button — pushed to right of toolbar */
.sos-export-btn {
  margin-left: auto;
  font-size: .8rem;
}

/* Single-keyword SOV fill bar — width fed via --sos-bar-w custom prop set by JS.
   Migrated 17 May 2026 (Pass 2) — was in share_of_search.css. */
.sos-sov-bar-fill {
  display: block;
  height: 100%;
  border-radius: 4px;
  background: var(--brand-accent);
  min-width: 2px;
  width: var(--sos-bar-w, 0%);
}

/* Stacked-share segment (you/competitor/other) — width fed via --sos-seg-w custom prop set by JS.
   Migrated 17 May 2026 (Pass 2) — was in share_of_search.css. */
.sos-share-seg {
  height: 100%;
  display: block;
  transition: width .25s ease;
  width: var(--sos-seg-w, 0%);
}

/* Universal selected-row tone — pairs with the existing `.bulk-bar`
   primitive in 60-dashboard-base.css. Added 17 May 2026 (Wave-7 UX sweep). */
tr.is-selected td,
.bulk-row.is-selected {
  background: var(--tone-info-bg);
}

/* ═══════════════════════════════════════════════════════════════════════
   18. SORTABLE TABLE HEADERS — th[data-sort] + .sort-arrow indicator
   Added 17 May 2026 (Universal CSS sweep — promoted from .lc-th-sort /
   listings_editor th[data-sort] cursor rule). Pairs with aria-sort.
   USE: <th class="th-sort" data-sort="col-key" aria-sort="none">…</th>
   ═══════════════════════════════════════════════════════════════════════ */
.th-sort,
th[data-sort] {
  cursor: pointer;
  user-select: none;
  transition: color .12s ease;
}
.th-sort:hover,
th[data-sort]:hover { color: var(--brand-accent); }
.th-sort.is-active,
th[data-sort][aria-sort="ascending"],
th[data-sort][aria-sort="descending"] { color: var(--brand-accent); }

.sort-arrow {
  margin-left: 4px;
  font-size: 0.75em;
  color: var(--brand-accent);
}
