/*
 * K6 OS — design tokens (2026-04-22).
 *
 * Extracted from _BASE_CSS in shared/dashboard.py so the ~100-line
 * colour + shadow + radius block ships once per session (served by
 * nginx with long-immutable cache headers), not inline in every
 * rendered HTML response. Every route and sibling tool reads from
 * here; the SmartScout Blueprint at /smartscout/* picks it up via
 * the after_request sidebar splice (audit/smartscout_graft_2026-04-22.md).
 *
 * Source of truth: /tmp/k6_design/v1/design_handoff_k6_os/README.md
 * §Color Tokens. Change tokens here — the rest of the app picks
 * them up through var(--name).
 */

:root {
  /* Surface + foreground scale (light) */
  --bg:             oklch(99% 0.002 260);
  --panel:          oklch(100% 0 0);
  --panel-2:        oklch(98% 0.003 260);
  --border:         oklch(92% 0.005 260);
  --border-strong:  oklch(85% 0.008 260);
  --fg:             oklch(18% 0.012 260);
  --fg-2:           oklch(38% 0.01 260);
  --fg-3:           oklch(55% 0.008 260);
  --fg-4:           oklch(72% 0.006 260);

  /* Semantic colour family (each with a -soft surface bg) */
  --accent:         oklch(52% 0.19 290);
  --accent-soft:    oklch(96% 0.03 290);
  --accent-fg:      #ffffff;
  --pos:            oklch(55% 0.14 150);
  --pos-soft:       oklch(96% 0.03 150);
  --neg:            oklch(58% 0.19 25);
  --neg-soft:       oklch(96% 0.04 25);
  --warn:           oklch(70% 0.14 75);
  --warn-soft:      oklch(97% 0.04 85);

  /* Geometry + shadow */
  --shadow-sm: 0 1px 2px rgba(0,0,0,0.04), 0 0 0 1px rgba(0,0,0,0.03);
  --shadow-md: 0 2px 6px rgba(0,0,0,0.05), 0 0 0 1px rgba(0,0,0,0.04);
  --radius-lg:      18px;
  --radius-md:      14px;
  --radius-sm:      10px;
  --radius-card:    10px;
  --radius-pill:    20px;

  /* Marketplace accent colours — dots, bars, top-borders */
  --mp-amazon:   oklch(72% 0.17 55);
  --mp-bol:      oklch(60% 0.17 250);
  --mp-allegro:  oklch(60% 0.18 25);
  --mp-kaufland: oklch(62% 0.17 15);
  --mp-neutral:  oklch(60% 0.01 260);

  /* ── Legacy aliases (pre-Phase-N inner-route CSS reads these) ── */
  --surface:        var(--panel);
  --border-soft:    var(--border);
  --text-1:         var(--fg);
  --text-2:         var(--fg-2);
  --text-3:         var(--fg-3);
  --positive:       var(--pos);
  --positive-bg:    var(--pos-soft);
  --negative:       var(--neg);
  --negative-bg:    var(--neg-soft);
  --warning:        var(--warn);
  --warning-bg:     var(--warn-soft);

  /* Per-tab accents (legacy nav used these; sidebar picks them up
     to tint the active pill's icon). Kept stable so inner-route
     code that reads --tab-<id> still works. */
  --tab-marketplace:    oklch(52% 0.19 290);
  --tab-agency:         oklch(55% 0.14 150);
  --tab-cashflow:       oklch(52% 0.19 260);
  --tab-payables:       oklch(58% 0.19 25);
  --tab-supplier-split: oklch(62% 0.16 75);
  --tab-brand-ops:      oklch(62% 0.13 200);
  --tab-walker-health:  oklch(55% 0.17 305);
  --tab-smartscout:     oklch(60% 0.19 340);
  --tab-users:          oklch(50% 0.01 260);
  --tab-audit:          oklch(40% 0.012 260);

}

/*
 * ─── Unified Variant A component layer (2026-04-23) ───────────────
 *
 * Promoted from templates/dashboard.html so every native page (agency,
 * cashflow, payables, supplier-split, walker-health, brand-ops, users,
 * audit) can opt into the same card / table / tile / page-header
 * pattern with one class instead of re-rolling per-page CSS. Names are
 * `.k6-` prefixed to namespace alongside the existing `.k6-shell`
 * sidebar layer; `.k6-card` etc. is content, `.k6-shell` etc. is chrome.
 *
 * Tokens only — no hex values. Change the look in tokens.css; every
 * page picks it up. Pages that still ship their own oversized titles
 * or chunky cards override locally and should be migrated onto these
 * classes whenever they're touched.
 */

.k6-page-head {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: flex-end;
  gap: 24px;
  padding: 24px 0 20px;
  margin-bottom: 8px;
}
.k6-page-head .k6-title-block { min-width: 0; }
.k6-page-title {
  margin: 0;
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--fg);
  line-height: 1.2;
}
.k6-page-meta {
  margin-top: 6px;
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  align-items: center;
  color: var(--fg-3);
  font-size: 12px;
}
.k6-page-meta .dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--fg-4);
  display: inline-block;
}
.k6-page-actions {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
}

.k6-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  margin-bottom: 14px;
  overflow: hidden;
}
.k6-card-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: 14px 18px 12px;
  gap: 12px;
  flex-wrap: wrap;
}
.k6-card-title {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: -0.005em;
  color: var(--fg);
  margin: 0;
}
.k6-card-title .sub {
  color: var(--fg-4);
  font-weight: 400;
  margin-left: 4px;
}
.k6-card-meta {
  font-size: 12px;
  color: var(--fg-3);
}
.k6-card-body { padding: 14px 18px 18px; }
.k6-card-body.flush { padding: 0; }

.k6-stat-tiles {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 14px;
  margin-bottom: 14px;
}
@media (max-width: 900px) { .k6-stat-tiles { grid-template-columns: 1fr; } }
.k6-stat-tile {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 18px 20px 16px;
  overflow: hidden;
}
.k6-stat-tile-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--fg-3);
  text-transform: uppercase;
}
.k6-stat-tile-value {
  margin-top: 8px;
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--fg);
  line-height: 1.15;
  font-variant-numeric: tabular-nums;
}
.k6-stat-tile-value.pos { color: var(--pos); }
.k6-stat-tile-value.neg { color: var(--neg); }
.k6-stat-tile-sub {
  margin-top: 6px;
  font-size: 12px;
  color: var(--fg-3);
}

.k6-data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}
.k6-data-table thead th {
  position: sticky;
  top: 0;
  background: var(--panel-2);
  border-bottom: 1px solid var(--border);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.08em;
  color: var(--fg-3);
  text-transform: uppercase;
  padding: 10px 14px;
  text-align: right;
  user-select: none;
  white-space: nowrap;
}
.k6-data-table thead th.text { text-align: left; }
.k6-data-table thead th a {
  color: inherit;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  cursor: pointer;
}
.k6-data-table thead th a:hover { color: var(--fg); }
.k6-data-table tbody tr {
  border-bottom: 1px solid var(--border);
  height: 40px;
}
body[data-density="compact"] .k6-data-table tbody tr { height: 32px; }
.k6-data-table tbody tr:hover td { background: var(--panel-2); }
.k6-data-table tbody tr:last-child { border-bottom: none; }
.k6-data-table td {
  padding: 0 14px;
  vertical-align: middle;
  font-size: 13px;
  color: var(--fg);
}
.k6-data-table td.text { text-align: left; }
.k6-data-table td.num {
  text-align: right;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}
.k6-data-table td.num.sub {
  font-size: 12px;
  color: var(--fg-2);
}
.k6-data-table td.muted { color: var(--fg-3); font-size: 11px; }
.k6-data-table td.pos { color: var(--pos); }
.k6-data-table td.neg { color: var(--neg); }

.k6-empty-state {
  padding: 48px 24px;
  text-align: center;
  color: var(--fg-3);
  border: 1px dashed var(--border);
  border-radius: var(--radius-card);
  background: var(--panel);
}

.k6-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: var(--radius-pill);
  font-size: 11px;
  font-weight: 500;
  color: var(--fg-2);
  background: var(--panel-2);
  border: 1px solid var(--border);
}
.k6-pill.pos  { color: var(--pos);  background: var(--pos-soft);  border-color: transparent; }
.k6-pill.neg  { color: var(--neg);  background: var(--neg-soft);  border-color: transparent; }
.k6-pill.warn { color: var(--warn); background: var(--warn-soft); border-color: transparent; }

/* Product-row thumbnail (2026-04-23). Used by /dashboard's products
   table and any other per-SKU surface. The img sits on a panel-2
   background so a slow / cancelled / 404'd image still shows a
   neutral 40×40 square instead of the broken-image glyph. The img's
   own onerror handler hides it, falling back to the wrapper square. */
.k6-product-thumb {
  display: inline-block;
  width: 40px;
  height: 40px;
  flex-shrink: 0;
  background: var(--panel-2);
  border-radius: var(--radius-sm);
  overflow: hidden;
  vertical-align: middle;
}
.k6-product-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  border-radius: var(--radius-sm);
}
/* td that hosts a .k6-product-thumb — keeps the column narrow and
   centered so the thumbnail doesn't push other columns around. */
.k6-table td.thumb-cell,
.k6-data-table td.thumb-cell,
table td.thumb-cell {
  width: 56px;
  padding: 4px 8px 4px 14px;
  vertical-align: middle;
}

[data-theme="dark"] {
  --bg:            oklch(15% 0.012 260);
  --panel:         oklch(19% 0.012 260);
  --panel-2:       oklch(22% 0.012 260);
  --border:        oklch(27% 0.012 260);
  --border-strong: oklch(34% 0.012 260);
  --fg:            oklch(97% 0.005 260);
  --fg-2:          oklch(78% 0.008 260);
  --fg-3:          oklch(62% 0.01 260);
  --fg-4:          oklch(45% 0.012 260);
  --accent:        oklch(72% 0.18 290);
  --accent-soft:   oklch(28% 0.08 290);
  --pos:           oklch(75% 0.16 150);
  --pos-soft:      oklch(28% 0.06 150);
  --neg:           oklch(72% 0.18 25);
  --neg-soft:      oklch(28% 0.08 25);
  --warn:          oklch(80% 0.14 85);
  --warn-soft:     oklch(28% 0.08 85);
  --shadow-sm: 0 1px 2px rgba(0,0,0,0.40), 0 0 0 1px rgba(0,0,0,0.35);
  --shadow-md: 0 2px 6px rgba(0,0,0,0.45), 0 0 0 1px rgba(0,0,0,0.40);

}

/*
 * ─── Brand Ops design tokens (2026-04-26) ─────────────────────
 *
 * Lifted from inline serve_dashboard.py styles per the
 * 2026-04-26 audit. Funnel tile colour palette + per-tile mobile
 * breakpoint live here so dark-mode portability cascades and a
 * single sed-on-CSS adjusts every brand-ops tile colour at once.
 *
 * Palette mirrors the `COLORS` dict that previously lived in
 * `_render_funnel_strip` — same hex values, same semantics
 * (green/amber/grey for funnel-step status). The Python helper
 * now emits class names instead of inline style strings.
 */
:root {
  /* Funnel tile colour palette — operator status semantics */
  --ba-tile-green-bg:     #064e3b;
  --ba-tile-green-fg:     #dcfce7;
  --ba-tile-green-border: #166534;
  --ba-tile-green-bar:    #10b981;
  --ba-tile-green-track:  #052e16;

  --ba-tile-amber-bg:     #713f12;
  --ba-tile-amber-fg:     #fef3c7;
  --ba-tile-amber-border: #854d0e;
  --ba-tile-amber-bar:    #f59e0b;
  --ba-tile-amber-track:  #451a03;

  --ba-tile-grey-bg:      #1e293b;
  --ba-tile-grey-fg:      #94a3b8;
  --ba-tile-grey-border:  #334155;
  --ba-tile-grey-bar:     #475569;
  --ba-tile-grey-track:   #0f172a;

  /* Funnel current-step ring (yellow accent) */
  --ba-tile-current-ring: 0 0 0 2px #fde68a, 0 0 0 4px rgba(253,230,138,.25);

  /* ── Brand Ops strip + cockpit banner (audit fix #4, 2026-04-26) ──
   * Pre-fix `_render_funnel_strip` and the cockpit master-check
   * banner emitted inline hex (slate-900 strip background, deep-
   * green/red/amber banner backgrounds). Lifting them here means
   * (a) dark-mode picks up an override below, (b) tenant rebrands
   * change a token instead of a Python literal, (c) the funnel
   * strip and the cockpit banner share one palette source.
   */
  --ba-strip-bg-start:     #0b1120;
  --ba-strip-bg-end:       #0f172a;
  --ba-strip-border:       #1e293b;
  --ba-strip-shadow:       0 4px 12px rgba(0,0,0,0.25);
  --ba-strip-fg:           #e2e8f0;
  --ba-strip-fg-muted:     #94a3b8;
  --ba-strip-fg-subtle:    #64748b;
  --ba-strip-fg-emph:      #cbd5e1;
  --ba-strip-current:      #fde68a;

  /* Cockpit master-check banner — green/red/amber three-state pill. */
  --ba-banner-green-bg:     #064e3b;
  --ba-banner-green-fg:     #d1fae5;
  --ba-banner-green-border: #065f46;
  --ba-banner-red-bg:       #7f1d1d;
  --ba-banner-red-fg:       #fee2e2;
  --ba-banner-red-border:   #991b1b;
  --ba-banner-amber-bg:     #713f12;
  --ba-banner-amber-fg:     #fef3c7;
  --ba-banner-amber-border: #854d0e;
}

/* Dark theme — the brand-ops strip + banner remain dark surfaces but
 * the slate-900 family blends into the dark page bg. Bump the strip
 * background a step lighter than the page so the strip still reads
 * as a distinct surface (parity with the K6 OS card-on-bg pattern).
 * The banners stay tuned to their semantic hue but pick up the same
 * lighter-than-bg treatment so they don't disappear on a near-black
 * dashboard surface.
 */
[data-theme="dark"] {
  --ba-strip-bg-start:     oklch(24% 0.012 260);
  --ba-strip-bg-end:       oklch(28% 0.012 260);
  --ba-strip-border:       oklch(34% 0.012 260);
  --ba-strip-shadow:       0 4px 12px rgba(0,0,0,0.55);
  --ba-strip-fg:           oklch(94% 0.005 260);
  --ba-strip-fg-muted:     oklch(72% 0.008 260);
  --ba-strip-fg-subtle:    oklch(58% 0.01 260);
  --ba-strip-fg-emph:      oklch(86% 0.005 260);
  /* Funnel tile palette — re-pin in dark so the dark-on-dark legacy
   * hex doesn't disappear. Same semantic hues, lighter L. */
  --ba-tile-green-bg:       oklch(34% 0.08 150);
  --ba-tile-green-fg:       oklch(94% 0.04 150);
  --ba-tile-green-border:   oklch(42% 0.08 150);
  --ba-tile-green-bar:      oklch(72% 0.16 150);
  --ba-tile-green-track:    oklch(22% 0.06 150);
  --ba-tile-amber-bg:       oklch(34% 0.08 75);
  --ba-tile-amber-fg:       oklch(94% 0.04 75);
  --ba-tile-amber-border:   oklch(42% 0.08 75);
  --ba-tile-amber-bar:      oklch(72% 0.16 75);
  --ba-tile-amber-track:    oklch(22% 0.06 75);
  --ba-tile-grey-bg:        oklch(28% 0.012 260);
  --ba-tile-grey-fg:        oklch(72% 0.008 260);
  --ba-tile-grey-border:    oklch(38% 0.012 260);
  --ba-tile-grey-bar:       oklch(52% 0.012 260);
  --ba-tile-grey-track:     oklch(20% 0.012 260);
  /* Banner palette — lighter L, retains hue */
  --ba-banner-green-bg:     oklch(32% 0.08 150);
  --ba-banner-green-fg:     oklch(94% 0.04 150);
  --ba-banner-green-border: oklch(40% 0.08 150);
  --ba-banner-red-bg:       oklch(32% 0.10 25);
  --ba-banner-red-fg:       oklch(94% 0.04 25);
  --ba-banner-red-border:   oklch(40% 0.10 25);
  --ba-banner-amber-bg:     oklch(32% 0.08 75);
  --ba-banner-amber-fg:     oklch(94% 0.04 75);
  --ba-banner-amber-border: oklch(40% 0.08 75);
}

/* Strip + banner component shells — emit semantic class names from
 * the Python helpers, take colours from the tokens above. */
.ba-funnel-strip-frame {
  background: linear-gradient(135deg,
              var(--ba-strip-bg-start) 0%,
              var(--ba-strip-bg-end) 100%);
  border: 1px solid var(--ba-strip-border);
  border-radius: 10px;
  padding: 14px 18px;
  margin: 12px 0 16px 0;
  box-shadow: var(--ba-strip-shadow);
  color: var(--ba-strip-fg);
}
.ba-funnel-strip-head {
  display: flex; justify-content: space-between;
  align-items: baseline; margin-bottom: 10px; gap: 16px;
  flex-wrap: wrap;
}
.ba-funnel-strip-title {
  font-size: 13px; font-weight: 600; color: var(--ba-strip-fg);
}
.ba-funnel-strip-sub { color: var(--ba-strip-fg-muted); font-weight: 400; }
.ba-funnel-strip-current { color: var(--ba-strip-current); }
.ba-funnel-strip-flow { font-size: 11px; color: var(--ba-strip-fg-subtle); }
.ba-funnel-strip-hint {
  margin-top: 10px; font-size: 12px;
  color: var(--ba-strip-fg-muted); line-height: 1.5;
}
.ba-funnel-strip-hint strong { color: var(--ba-strip-fg-emph); }

.ba-banner {
  display: block; padding: 10px 14px;
  border-radius: 8px; font-size: 13px; font-weight: 500;
  margin-bottom: 10px; text-decoration: none;
}
.ba-banner-green {
  background: var(--ba-banner-green-bg);
  color: var(--ba-banner-green-fg);
  border: 1px solid var(--ba-banner-green-border);
}
.ba-banner-red {
  background: var(--ba-banner-red-bg);
  color: var(--ba-banner-red-fg);
  border: 1px solid var(--ba-banner-red-border);
}
.ba-banner-amber {
  background: var(--ba-banner-amber-bg);
  color: var(--ba-banner-amber-fg);
  border: 1px solid var(--ba-banner-amber-border);
}

/* Funnel-strip responsive grid. Audit P0#1: pre-fix the strip
 * hardcoded grid-template-columns:repeat(4,1fr) inline with NO
 * media query — at 375px every tile squashed unreadably. The
 * stack collapses 4-up → 2-up at <= 720px → 1-up at <= 480px so
 * each tile keeps room for its label, count, progress bar, and
 * diagnostic line. Sticky pin lifts on small screens (the strip
 * pins to the top of viewport on desktop but stays in flow on
 * mobile so the operator can scroll past it normally). */
.ba-funnel-strip {
  position: sticky;
  top: 0;
  z-index: 30;
}
.ba-funnel-steps {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
}
@media (max-width: 720px) {
  .ba-funnel-strip { position: static; }
  .ba-funnel-steps { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 480px) {
  .ba-funnel-steps { grid-template-columns: 1fr; }
}

/* Funnel tile colour classes — picked by status. Emit one of
 * .ba-funnel-tile-{green,amber,grey} from the Python helper. */
.ba-funnel-tile {
  border-radius: 8px;
  padding: 12px 14px;
}
.ba-funnel-tile-green {
  background: var(--ba-tile-green-bg);
  border: 1px solid var(--ba-tile-green-border);
  color: var(--ba-tile-green-fg);
}
.ba-funnel-tile-amber {
  background: var(--ba-tile-amber-bg);
  border: 1px solid var(--ba-tile-amber-border);
  color: var(--ba-tile-amber-fg);
}
.ba-funnel-tile-grey {
  background: var(--ba-tile-grey-bg);
  border: 1px solid var(--ba-tile-grey-border);
  color: var(--ba-tile-grey-fg);
}
.ba-funnel-tile.is-current {
  box-shadow: var(--ba-tile-current-ring);
}

/* Cockpit action chips minimum touch-target — audit P1#3.
 * Operator chips like "🌱 Onderzoek missende SKUs (247)" used
 * padding:5px 10px (30px tall, below HIG's 44px floor). Lifts
 * to a 44px floor on touch viewports without enlarging on
 * desktop. */
@media (max-width: 720px) {
  .ba-cta-primary,
  .ba-action-chip {
    min-height: 44px;
  }
}

/*
 * ─── K6 OS Design System v2 (2026-04-27) ──────────────────────────
 *
 * Forward-compatible token + component additions from the
 * design-system handoff (see docs/design/handoff_2026-04-27/).
 * Extends the envelope, never overwrites — every existing
 * --bg / --panel / --fg-* / --accent / --pos / --neg / --warn
 * value is untouched so engineering + operator muscle memory
 * keep working. New tokens follow the same OKLCH-only rule and
 * cascade through [data-theme="dark"].
 *
 * Adds:
 *   • Status semantic tokens — folds status-SUCCESS / FAILURE
 *     drift into one family (FIX#8 in the brief).
 *   • Type-scale tokens — the design-system type-scale values
 *     promoted from inline literals so a future scale change
 *     lands in one file.
 *   • Component primitives — page-purpose line, `?` glossary
 *     chip, basis chip, live-write button, diff modal,
 *     action-result page, drawer, coachmark. These are the
 *     "missing affordances" §6 of the brief enumerates;
 *     ship them tokenised so emerging pages can compose them.
 *
 * Helpers in shared/dashboard.py (`_render_glossary_chip`,
 * `_render_page_purpose`, `_render_action_result_page`,
 * `_render_diff_modal`, `_icon`) emit class names that pick up
 * these styles. Don't inline these patterns — go through the
 * helpers.
 */
:root {
  /* Type scale (intent-named, not size-named — change here, every
     page picks it up). Mirrors the `colors_and_type.css` mock from
     the design-system handoff. */
  --type-h1:           22px;
  --type-h1-editorial: 40px;
  --type-bignum:       54px;
  --type-h2:           20px;
  --type-h3:           16px;
  --type-card-title:   13px;
  --type-body:         14px;
  --type-body-sm:      13px;
  --type-meta:         12px;
  --type-micro:        11px;
  --type-eyebrow:      10px;

  /* Weights */
  --w-regular: 400;
  --w-mid:     450;
  --w-medium:  500;
  --w-semi:    600;
  --w-bold:    700;

  /* Tracking */
  --track-h1:           -0.015em;
  --track-editorial:    -0.025em;
  --track-bignum:       -0.03em;
  --track-card:         -0.005em;
  --track-mono:         -0.015em;
  --track-eyebrow:      0.08em;
  --track-eyebrow-wide: 0.14em;

  /* Line-height */
  --lh-body:  1.45;
  --lh-tight: 1.2;
  --lh-mono:  1.15;

  /* Status semantic family — folds the legacy status-SUCCESS /
     status-FAILURE / status-PENDING drift onto the canonical
     pos/warn/neg/fg-3 family so every history page reads
     consistently with the rest of the app. */
  --status-ok:      var(--pos);
  --status-warn:    var(--warn);
  --status-error:   var(--neg);
  --status-pending: var(--fg-3);
  --status-ok-bg:      var(--pos-soft);
  --status-warn-bg:    var(--warn-soft);
  --status-error-bg:   var(--neg-soft);
  --status-pending-bg: var(--panel-2);

  /* Drawer / modal / coachmark / glossary popover surfaces. The
     drawer + modal lift OFF the page; the coachmark + glossary
     popover hover ON it. Same shadow family but the modal +
     drawer floor at --shadow-md (defined above) and coachmark
     uses a soft accent ring instead of an alpha shadow. */
  --modal-backdrop:        rgba(0, 0, 0, 0.40);
  --drawer-shadow:         var(--shadow-md);
  --coach-ring:            0 0 0 4px var(--accent-soft),
                           0 0 0 6px rgba(0, 0, 0, 0.08);
  --gloss-popover-bg:      var(--panel);
  --gloss-popover-head-bg: var(--accent-soft);
  --gloss-popover-shadow:  var(--shadow-md);

  /* Diff-modal pane backgrounds — the "before" pane uses the
     neutral panel-2 surface; the "after" pane uses an accent-
     tinted surface to telegraph "this is what's about to ship". */
  --diff-before-bg:     var(--panel-2);
  --diff-after-bg:      var(--accent-soft);
  --diff-add-bg:        var(--pos-soft);
  --diff-add-fg:        var(--pos);
  --diff-remove-bg:     var(--neg-soft);
  --diff-remove-fg:     var(--neg);
}

[data-theme="dark"] {
  --modal-backdrop:        rgba(0, 0, 0, 0.55);
  --coach-ring:            0 0 0 4px var(--accent-soft),
                           0 0 0 6px rgba(255, 255, 255, 0.06);
}

/* ─── Page-purpose line — applied below H1 on every canonical
 *  page (FIX#14 in the brief). One sentence describing what the
 *  page is for and who acts on it. Constrained max-width keeps
 *  the line readable on wide editorial layouts. */
.k6-page-purpose {
  margin-top: 6px;
  font-size: var(--type-body-sm);
  color: var(--fg-2);
  max-width: 720px;
  line-height: var(--lh-body);
}

/* ─── `?` glossary chip — inline-with-text, hover/click reveals
 *  a 1-2 sentence definition. Used on the first appearance per
 *  page of K6 institutional terms (Werkbank-funnel, Push (dry),
 *  BASIS · ACTUAL, rate_limited, LOW sidecar). See
 *  shared/dashboard.py::_render_glossary_chip.
 *
 *  Implementation note: the popover is :hover and :focus-within
 *  triggered via pure CSS (the chip is a <span tabindex="0">)
 *  so it lands without client-side JS — matches the "no JS for
 *  data state" non-negotiable. */
.k6-gloss {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px; height: 16px;
  margin-left: 4px;
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 10px;
  font-weight: 700;
  cursor: help;
  vertical-align: 1px;
  border: none;
  user-select: none;
}
.k6-gloss:hover, .k6-gloss:focus-visible { filter: brightness(0.95); outline: none; }
.k6-gloss-host { position: relative; display: inline; }
.k6-gloss-popover {
  position: absolute;
  top: calc(100% + 8px);
  left: -4px;
  min-width: 280px;
  max-width: 360px;
  background: var(--gloss-popover-bg);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: var(--gloss-popover-shadow);
  padding: 0;
  font-size: var(--type-meta);
  color: var(--fg-2);
  line-height: var(--lh-body);
  z-index: 50;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
  transform: translateY(-4px);
  transition: opacity 0.12s, transform 0.12s;
}
.k6-gloss-host:hover .k6-gloss-popover,
.k6-gloss-host:focus-within .k6-gloss-popover {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}
.k6-gloss-popover .head {
  padding: 9px 14px 7px;
  background: var(--gloss-popover-head-bg);
  border-bottom: 1px solid var(--border);
}
.k6-gloss-popover .term {
  font-size: var(--type-eyebrow);
  font-weight: var(--w-semi);
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--accent);
}
.k6-gloss-popover .body { padding: 10px 14px 12px; }
.k6-gloss-popover .body code {
  font-family: 'JetBrains Mono', ui-monospace, Menlo, Consolas, monospace;
  font-size: 11px;
  color: var(--fg);
  background: var(--panel-2);
  padding: 1px 5px;
  border-radius: 3px;
  border: 1px solid var(--border);
}

/* ─── Live-API write button — visually distinct from nav/edit
 *  links. Coloured fill, 6px radius. ALWAYS opens a confirm /
 *  diff-preview modal — never fires direct (FIX#11 in the
 *  brief). The .danger variant is for irreversible destructive
 *  writes (delete listing, deactivate offer). */
.k6-live-write {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: 6px;
  background: var(--accent);
  color: var(--accent-fg);
  font-size: 12px;
  font-weight: var(--w-medium);
  border: none;
  cursor: pointer;
  text-decoration: none;
  font-family: inherit;
  line-height: 1.2;
}
.k6-live-write:hover { filter: brightness(1.06); text-decoration: none; }
.k6-live-write:active { transform: translateY(1px); }
.k6-live-write:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.k6-live-write.danger { background: var(--neg); }
.k6-live-write[disabled],
.k6-live-write.is-disabled {
  background: var(--panel-2);
  color: var(--fg-3);
  cursor: not-allowed;
  filter: none;
}

/* ─── Basis chip (cashflow / brand-ops basis label) — encodes
 *  whether a tile total is gefactureerd (ACTUAL) or modelled
 *  (MODEL / MIXED). Lives on the cashflow tile-grid + brand-ops
 *  cockpit. */
.k6-basis-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 7px;
  border-radius: 4px;
  font-size: var(--type-eyebrow);
  font-weight: var(--w-semi);
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  font-family: 'JetBrains Mono', ui-monospace, Menlo, Consolas, monospace;
}
.k6-basis-chip.actual { background: var(--pos-soft); color: var(--pos); }
.k6-basis-chip.model  { background: var(--warn-soft); color: var(--warn); }
.k6-basis-chip.mixed  { background: var(--warn-soft); color: var(--warn); }
.k6-basis-chip.unknown { background: var(--neg-soft); color: var(--neg); }
.k6-basis-chip .d { width: 5px; height: 5px; border-radius: 50%; background: currentColor; }

/* ─── Diff-preview modal — current vs sent payload on every
 *  live-API write (FIX#11 + missing affordance §6.4). The Python
 *  helper emits the modal markup; this stylesheet shapes it.
 *  Two-pane grid collapses to single-column at <720px. */
.k6-modal-backdrop {
  position: fixed;
  inset: 0;
  background: var(--modal-backdrop);
  z-index: 100;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 24px 16px;
  overflow-y: auto;
}
.k6-diff-modal {
  width: 100%;
  max-width: 680px;
  background: var(--panel);
  border-radius: 14px;
  border: 1px solid var(--border);
  box-shadow: var(--shadow-md);
  overflow: hidden;
}
.k6-diff-modal-head {
  padding: 14px 20px;
  background: var(--accent-soft);
  border-bottom: 1px solid var(--border);
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
}
.k6-diff-modal-title {
  font-size: var(--type-body);
  font-weight: var(--w-semi);
  letter-spacing: -0.01em;
  color: var(--fg);
  margin: 0;
}
.k6-diff-modal-meta {
  margin-top: 4px;
  font-size: var(--type-micro);
  color: var(--fg-3);
  display: flex;
  gap: 8px;
  align-items: center;
}
.k6-diff-modal-meta .live-tag {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-family: 'JetBrains Mono', ui-monospace, Menlo, Consolas, monospace;
  font-size: 10px;
  color: var(--neg);
  font-weight: var(--w-medium);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.k6-diff-modal-meta .live-tag::before {
  content: "";
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--neg);
}
.k6-diff-modal-body { padding: 16px 20px; }
.k6-diff-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}
@media (max-width: 720px) { .k6-diff-grid { grid-template-columns: 1fr; } }
.k6-diff-pane { border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.k6-diff-pane-head {
  padding: 8px 12px;
  font-size: var(--type-eyebrow);
  font-weight: var(--w-semi);
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  border-bottom: 1px solid var(--border);
}
.k6-diff-pane.before .k6-diff-pane-head { background: var(--diff-before-bg); color: var(--fg-3); }
.k6-diff-pane.after  .k6-diff-pane-head { background: var(--diff-after-bg);  color: var(--accent); }
.k6-diff-pane-body {
  padding: 12px 14px;
  font-size: var(--type-meta);
  line-height: var(--lh-body);
  color: var(--fg-2);
  font-family: 'JetBrains Mono', ui-monospace, Menlo, Consolas, monospace;
}
.k6-diff-add { background: var(--diff-add-bg); color: var(--diff-add-fg); padding: 1px 4px; border-radius: 3px; font-weight: var(--w-medium); }
.k6-diff-rm  { background: var(--diff-remove-bg); color: var(--diff-remove-fg); text-decoration: line-through; padding: 1px 4px; border-radius: 3px; }
.k6-diff-modal-foot {
  padding: 14px 20px;
  border-top: 1px solid var(--border);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  background: var(--panel-2);
}

/* ─── Action-result page (shared shape for async-spawn POSTs:
 *  /bol-rescan, /asin-extract, /keepa-velocity-fetch, /payables/
 *  reconnect, /exact-callback). Replaces the "we kicked it off"
 *  static template with three states (in-flight / success /
 *  failure) per missing affordance §6.5. */
.k6-action-result {
  max-width: 560px;
  margin: 24px auto;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 24px 28px 22px;
}
.k6-action-result-head {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 14px;
}
.k6-action-result-glyph {
  width: 36px; height: 36px;
  border-radius: 8px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.k6-action-result.is-pending .k6-action-result-glyph { background: var(--accent-soft); color: var(--accent); }
.k6-action-result.is-success .k6-action-result-glyph { background: var(--pos-soft); color: var(--pos); }
.k6-action-result.is-error   .k6-action-result-glyph { background: var(--neg-soft); color: var(--neg); }
.k6-action-result-title {
  font-size: var(--type-h2);
  font-weight: var(--w-semi);
  letter-spacing: var(--track-h1);
  margin: 0;
}
.k6-action-result-meta {
  margin: 4px 0 0;
  font-size: var(--type-meta);
  color: var(--fg-3);
}
.k6-action-result-tail {
  margin-top: 14px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 10px 12px;
  font-family: 'JetBrains Mono', ui-monospace, Menlo, Consolas, monospace;
  font-size: var(--type-micro);
  color: var(--fg-2);
  line-height: 1.5;
  max-height: 180px;
  overflow-y: auto;
  white-space: pre-wrap;
}
.k6-action-result-actions {
  margin-top: 16px;
  display: flex;
  gap: 8px;
  justify-content: flex-end;
}

/* ─── Drawer (CSS :target driven) — opens from a row to show
 *  per-SKU history / per-payable detail / per-audit-row payload.
 *  Pure CSS — no client-side JS. Click triggers `<a href="#row-N">`
 *  → :target activates the drawer pane → click again or another
 *  row resets via <a href="#close">. */
.k6-drawer {
  position: fixed;
  top: 0;
  right: -480px;
  width: min(480px, 92vw);
  height: 100vh;
  background: var(--panel);
  border-left: 1px solid var(--border);
  box-shadow: var(--drawer-shadow);
  z-index: 80;
  transition: right 0.22s cubic-bezier(0.4, 0, 0.2, 1);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.k6-drawer:target { right: 0; }
.k6-drawer-head {
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.k6-drawer-title {
  font-size: var(--type-card-title);
  font-weight: var(--w-semi);
  letter-spacing: var(--track-card);
  margin: 0;
}
.k6-drawer-close {
  width: 28px; height: 28px;
  border-radius: 6px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--fg-3);
  text-decoration: none;
  border: 1px solid var(--border);
}
.k6-drawer-close:hover { color: var(--fg); background: var(--panel-2); }
.k6-drawer-body {
  flex: 1;
  overflow-y: auto;
  padding: 14px 18px 18px;
}

/* ─── Coachmark (first-run overlay on /brand-ops/<brand>/bol-
 *  assortment, dismissed via localStorage key
 *  `k6-tour-seen-bol-assortment`). The mark is a soft accent
 *  ring + a card with the step copy + Next/Skip controls. The
 *  show/hide is gated by an inline <head> script that reads the
 *  localStorage key — same pattern as theme/density. */
.k6-coach-target {
  position: relative;
  z-index: 60;
  box-shadow: var(--coach-ring);
  border-radius: var(--radius-sm);
}
.k6-coach-card {
  position: absolute;
  z-index: 70;
  width: min(320px, 80vw);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  padding: 14px 16px 12px;
  font-size: var(--type-meta);
  color: var(--fg-2);
  line-height: var(--lh-body);
}
.k6-coach-step {
  font-size: var(--type-eyebrow);
  font-weight: var(--w-semi);
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--accent);
}
.k6-coach-title {
  margin: 4px 0 6px;
  font-size: var(--type-card-title);
  font-weight: var(--w-semi);
  color: var(--fg);
}
.k6-coach-actions {
  margin-top: 12px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
}

/* ─── Sidebar bottom-bar (mobile, role-aware) — placeholder
 *  surface so the breakpoint flip works while engineering wires
 *  the role-aware tab list (admin/operator = 5-tab, partner =
 *  3-tab). At <=768px the sticky sidebar yields to a fixed
 *  bottom-bar; today the desktop sidebar squashes to 64px which
 *  is the largest single missing affordance per the brief.
 *  The full list comes from `_render_mobile_bottom_bar` in
 *  shared/dashboard.py. */
.k6-mobile-bottom-bar {
  display: none;
}
@media (max-width: 768px) {
  .k6-mobile-bottom-bar {
    display: flex;
    position: fixed;
    bottom: 0; left: 0; right: 0;
    height: 64px;
    background: var(--panel);
    border-top: 1px solid var(--border);
    z-index: 40;
    padding: 6px 0 max(6px, env(safe-area-inset-bottom));
    align-items: stretch;
    box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.04);
  }
  .k6-mobile-bottom-bar a {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    color: var(--fg-3);
    text-decoration: none;
    font-size: 10px;
    font-weight: var(--w-semi);
    letter-spacing: 0.04em;
    text-transform: uppercase;
  }
  .k6-mobile-bottom-bar a.active { color: var(--accent); }
  .k6-mobile-bottom-bar a:hover { color: var(--fg); }
  .k6-shell-with-mobile-bar .k6-main { padding-bottom: 80px; }
}

/* ─── Why-is-this-red? hover affordance — every status pill,
 *  disabled button, and "Niet beschikbaar" cell can carry a
 *  one-line explanation via `data-why="reason"`. CSS-only pure
 *  pattern — the tooltip surface is a ::after pseudo-element on
 *  the hover/focus state. */
[data-why] {
  position: relative;
  cursor: help;
}
[data-why]:hover::after,
[data-why]:focus-visible::after {
  content: attr(data-why);
  position: absolute;
  bottom: calc(100% + 6px);
  left: 0;
  background: var(--panel);
  color: var(--fg-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px 10px;
  font-size: var(--type-micro);
  font-weight: var(--w-regular);
  letter-spacing: 0;
  text-transform: none;
  white-space: nowrap;
  max-width: 320px;
  white-space: normal;
  width: max-content;
  box-shadow: var(--shadow-sm);
  z-index: 30;
  pointer-events: none;
}

/* ─── Status pill family — folds the legacy status-SUCCESS /
 *  status-FAILURE / status-PENDING drift on history pages onto
 *  the canonical pos/warn/neg/pending family (FIX#8). Existing
 *  .k6-pill.pos / .neg / .warn already shipped above; this adds
 *  the `pending` variant + a synonym alias for `error`. */
.k6-pill.pending { color: var(--status-pending); background: var(--status-pending-bg); border-color: transparent; }
.k6-pill.error   { color: var(--status-error);   background: var(--status-error-bg);   border-color: transparent; }
.k6-pill.ok      { color: var(--status-ok);      background: var(--status-ok-bg);      border-color: transparent; }

/*
 * ─── Mobile design system v2 (2026-04-27 handoff) ────────────────
 *
 * Bottom-sheet, mobile stat-tile, and card-stream primitives the
 * mobile handoff calls for. Surfaces only emitted on ≤768px
 * viewports — desktop ignores them via the gating @media block.
 *
 * Bottom sheets replace centered modals on mobile (push-confirm,
 * filter, approve). Mobile invoice flows use `.k6-bottom-sheet`
 * with a slide-up animation; desktop keeps `.k6-diff-modal`.
 */

@media (max-width: 768px) {
  /* Bottom sheet — slide-up panel anchored to the viewport bottom.
     Backdrop sits behind, sheet animates from y=100% to 0. The
     close affordance is a CSS :target pattern: <a href="#close">
     resets the sheet, <a href="#sheet-id"> opens it. */
  .k6-bottom-sheet-backdrop {
    position: fixed;
    inset: 0;
    background: var(--modal-backdrop);
    z-index: 90;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.18s;
  }
  .k6-bottom-sheet:target ~ .k6-bottom-sheet-backdrop,
  .k6-bottom-sheet.is-open ~ .k6-bottom-sheet-backdrop {
    opacity: 1;
    pointer-events: auto;
  }

  .k6-bottom-sheet {
    position: fixed;
    left: 0; right: 0;
    bottom: 0;
    transform: translateY(100%);
    background: var(--panel);
    border-top-left-radius: 18px;
    border-top-right-radius: 18px;
    border-top: 1px solid var(--border);
    box-shadow: 0 -8px 24px rgba(0, 0, 0, 0.12);
    z-index: 95;
    padding: 8px 18px max(18px, env(safe-area-inset-bottom));
    max-height: 88vh;
    overflow-y: auto;
    transition: transform 0.22s cubic-bezier(0.4, 0, 0.2, 1);
  }
  .k6-bottom-sheet:target,
  .k6-bottom-sheet.is-open { transform: translateY(0); }

  .k6-bottom-sheet-grabber {
    width: 36px; height: 4px;
    background: var(--border-strong);
    border-radius: 2px;
    margin: 6px auto 12px;
  }
  .k6-bottom-sheet-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 12px;
  }
  .k6-bottom-sheet-title {
    font-size: var(--type-h3);
    font-weight: var(--w-semi);
    letter-spacing: -0.01em;
    margin: 0;
  }
  .k6-bottom-sheet-close {
    width: 32px; height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--fg-3);
    text-decoration: none;
    border-radius: 8px;
  }
  .k6-bottom-sheet-close:hover { color: var(--fg); background: var(--panel-2); }
  .k6-bottom-sheet-body { padding: 0 0 16px; }
  .k6-bottom-sheet-footer {
    position: sticky;
    bottom: 0;
    background: var(--panel);
    padding: 12px 0 8px;
    border-top: 1px solid var(--border);
    display: flex;
    gap: 8px;
    margin-top: 12px;
  }
  .k6-bottom-sheet-footer .k6-live-write { flex: 1; justify-content: center; }

  /* Mobile diff-modal collapse: when .k6-diff-modal lands inside a
     mobile viewport, escalate it to a full-height bottom-sheet
     surface. Same markup, mobile-tuned skin. */
  .k6-modal-backdrop:has(.k6-diff-modal) {
    align-items: flex-end;
    padding: 0;
  }
  .k6-modal-backdrop .k6-diff-modal {
    border-top-left-radius: 18px;
    border-top-right-radius: 18px;
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;
    max-height: 92vh;
    overflow-y: auto;
    width: 100%;
    max-width: none;
  }

  /* Mobile FAB (Floating Action Button) — anchored bottom-right
     above the bottom-bar. Used on /brand-ops mobile (Push) and
     /payables mobile (Approve next). */
  .k6-fab {
    position: fixed;
    right: 16px;
    bottom: calc(78px + env(safe-area-inset-bottom));
    z-index: 50;
    width: 56px;
    height: 56px;
    border-radius: 28px;
    background: var(--accent);
    color: var(--accent-fg);
    border: none;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 6px 16px -4px rgba(0, 0, 0, 0.25);
    cursor: pointer;
    text-decoration: none;
  }
  .k6-fab:hover { filter: brightness(1.06); }

  /* Mobile card-stream — replaces tables with vertical card stacks.
     Each row is a flex column with thumb (optional) + title + meta
     + value. Used by /brand-ops mobile + /payables mobile. */
  .k6-mobile-card-stream {
    display: flex;
    flex-direction: column;
    gap: 8px;
  }
  .k6-mobile-card {
    display: grid;
    grid-template-columns: 40px 1fr auto;
    column-gap: 12px;
    align-items: center;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 12px 14px;
    text-decoration: none;
    color: var(--fg);
  }
  .k6-mobile-card-thumb {
    width: 40px; height: 40px;
    background: var(--panel-2);
    border-radius: 8px;
    grid-row: 1 / span 2;
  }
  .k6-mobile-card-title {
    font-size: var(--type-body-sm);
    font-weight: var(--w-medium);
    line-height: 1.3;
    overflow: hidden;
    text-overflow: ellipsis;
    -webkit-line-clamp: 1;
    -webkit-box-orient: vertical;
  }
  .k6-mobile-card-meta {
    font-size: var(--type-micro);
    color: var(--fg-3);
    line-height: 1.4;
    margin-top: 2px;
  }
  .k6-mobile-card-value {
    grid-column: 3;
    grid-row: 1 / span 2;
    font-family: 'JetBrains Mono', ui-monospace, Menlo, Consolas, monospace;
    font-variant-numeric: tabular-nums;
    font-size: var(--type-body-sm);
    font-weight: var(--w-semi);
    color: var(--fg);
    text-align: right;
    align-self: center;
  }
  .k6-mobile-card-value.pos { color: var(--pos); }
  .k6-mobile-card-value.neg { color: var(--neg); }
  .k6-mobile-card.severity-red    { border-left: 3px solid var(--neg); }
  .k6-mobile-card.severity-amber  { border-left: 3px solid var(--warn); }
  .k6-mobile-card.severity-green  { border-left: 3px solid var(--pos); }

  /* Hero number — used on the mobile dashboard's "today net" tile
     and the cashflow weekly net hero. Larger than the desktop
     stat-tile-value because mobile owns more vertical space per
     primary metric. */
  .k6-mobile-hero {
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 14px;
    padding: 18px 18px 16px;
    margin-bottom: 12px;
  }
  .k6-mobile-hero-eyebrow {
    font-size: var(--type-eyebrow);
    font-weight: var(--w-semi);
    letter-spacing: var(--track-eyebrow);
    text-transform: uppercase;
    color: var(--fg-3);
  }
  .k6-mobile-hero-value {
    margin-top: 8px;
    font-family: 'JetBrains Mono', ui-monospace, Menlo, Consolas, monospace;
    font-variant-numeric: tabular-nums;
    font-size: 40px;
    font-weight: var(--w-semi);
    letter-spacing: var(--track-bignum);
    line-height: var(--lh-mono);
    color: var(--fg);
  }
  .k6-mobile-hero-value.pos { color: var(--pos); }
  .k6-mobile-hero-value.neg { color: var(--neg); }
  .k6-mobile-hero-meta {
    margin-top: 6px;
    font-size: var(--type-meta);
    color: var(--fg-3);
  }

  /* Mobile segmented control — used on mobile brand-ops to switch
     funnel stages (Onderzoek / Verbeter / Klaar / Activeer). */
  .k6-mobile-segmented {
    display: inline-flex;
    background: var(--panel-2);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 3px;
    width: 100%;
    margin-bottom: 12px;
  }
  .k6-mobile-segmented a {
    flex: 1;
    text-align: center;
    padding: 8px 4px;
    border-radius: 7px;
    font-size: var(--type-meta);
    font-weight: var(--w-medium);
    color: var(--fg-3);
    text-decoration: none;
  }
  .k6-mobile-segmented a.is-active {
    background: var(--panel);
    color: var(--fg);
    box-shadow: var(--shadow-sm);
  }
}

/* Bottom-sheet desktop fallback — when emitted on a wide viewport
 * (e.g. tablet rotated to landscape), centre it as a small dialog
 * instead of the slide-up shape. */
@media (min-width: 769px) {
  .k6-bottom-sheet {
    position: fixed;
    left: 50%;
    bottom: 50%;
    transform: translate(-50%, 50%);
    max-width: 480px;
    border-radius: 14px;
    border: 1px solid var(--border);
    box-shadow: var(--shadow-md);
    padding: 18px 22px max(20px, env(safe-area-inset-bottom));
  }
  .k6-bottom-sheet-grabber { display: none; }
}

