/* ==========================================================================
   Drivra — component library
   Requires tokens.css. The behavioural contract for every component here
   lives in SYSTEM.md (§ "Component contracts"); this file is only its look.

   Brand rules this file enforces (README "The rules behind the look"):
     rules not boxes · one accent · flat · editorial hierarchy · quiet motion

   Section index
     01 base              08 search             15 tabs
     02 utilities         09 query bar/chips    16 cards
     03 app shell         10 data table         17 attributes / entity head
     04 page header       11 pagination         18 history / audit
     05 buttons           12 KPIs               19 banners / toasts
     06 menus             13 charts             20 dialog / drawer
     07 forms             14 status/freshness/  21 empty / loading states
                             tooltips           22 maps
                                                23 dashboard layout
                                                24 simple table · badge · tag ·
                                                   steps · file drop · accordion
   ========================================================================== */

/* ── 01 base ─────────────────────────────────────────────────────────────── */

*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.55;
}

h1,
h2,
h3,
h4 {
  font-family: var(--font);
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -0.02em;
  margin: 0;
}

p {
  margin: 0;
}

a {
  color: inherit;
  text-decoration: none;
  transition: color 0.2s var(--ease-out), background-color 0.2s var(--ease-out), border-color 0.2s var(--ease-out);
}

button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}

/* [hidden] must always win over component display rules (.icon-btn, .banner, .dt-bulk…). */
[hidden] {
  display: none !important;
}

::selection {
  background: color-mix(in srgb, var(--color-accent) 28%, transparent);
}

:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* The logo's wordmark is navy: in dark mode swap to a light-ink variant (same artwork, recoloured:
   wordmark → dark --color-text, mark → dark --color-accent). Every logo placement in this system. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) :is(.shell-brand img, .auth-card .logo, .ambient-head img) {
    content: url("assets/logo-dark.png");
  }
}
:root[data-theme="dark"] :is(.shell-brand img, .auth-card .logo, .ambient-head img) {
  content: url("assets/logo-dark.png");
}

/* ── 02 utilities / editorial vocabulary ─────────────────────────────────── */

.visually-hidden {
  position: absolute !important;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  left: 8px;
  top: -100px;
  z-index: var(--z-tooltip);
  background: var(--color-text);
  color: var(--color-bg);
  padding: 8px 14px;
  font-weight: 700;
  font-size: 13px;
}

.skip-link:focus {
  top: 8px;
}

.text-muted {
  color: var(--color-muted);
}

.num {
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.mono {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.92em;
}

.label {
  font-size: 11px;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  font-weight: 600;
}

.kicker {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 11px;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--color-muted);
  margin: 0 0 20px;
}

.kicker::before {
  content: "";
  width: 22px;
  height: 2px;
  background: var(--color-accent);
  flex: none;
}

.subhead {
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--color-muted);
  margin: 0 0 16px;
}

.inline-link {
  color: var(--color-accent-700);
  font-weight: 700;
  border-bottom: 1px solid transparent;
}

.inline-link:hover {
  border-bottom-color: var(--color-accent-700);
}

.divider {
  height: 1px;
  border: 0;
  margin: 0;
  background: var(--color-divider-strong);
}

.section {
  padding: var(--space-8) 0;
  border-top: 1px solid var(--color-divider-strong);
}

.section > h2,
.section-title {
  font-size: 18px;
  letter-spacing: -0.01em;
  margin: 0 0 var(--space-4);
}

.stack > * + * {
  margin-top: var(--space-4);
}

.cluster {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}

.spacer {
  flex: 1;
}

/* Scroll-reveal is for marketing pages only. Do not use in the app. */
.reveal {
  transition: opacity 0.5s var(--ease-out), transform 0.5s var(--ease-out);
}

.js-reveal .reveal {
  opacity: 0;
  transform: translateY(12px);
}

.reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
}

/* ── 03 app shell ────────────────────────────────────────────────────────── */
/* Global nav (left) · top bar (search, freshness, user) · main.
   <div class="shell"><nav class="shell-nav">…</nav><header class="shell-top">…</header><main class="shell-main" id="main">…</main></div> */

.shell {
  display: grid;
  grid-template-columns: var(--shell-nav-w) minmax(0, 1fr);
  grid-template-rows: var(--shell-top-h) 1fr;
  grid-template-areas:
    "nav top"
    "nav main";
  min-height: 100vh;
}

.shell-nav {
  grid-area: nav;
  border-right: 1px solid var(--color-divider-strong);
  background: var(--color-bg);
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
}

/* The nav scrolls when it's taller than the window; its children never shrink to fit. */
.shell-nav > * {
  flex: none;
}

.shell-brand {
  display: flex;
  align-items: center;
  height: var(--shell-top-h);
  padding: 0 20px;
  border-bottom: 1px solid var(--color-divider);
}

.shell-brand img {
  height: 26px;
  width: auto;
}

/* Sectioned nav: Drivra Engine is one platform with several products. The Platform section comes
   first, then one collapsible section per product (Fleet, Aggregator, Drive to own), then Admin. A
   section is a <details>: open/closed is remembered per person, and the section holding the current
   page is always open. */
.nav-section {
  border-top: 1px solid var(--color-divider);
}

.nav-section:first-of-type {
  border-top: 0;
}

.nav-section > summary {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 40px;
  padding: 0 20px;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--color-text);
  cursor: pointer;
  list-style: none;
  user-select: none;
}

.nav-section > summary::-webkit-details-marker {
  display: none;
}

.nav-section > summary::after {
  content: "";
  margin-left: auto;
  width: 7px;
  height: 7px;
  border-right: 2px solid var(--color-muted);
  border-bottom: 2px solid var(--color-muted);
  transform: rotate(-45deg);
  transition: transform 0.15s var(--ease-out);
}

.nav-section[open] > summary::after {
  transform: rotate(45deg);
}

.nav-section > summary:hover {
  background: var(--color-surface);
}

.nav-section > summary:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: -2px;
}

/* The section you're in: a quiet accent on its label, so a collapsed sidebar still says where you are. */
.nav-section.is-current > summary {
  color: var(--color-accent-700);
}

.nav-section .nav-group {
  padding: 2px 0 8px;
}

.nav-section .nav-group + .nav-group {
  border-top: 0;
}

.nav-section .nav-group-label {
  padding-top: 6px;
}

.nav-group {
  padding: 14px 0 6px;
}

.nav-group + .nav-group {
  border-top: 1px solid var(--color-divider);
}

.nav-group-label {
  padding: 0 20px 6px;
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--color-muted);
}

.nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 34px;
  padding: 0 20px;
  font-size: 14px;
  font-weight: 600;
  color: var(--color-text);
  border-left: 2px solid transparent;
}

.nav-item:hover {
  background: var(--color-surface);
}

.nav-item[aria-current="page"] {
  color: var(--color-accent-700);
  border-left-color: var(--color-accent);
  background: var(--color-accent-100);
}

.nav-item .count {
  margin-left: auto;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--color-muted);
}

.shell-top {
  grid-area: top;
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: 0 var(--space-8);
  border-bottom: 1px solid var(--color-divider-strong);
  background: var(--color-bg);
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
}

.shell-main {
  grid-area: main;
  min-width: 0;
  padding: var(--space-6) var(--space-8) var(--space-12);
}

.shell-menu-toggle {
  display: none;
}

@media (max-width: 860px) {
  .shell {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "top"
      "main";
  }
  .shell-nav {
    position: fixed;
    inset: 0 auto 0 0;
    width: min(86vw, 300px);
    z-index: var(--z-drawer);
    transform: translateX(-100%);
    transition: transform 0.25s var(--ease-out);
    box-shadow: var(--shadow-overlay);
  }
  .shell.nav-open .shell-nav {
    transform: none;
  }
  .shell-menu-toggle {
    display: inline-flex;
  }
  .shell-top,
  .shell-main {
    padding-inline: 16px;
  }
  /* A phone-width top bar keeps only what you act on: the menu, freshness (truncated) and the
     action buttons. Context and user labels drop out — the open nav shows where you are. */
  .shell-top {
    gap: var(--space-2);
  }
  .shell-top > .label {
    display: none;
  }
  .shell-top .fresh {
    display: block;
    flex: 0 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .shell-top .fresh::before {
    display: inline-block;
    margin-right: 6px;
    vertical-align: middle;
  }
}

/* Breadcrumbs: where am I, and the way back with context intact. */
.breadcrumbs ol {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: 12px;
  font-weight: 600;
  color: var(--color-muted);
}

.breadcrumbs li + li::before {
  content: "/";
  margin-right: 6px;
  color: var(--color-faint);
}

.breadcrumbs a:hover {
  color: var(--color-accent-700);
}

.breadcrumbs [aria-current="page"] {
  color: var(--color-text);
}

/* ── 04 page header ──────────────────────────────────────────────────────── */
/* Identity → context line → one primary action. Exactly one .page-head per page. */

.page-head {
  display: flex;
  align-items: flex-end;
  gap: var(--space-6);
  flex-wrap: wrap;
  padding: var(--space-4) 0 var(--space-6);
}

.page-head-text {
  flex: 1 1 320px;
  min-width: 0;
}

.page-head .breadcrumbs {
  margin-bottom: 10px;
}

.page-title {
  font-size: clamp(1.75rem, 1.5rem + 1vw, 2.25rem);
  margin: 0;
}

.page-context {
  margin-top: 8px;
  font-size: 14px;
  color: var(--color-muted);
  max-width: 70ch;
}

.page-actions {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
}

/* ── 05 buttons ──────────────────────────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: var(--control-h);
  padding: 0 16px;
  font-family: var(--font);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.01em;
  line-height: 1;
  white-space: nowrap;
  border-radius: var(--radius);
  border: 1px solid transparent;
  cursor: pointer;
  text-decoration: none;
  transition: background 0.2s var(--ease-out), color 0.2s var(--ease-out), border-color 0.2s var(--ease-out);
}

.btn-lg {
  min-height: 46px;
  padding: 0 26px;
}

.btn-sm {
  min-height: var(--control-h-sm);
  padding: 0 10px;
  font-size: 12px;
}

.btn-primary {
  background: var(--color-accent);
  color: var(--color-on-accent);
  border-color: var(--color-accent);
}

.btn-primary:hover {
  background: var(--color-accent-700);
  border-color: var(--color-accent-700);
}

.btn-secondary {
  background: transparent;
  color: var(--color-text);
  border-color: var(--color-divider-strong);
}

.btn-secondary:hover {
  background: var(--color-text);
  color: var(--color-bg);
  border-color: var(--color-text);
}

.btn-ghost {
  background: transparent;
  color: var(--color-text);
}

.btn-ghost:hover {
  background: var(--color-surface);
}

.btn-danger {
  background: var(--status-critical);
  color: var(--color-on-status);
  border-color: var(--status-critical);
}

.btn-danger:hover {
  background: color-mix(in srgb, var(--status-critical) 80%, #000);
}

.btn-danger-quiet {
  background: transparent;
  color: var(--status-critical);
  border-color: color-mix(in srgb, var(--status-critical) 50%, transparent);
}

.btn-danger-quiet:hover {
  background: var(--status-critical-tint);
}

/* Disabled: keep it visible and explain why via aria-describedby / .why-disabled.
   Prefer aria-disabled="true" over [disabled] so it stays focusable and the reason is reachable. */
.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: 0.45;
  cursor: not-allowed;
}

.btn-primary[aria-disabled="true"]:hover {
  background: var(--color-accent);
}

.btn-secondary[aria-disabled="true"]:hover {
  background: transparent;
  color: var(--color-text);
  border-color: var(--color-divider-strong);
}

/* Busy: the label stays; a 2px bar sweeps the bottom edge. Set aria-busy="true". */
.btn[aria-busy="true"] {
  position: relative;
  overflow: hidden;
  cursor: progress;
}

.btn[aria-busy="true"]::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  height: 2px;
  width: 40%;
  background: currentColor;
  animation: sweep 1.1s var(--ease-out) infinite;
}

@keyframes sweep {
  from {
    transform: translateX(-100%);
  }
  to {
    transform: translateX(250%);
  }
}

.icon-btn {
  display: inline-grid;
  place-items: center;
  width: var(--control-h);
  height: var(--control-h);
  padding: 0;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius);
  color: var(--color-text);
  cursor: pointer;
}

.icon-btn:hover {
  background: var(--color-surface);
}

.icon-btn.sm {
  width: var(--control-h-sm);
  height: var(--control-h-sm);
}

.icon {
  width: 16px;
  height: 16px;
  flex: none;
  stroke: currentColor;
  fill: none;
  stroke-width: 2;
  stroke-linecap: square;
}

.btn-group {
  display: inline-flex;
}

.btn-group > .btn {
  border-radius: 0;
}

.btn-group > .btn + .btn {
  margin-left: -1px;
}

.btn-group > .btn[aria-pressed="true"] {
  background: var(--color-text);
  color: var(--color-bg);
  border-color: var(--color-text);
}

.why-disabled {
  font-size: 12px;
  color: var(--color-muted);
}

/* ── 06 menus / dropdowns ────────────────────────────────────────────────── */

.menu-wrap {
  position: relative;
  display: inline-block;
}

.menu,
.menu-surface {
  background: var(--color-bg);
  border: 1px solid var(--color-divider-strong);
  box-shadow: var(--shadow-overlay);
}

.menu {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  z-index: var(--z-dropdown);
  min-width: 200px;
  padding: 4px 0;
  margin: 0;
  list-style: none;
}

.menu.align-left {
  left: 0;
  right: auto;
}

.menu[hidden] {
  display: none;
}

.menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 34px;
  padding: 9px 14px;
  background: none;
  border: 0;
  text-align: left;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.35;
  cursor: pointer;
}

/* A run of items with no heading/separator between them (e.g. message templates) still needs a
   seam once labels wrap to 2-3 lines, or consecutive items read as one paragraph. */
.menu-item + .menu-item {
  border-top: 1px solid var(--color-divider);
}

.menu.menu-wide {
  min-width: 320px;
}

.menu-item:hover,
.menu-item:focus-visible {
  background: var(--color-surface);
  outline: none;
}

.menu-item[aria-disabled="true"] {
  color: var(--color-faint);
  cursor: not-allowed;
}

.menu-item .hint {
  margin-left: auto;
  font-size: 11px;
  font-weight: 600;
  color: var(--color-muted);
}

.menu-item.danger {
  color: var(--status-critical);
}

.menu-sep {
  height: 1px;
  margin: 4px 0;
  background: var(--color-divider);
}

.menu-label {
  padding: 8px 14px 4px;
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--color-muted);
}

.menu-check {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 32px;
  padding: 0 14px;
  font-size: 14px;
  cursor: pointer;
}

.menu-check:hover {
  background: var(--color-surface);
}

/* ── 07 forms ────────────────────────────────────────────────────────────── */

.form {
  max-width: 720px;
}

.form-section {
  border-top: 1px solid var(--color-divider-strong);
  padding: var(--space-6) 0;
}

.form-section > h2 {
  font-size: 16px;
  margin: 0 0 4px;
}

.form-section > .section-help {
  font-size: 13px;
  color: var(--color-muted);
  margin: 0 0 var(--space-4);
}

.form-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-4) var(--space-6);
}

.form-grid .span-2 {
  grid-column: 1 / -1;
}

@media (max-width: 640px) {
  .form-grid {
    grid-template-columns: 1fr;
  }
}

.field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.field-label {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-size: 13px;
  font-weight: 700;
}

/* Required is the default for most forms; mark whichever is the MINORITY.
   Both markers are words, not just symbols. */
.req,
.opt {
  font-size: 11px;
  font-weight: 600;
  color: var(--color-muted);
  letter-spacing: 0.02em;
}

.req {
  color: var(--status-critical);
}

.field-hint {
  font-size: 12px;
  color: var(--color-muted);
}

.field-error {
  display: flex;
  gap: 6px;
  font-size: 12px;
  font-weight: 600;
  color: var(--status-critical);
}

.field-error::before {
  content: "!";
  display: inline-grid;
  place-items: center;
  width: 14px;
  height: 14px;
  flex: none;
  margin-top: 1px;
  background: var(--status-critical);
  color: var(--color-on-status);
  font-size: 10px;
  font-weight: 800;
}

.field-error[hidden] {
  display: none;
}

.input,
.select,
.textarea {
  width: 100%;
  min-height: var(--control-h);
  padding: 0 var(--control-pad-x);
  background: var(--control-bg);
  border: 1px solid var(--control-border);
  border-radius: var(--radius);
  font-size: 14px;
  transition: border-color 0.15s var(--ease-out), box-shadow 0.15s var(--ease-out);
}

.textarea {
  padding: 8px var(--control-pad-x);
  min-height: 88px;
  resize: vertical;
  line-height: 1.5;
}

.select {
  appearance: none;
  padding-right: 32px;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 17px) 50%, calc(100% - 12px) 50%;
  background-size: 5px 5px;
  background-repeat: no-repeat;
}

.input:hover,
.select:hover,
.textarea:hover {
  border-color: var(--color-text);
}

.input:focus-visible,
.select:focus-visible,
.textarea:focus-visible {
  outline: none;
  border-color: var(--color-accent);
  box-shadow: 0 0 0 1px var(--color-accent);
}

.input-sm {
  min-height: var(--control-h-sm);
  font-size: 13px;
}

.field.is-invalid .input,
.field.is-invalid .select,
.field.is-invalid .textarea,
.input[aria-invalid="true"] {
  border-color: var(--status-critical);
  box-shadow: 0 0 0 1px var(--status-critical);
}

/* Immutable / system-generated: not an input at all — plain text with a label saying why. */
.field-static {
  min-height: var(--control-h);
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  border-bottom: 1px dashed var(--color-divider);
}

.field-static .tag {
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--color-muted);
  border: 1px solid var(--color-divider);
  padding: 1px 5px;
}

.input:disabled,
.select:disabled,
.textarea:disabled {
  background: var(--color-surface);
  color: var(--color-muted);
  cursor: not-allowed;
}

.input-affix {
  display: flex;
  align-items: stretch;
}

.input-affix > .affix {
  display: flex;
  align-items: center;
  padding: 0 10px;
  font-size: 13px;
  color: var(--color-muted);
  border: 1px solid var(--control-border);
  background: var(--color-surface);
}

.input-affix > .affix:first-child {
  border-right: 0;
}

.input-affix > .affix:last-child {
  border-left: 0;
}

.choice {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 14px;
  cursor: pointer;
  min-height: var(--hit-min);
}

.choice input {
  width: 16px;
  height: 16px;
  margin: 3px 0 0;
  accent-color: var(--color-accent);
  flex: none;
}

.choice-desc {
  display: block;
  font-size: 12px;
  color: var(--color-muted);
}

fieldset.field {
  border: 0;
  padding: 0;
  margin: 0;
}

fieldset.field > legend {
  padding: 0;
  margin-bottom: 6px;
}

.switch {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: 14px;
  cursor: pointer;
}

.switch input {
  appearance: none;
  width: 34px;
  height: 18px;
  margin: 0;
  border: 1px solid var(--control-border);
  background: var(--color-surface);
  position: relative;
  cursor: pointer;
  transition: background 0.15s var(--ease-out);
}

.switch input::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 12px;
  height: 12px;
  background: var(--color-text);
  transition: transform 0.15s var(--ease-out);
}

.switch input:checked {
  background: var(--color-accent);
  border-color: var(--color-accent);
}

.switch input:checked::after {
  background: var(--color-on-accent);
  transform: translateX(16px);
}

/* Error summary at the top of a form after a failed submit: links to each field. */
.error-summary {
  border-left: 3px solid var(--status-critical);
  background: var(--status-critical-tint);
  padding: 14px 18px;
  margin-bottom: var(--space-6);
}

.error-summary h2 {
  font-size: 14px;
  margin: 0 0 6px;
  color: var(--status-critical);
}

.error-summary ul {
  margin: 0;
  padding-left: 18px;
  font-size: 13px;
}

.error-summary a {
  color: var(--status-critical);
  text-decoration: underline;
}

/* Sticky action bar: save/cancel always reachable on long forms. */
.form-actions {
  position: sticky;
  bottom: 0;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 14px 0;
  border-top: 1px solid var(--color-divider-strong);
  background: var(--color-bg);
  z-index: var(--z-sticky);
}

.form-actions .status-text {
  font-size: 12px;
  color: var(--color-muted);
}

details.disclose > summary {
  cursor: pointer;
  font-size: 13px;
  font-weight: 700;
  color: var(--color-accent-700);
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: var(--hit-min);
}

details.disclose > summary::-webkit-details-marker {
  display: none;
}

details.disclose > summary::before {
  content: "+";
  width: 14px;
  font-weight: 800;
}

details.disclose[open] > summary::before {
  content: "−";
}

/* ── 08 search ───────────────────────────────────────────────────────────── */
/* Placeholder states SCOPE ("Search plate, IMEI, driver"), never just "Search". */

.search {
  position: relative;
  display: flex;
  align-items: center;
  min-width: 220px;
  flex: 1 1 280px;
  max-width: 420px;
}

.search .icon {
  position: absolute;
  left: 11px;
  color: var(--color-muted);
  pointer-events: none;
}

.search .input {
  padding-left: 34px;
  padding-right: 34px;
}

.search-clear {
  position: absolute;
  right: 4px;
}

.search[aria-busy="true"]::after {
  content: "";
  position: absolute;
  left: 1px;
  right: 1px;
  bottom: 1px;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--color-accent), transparent);
  background-size: 50% 100%;
  background-repeat: no-repeat;
  animation: bar-slide 1s linear infinite;
}

@keyframes bar-slide {
  from {
    background-position: -50% 0;
  }
  to {
    background-position: 150% 0;
  }
}

.search-mode {
  font-size: 11px;
  color: var(--color-muted);
}

mark.hit {
  background: color-mix(in srgb, var(--color-accent) 18%, transparent);
  color: inherit;
  padding: 0 1px;
}

/* ── 09 query bar · filters · chips · saved views ────────────────────────── */
/* Row 1: view selector · search · common filters · "More filters" · column/density.
   Row 2 (only when something is active): chips + "Clear all". */

.querybar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  padding: 12px 0;
  border-top: 1px solid var(--color-divider-strong);
}

.filter-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: var(--control-h);
  padding: 0 12px;
  background: var(--control-bg);
  border: 1px solid var(--control-border);
  border-radius: var(--radius);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}

.filter-btn:hover {
  border-color: var(--color-text);
}

.filter-btn[aria-expanded="true"] {
  border-color: var(--color-accent);
  box-shadow: 0 0 0 1px var(--color-accent);
}

.filter-btn .val {
  color: var(--color-accent-700);
  font-weight: 700;
}

.filter-btn .badge {
  min-width: 18px;
  padding: 0 5px;
  background: var(--color-accent);
  color: var(--color-on-accent);
  font-size: 11px;
  font-weight: 700;
  line-height: 18px;
  text-align: center;
}

.chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  padding: 0 0 12px;
}

.chips-label {
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--color-muted);
  margin-right: 4px;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 28px;
  padding: 0 4px 0 10px;
  background: var(--color-accent-100);
  border: 1px solid color-mix(in srgb, var(--color-accent) 35%, transparent);
  font-size: 12px;
  font-weight: 600;
  color: var(--color-accent-700);
}

.chip .k {
  font-weight: 500;
  color: var(--color-text);
}

.chip button {
  display: inline-grid;
  place-items: center;
  width: 22px;
  height: 22px;
  padding: 0;
  background: none;
  border: 0;
  color: inherit;
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
}

.chip button:hover {
  background: color-mix(in srgb, var(--color-accent) 18%, transparent);
}

.chip.readonly {
  padding-right: 10px;
  background: var(--color-surface);
  border-color: var(--color-divider);
  color: var(--color-text);
}

.link-btn {
  background: none;
  border: 0;
  padding: 4px 6px;
  font-size: 12px;
  font-weight: 700;
  color: var(--color-accent-700);
  cursor: pointer;
  min-height: var(--hit-min);
}

.link-btn:hover {
  text-decoration: underline;
}

/* Filter popover body */
.filter-pop {
  padding: 12px 14px;
  min-width: 260px;
}

.filter-pop .field + .field {
  margin-top: 12px;
}

.filter-pop-foot {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--color-divider);
}

.view-select {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  font-weight: 700;
}

.view-select .modified {
  font-size: 11px;
  font-weight: 600;
  color: var(--status-warning);
}

/* ── 10 data table ───────────────────────────────────────────────────────── */
/* <section class="dt"> toolbar(querybar) · chips · dt-meta · dt-bulk · dt-scroll>table · pager */

.dt {
  position: relative;
  min-width: 0;
}

.dt-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 16px;
  padding: 0 0 10px;
  font-size: 13px;
  color: var(--color-muted);
}

.dt-meta strong {
  color: var(--color-text);
  font-variant-numeric: tabular-nums;
}

.dt-scroll {
  position: relative;
  overflow: auto;
  max-width: 100%;
  border-top: 1px solid var(--color-divider-strong);
  border-bottom: 1px solid var(--color-divider-strong);
}

.dt-scroll.fixed-h {
  max-height: 70vh;
}

.dt-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: 14px;
}

.dt-table th,
.dt-table td {
  padding: 0 12px;
  height: var(--row-h);
  text-align: left;
  vertical-align: middle;
  border-bottom: 1px solid var(--color-divider);
  white-space: nowrap;
  background: var(--color-bg);
}

.dt.compact .dt-table th,
.dt.compact .dt-table td {
  height: var(--row-h-compact);
  font-size: 13px;
}

.dt-table td.wrap {
  white-space: normal;
  min-width: 220px;
}

.dt-table thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  height: 38px;
  font-size: 11px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--color-muted);
  border-bottom: 1px solid var(--color-divider-strong);
}

.dt-table th.num,
.dt-table td.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.dt-table tbody tr:hover td {
  background: var(--color-surface);
}

.dt-table tbody tr[aria-selected="true"] td {
  background: var(--color-accent-100);
}

.dt-table tbody tr.is-clickable {
  cursor: pointer;
}

.dt-table td.null {
  color: var(--color-muted);
}

/* Sticky identity column (and the selection column before it). */
.dt-table .sticky-1 {
  position: sticky;
  left: 0;
  z-index: 1;
}

.dt-table .sticky-2 {
  position: sticky;
  left: 44px;
  z-index: 1;
  box-shadow: 1px 0 0 var(--color-divider-strong);
}

.dt-table thead .sticky-1,
.dt-table thead .sticky-2 {
  z-index: 3;
}

.dt-table .col-select {
  width: 44px;
  min-width: 44px;
  padding: 0 14px;
}

.dt-table .col-select input {
  width: 16px;
  height: 16px;
  margin: 0;
  accent-color: var(--color-accent);
  cursor: pointer;
}

.dt-table .col-actions {
  width: 1%;
  text-align: right;
  padding-right: 6px;
}

/* Sort header: the whole header label is a button. aria-sort goes on the <th>. */
.sort-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 100%;
  padding: 0;
  background: none;
  border: 0;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  color: inherit;
  cursor: pointer;
}

th.num .sort-btn {
  flex-direction: row-reverse;
}

.sort-btn:hover {
  color: var(--color-text);
}

.sort-ind {
  display: inline-flex;
  flex-direction: column;
  gap: 2px;
  width: 8px;
}

.sort-ind::before,
.sort-ind::after {
  content: "";
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  opacity: 0.35;
}

.sort-ind::before {
  border-bottom: 4px solid currentColor;
}

.sort-ind::after {
  border-top: 4px solid currentColor;
}

th[aria-sort="ascending"],
th[aria-sort="descending"] {
  color: var(--color-accent-700);
}

th[aria-sort="ascending"] .sort-ind::before,
th[aria-sort="descending"] .sort-ind::after {
  opacity: 1;
}

th[aria-sort="ascending"] .sort-ind::after,
th[aria-sort="descending"] .sort-ind::before {
  opacity: 0.15;
}

.sort-prio {
  min-width: 14px;
  height: 14px;
  padding: 0 3px;
  background: var(--color-accent-700);
  color: var(--color-on-accent);
  font-size: 9px;
  line-height: 14px;
  text-align: center;
  letter-spacing: 0;
}

.th-tip {
  margin-left: 4px;
}

/* Column resize handle (only on columns that opt in). */
.col-resize {
  position: absolute;
  right: -3px;
  top: 0;
  bottom: 0;
  width: 6px;
  cursor: col-resize;
}

.col-resize:hover {
  background: var(--color-accent);
}

/* Refreshing: keep the current rows, dim them, show a 2px bar at the top. */
.dt.is-refreshing .dt-table tbody {
  opacity: 0.5;
  transition: opacity 0.15s var(--ease-out) 0.15s;
}

.dt-progress {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 2px;
  overflow: hidden;
  z-index: 4;
  pointer-events: none;
}

.dt.is-refreshing .dt-progress::after,
.progress-indeterminate::after {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 30%;
  background: var(--color-accent);
  animation: sweep 1.1s var(--ease-out) infinite;
}

/* State row: empty / no-match / error / no-permission INSIDE the table frame,
   so headers (and the user's query) stay visible. */
.dt-state td {
  height: auto;
  padding: 0;
  white-space: normal;
}

.dt-state:hover td {
  background: var(--color-bg) !important;
}

/* Bulk action bar: replaces the meta row while a selection exists. */
.dt-bulk {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-4);
  min-height: 44px;
  padding: 6px 12px;
  margin-bottom: 10px;
  background: var(--color-text);
  color: var(--color-bg);
  font-size: 13px;
}

.dt-bulk[hidden] {
  display: none;
}

.dt-bulk strong {
  font-variant-numeric: tabular-nums;
}

.dt-bulk .btn-secondary {
  color: var(--color-bg);
  border-color: color-mix(in srgb, var(--color-bg) 60%, transparent);
}

.dt-bulk .btn-secondary:hover {
  background: var(--color-bg);
  color: var(--color-text);
}

.dt-bulk .link-btn {
  color: var(--color-accent-100);
}

/* Partial data: some rows/columns failed or were truncated. Sits above the table. */
.dt-partial {
  margin-bottom: 10px;
}

/* ── 11 pagination ───────────────────────────────────────────────────────── */

.pager {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-4);
  padding: 12px 0;
  font-size: 13px;
}

.pager-range {
  color: var(--color-muted);
  font-variant-numeric: tabular-nums;
}

.pager-range strong {
  color: var(--color-text);
}

.pager-size {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--color-muted);
}

.pager-size .select {
  width: auto;
  min-height: var(--control-h-sm);
  font-size: 13px;
}

.pager-nav {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  margin-left: auto;
}

.pager-nav .btn {
  min-width: var(--control-h-sm);
}

.pager-nav .btn[aria-current="page"] {
  background: var(--color-text);
  color: var(--color-bg);
  border-color: var(--color-text);
}

.pager-gap {
  padding: 0 4px;
  color: var(--color-muted);
}

.pager-jump {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--color-muted);
}

.pager-jump .input {
  width: 64px;
  min-height: var(--control-h-sm);
}

/* ── 12 KPIs — explicit hierarchy ────────────────────────────────────────── */
/* ONE .kpi-primary per page · 2–4 .kpi-secondary · .kpi-diagnostic strip ·
   supporting metrics go in an .attrs list, not a tile. */

.kpis {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 2fr);
  gap: var(--space-8);
  padding: var(--space-6) 0;
  border-top: 1px solid var(--color-divider-strong);
}

@media (max-width: 900px) {
  .kpis {
    grid-template-columns: 1fr;
    gap: var(--space-6);
  }
}

.kpi-secondary-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--space-6);
  align-content: start;
}

.kpi {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.kpi-label {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--color-muted);
}

.kpi-value {
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--color-text);
}

.kpi-unit {
  font-size: 0.45em;
  font-weight: 600;
  letter-spacing: 0;
  color: var(--color-muted);
  margin-left: 4px;
}

.kpi-scope {
  font-size: 12px;
  color: var(--color-muted);
}

.kpi-primary .kpi-value {
  font-size: var(--fs-numeral);
}

.kpi-primary {
  border-left: 2px solid var(--color-accent);
  padding-left: var(--space-4);
}

.kpi-secondary .kpi-value {
  font-size: 26px;
}

.kpi-secondary {
  border-top: 1px solid var(--color-divider);
  padding-top: 12px;
}

/* Delta: arrow + signed number + comparison words. Colour follows "is this good?",
   not "is it up?". Direction and goodness are separate classes. */
.delta {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 13px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.delta::before {
  font-size: 10px;
}

.delta.up::before {
  content: "▲";
}

.delta.down::before {
  content: "▼";
}

.delta.flat::before {
  content: "■";
  font-size: 8px;
}

.delta.good {
  color: var(--status-good);
}

.delta.bad {
  color: var(--status-critical);
}

.delta.neutral {
  color: var(--color-ink-secondary);
}

.delta-vs {
  font-size: 12px;
  font-weight: 500;
  color: var(--color-muted);
}

.kpi-drill {
  font-size: 12px;
  font-weight: 700;
  color: var(--color-accent-700);
  margin-top: 4px;
}

.kpi-drill:hover {
  text-decoration: underline;
}

/* Diagnostic strip: the numbers that explain movement in the primary KPI. */
.kpi-diagnostic {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 24px;
  padding: 10px 0 0;
  margin-top: var(--space-4);
  border-top: 1px dashed var(--color-divider);
  font-size: 13px;
}

.kpi-diagnostic .d-label {
  color: var(--color-muted);
}

.kpi-diagnostic .d-value {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.kpi.is-loading .kpi-value {
  color: transparent;
  background: var(--color-surface);
  width: 5ch;
}

/* ── 13 charts ───────────────────────────────────────────────────────────── */
/* <figure class="viz"> head(title = the question's subject; scope = population · period · unit)
   · legend · plot · foot(caveats + <details> methodology + table-view toggle) */

.viz {
  margin: 0;
  padding: var(--space-4) 0 var(--space-6);
  border-top: 1px solid var(--color-divider-strong);
  min-width: 0;
}

.viz-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 6px var(--space-4);
  margin-bottom: 12px;
}

.viz-title {
  font-size: 16px;
  letter-spacing: -0.01em;
  margin: 0;
}

.viz-scope {
  font-size: 12px;
  color: var(--color-muted);
  margin-top: 4px;
}

.viz-head-text {
  flex: 1 1 280px;
}

.viz-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  font-size: 12px;
  margin-bottom: 8px;
  padding: 0;
  list-style: none;
}

.viz-legend li {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.viz-legend button {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: none;
  border: 0;
  padding: 2px 0;
  font-size: 12px;
  cursor: pointer;
  min-height: var(--hit-min);
}

.viz-legend button[aria-pressed="false"] {
  opacity: 0.4;
}

.viz-swatch {
  width: 10px;
  height: 10px;
  flex: none;
}

.viz-swatch.line {
  height: 2px;
  width: 14px;
}

.viz-plot {
  position: relative;
  width: 100%;
}

.viz-plot svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

.viz-plot .grid line {
  stroke: var(--viz-grid);
  shape-rendering: crispEdges;
}

.viz-plot .axis text {
  font-size: 11px;
  fill: var(--color-ink-secondary);
  font-variant-numeric: tabular-nums;
}

.viz-plot .baseline {
  stroke: var(--viz-axis);
  shape-rendering: crispEdges;
}

.viz-plot .crosshair {
  stroke: var(--color-text);
  stroke-width: 1;
  stroke-dasharray: 2 3;
}

.viz-plot .direct-label {
  font-size: 11px;
  font-weight: 700;
  fill: var(--color-text);
}

.viz-tooltip {
  position: absolute;
  z-index: var(--z-tooltip);
  pointer-events: none;
  min-width: 140px;
  max-width: 260px;
  padding: 8px 10px;
  background: var(--color-text);
  color: var(--color-bg);
  font-size: 12px;
  line-height: 1.4;
  box-shadow: var(--shadow-overlay);
}

.viz-tooltip[hidden] {
  display: none;
}

.viz-tooltip .tt-head {
  font-weight: 700;
  margin-bottom: 4px;
}

.viz-tooltip .tt-row {
  display: flex;
  align-items: center;
  gap: 6px;
}

.viz-tooltip .tt-row .v {
  margin-left: auto;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.viz-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 8px var(--space-6);
  margin-top: 10px;
  font-size: 12px;
  color: var(--color-muted);
}

.viz-foot .caveat::before {
  content: "Note · ";
  font-weight: 700;
}

.viz-method {
  flex-basis: 100%;
}

.viz-method > div {
  margin-top: 6px;
  padding-left: 20px;
  max-width: 70ch;
  color: var(--color-text);
  font-size: 13px;
}

.viz-table {
  margin-top: 10px;
}

.viz-table[hidden] {
  display: none;
}

.viz-state {
  display: grid;
  place-items: center;
  min-height: 220px;
  background: repeating-linear-gradient(0deg, transparent 0 43px, var(--viz-grid) 43px 44px);
  text-align: center;
}

.viz-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr));
  gap: 0 var(--space-8);
}

.meter {
  display: block;
  width: 100%;
  height: 6px;
  background: var(--color-surface);
  position: relative;
  overflow: hidden;
}

.meter > span {
  position: absolute;
  inset: 0 auto 0 0;
  background: var(--viz-single);
}

/* ── 14 status · freshness · tooltips ────────────────────────────────────── */
/* Status = shape + word + colour. Shapes: good ■  warning ▲  serious ◆  critical ●  neutral □ */

.status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  font-weight: 700;
  line-height: 1;
  white-space: nowrap;
  color: var(--status-neutral);
}

.status::before {
  content: "";
  width: 8px;
  height: 8px;
  flex: none;
  background: currentColor;
}

.status.good {
  color: var(--status-good);
}

.status.warning {
  color: var(--status-warning);
}

.status.warning::before {
  width: 0;
  height: 0;
  background: none;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-bottom: 9px solid currentColor;
}

.status.serious {
  color: var(--status-serious);
}

.status.serious::before {
  transform: rotate(45deg) scale(0.85);
}

.status.critical {
  color: var(--status-critical);
}

.status.critical::before {
  border-radius: 50%;
}

.status.neutral::before {
  background: none;
  border: 1.5px solid currentColor;
}

/* Filled variant for places where the status IS the content (entity header). */
.status.pill {
  padding: 5px 8px;
  background: var(--status-neutral-tint);
}

.status.pill.good {
  background: var(--status-good-tint);
}

.status.pill.warning {
  background: var(--status-warning-tint);
}

.status.pill.serious {
  background: var(--status-serious-tint);
}

.status.pill.critical {
  background: var(--status-critical-tint);
}

/* Freshness: never imply live when it isn't. */
.fresh {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  font-weight: 600;
  color: var(--color-ink-secondary);
  white-space: nowrap;
}

.fresh:empty {
  display: none;
}

.fresh::before {
  content: "";
  width: 6px;
  height: 6px;
  background: var(--color-faint);
}

.fresh.live {
  color: var(--status-good);
}

.fresh.live::before {
  background: var(--status-good);
  animation: pulse 2s var(--ease-out) infinite;
}

.fresh.delayed {
  color: var(--status-warning);
}

.fresh.delayed::before {
  background: var(--status-warning);
}

.fresh.processing::before {
  background: none;
  border: 1.5px solid currentColor;
}

.fresh.failed {
  color: var(--status-critical);
}

.fresh.failed::before {
  background: var(--status-critical);
  border-radius: 50%;
}

@keyframes pulse {
  50% {
    opacity: 0.25;
  }
}

/* Info tooltip: a focusable (i) trigger. Content via data-tip; the same text MUST
   be in aria-label (or aria-describedby) so it isn't hover-only. */
.tip {
  position: relative;
  display: inline-grid;
  place-items: center;
  width: 16px;
  height: 16px;
  border: 1.5px solid currentColor;
  border-radius: 50%;
  font-size: 10px;
  font-weight: 800;
  font-style: normal;
  line-height: 1;
  text-transform: none;
  letter-spacing: 0;
  color: var(--color-muted);
  cursor: help;
  background: none;
  padding: 0;
  flex: none;
}

.tip::before {
  content: "i";
}

.tip:hover,
.tip:focus-visible {
  color: var(--color-text);
}

.tip::after {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  z-index: var(--z-tooltip);
  width: max-content;
  max-width: min(280px, calc(100vw - 32px));
  padding: 8px 10px;
  background: var(--color-text);
  color: var(--color-bg);
  font-size: 12px;
  font-weight: 500;
  line-height: 1.45;
  text-align: left;
  white-space: normal;
  box-shadow: var(--shadow-overlay);
  /* display:none, not visibility:hidden — a hidden bubble still counts toward the page's scroll
     width, so one near the right edge gave phones a sideways scroll. */
  display: none;
  pointer-events: none;
}

.tip:hover::after,
.tip:focus-visible::after {
  display: block;
}

.tip.tip-right::after {
  left: auto;
  right: -8px;
  transform: none;
}

.tip.tip-left::after {
  left: -8px;
  transform: none;
}

.tip.tip-below::after {
  bottom: auto;
  top: calc(100% + 8px);
}

/* ── 15 tabs ─────────────────────────────────────────────────────────────── */

.tabs {
  display: flex;
  gap: var(--space-6);
  border-bottom: 1px solid var(--color-divider-strong);
  overflow-x: auto;
  scrollbar-width: none;
  margin-bottom: var(--space-6);
}

.tab {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 40px;
  padding: 0 2px;
  background: none;
  border: 0;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--color-muted);
  white-space: nowrap;
  cursor: pointer;
}

.tab:hover {
  color: var(--color-text);
}

.tab[aria-selected="true"] {
  color: var(--color-accent-700);
}

.tab[aria-selected="true"]::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 2px;
  background: var(--color-accent);
}

.tab .count {
  font-size: 11px;
  font-weight: 600;
  color: var(--color-muted);
  font-variant-numeric: tabular-nums;
}

[role="tabpanel"][hidden] {
  display: none;
}

/* ── 16 cards (use sparingly — see SYSTEM.md §17) ────────────────────────── */
/* A card is a self-contained unit you could move or link to. Never nest. */

.card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: var(--space-4);
  background: var(--color-bg);
  border: 1px solid var(--color-divider);
  border-top: 2px solid var(--color-text);
  min-width: 0;
}

a.card:hover {
  border-top-color: var(--color-accent);
  background: var(--color-surface);
}

.card-title {
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.card-body {
  font-size: 13px;
  color: var(--color-muted);
}

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: var(--space-4);
}

/* ── 17 entity head · attributes ─────────────────────────────────────────── */

.entity-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--space-4);
  align-items: end;
  padding: var(--space-4) 0 var(--space-6);
}

.entity-id {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 14px;
}

.entity-id h1 {
  font-size: clamp(1.75rem, 1.5rem + 1vw, 2.25rem);
}

.entity-sub {
  margin-top: 8px;
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
  font-size: 13px;
  color: var(--color-muted);
}

@media (max-width: 700px) {
  .entity-head {
    grid-template-columns: 1fr;
  }
}

/* Attribute list: grouped by how people reason about the entity, not by schema. */
.attrs {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 0 var(--space-6);
  margin: 0;
}

.attr {
  padding: 10px 0;
  border-top: 1px solid var(--color-divider);
  min-width: 0;
}

.attr dt {
  font-size: 11px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--color-muted);
  display: flex;
  align-items: center;
  gap: 6px;
}

.attr dd {
  margin: 4px 0 0;
  font-size: 14px;
  overflow-wrap: anywhere;
}

.attr dd.is-empty {
  color: var(--color-muted);
}

.attr.wide {
  grid-column: 1 / -1;
}

.detail-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: var(--space-8);
}

@media (max-width: 1100px) {
  .detail-layout {
    grid-template-columns: 1fr;
  }
}

.aside-block + .aside-block {
  margin-top: var(--space-6);
}

/* ── 18 history / audit ──────────────────────────────────────────────────── */

.history {
  list-style: none;
  margin: 0;
  padding: 0;
}

.history-item {
  display: grid;
  grid-template-columns: 132px minmax(0, 1fr);
  gap: 16px;
  padding: 12px 0;
  border-top: 1px solid var(--color-divider);
  font-size: 13px;
}

.history-when {
  color: var(--color-muted);
  font-variant-numeric: tabular-nums;
}

.history-when time {
  display: block;
  color: var(--color-text);
  font-weight: 600;
}

.history-who {
  font-weight: 700;
}

.history-what {
  margin-top: 4px;
}

.change {
  display: grid;
  grid-template-columns: minmax(90px, auto) minmax(0, 1fr) auto minmax(0, 1fr);
  gap: 4px 8px;
  align-items: baseline;
  margin-top: 6px;
  font-size: 13px;
}

.change .field-name {
  color: var(--color-muted);
  font-weight: 600;
}

.change .before {
  text-decoration: line-through;
  text-decoration-color: var(--color-faint);
  color: var(--color-ink-secondary);
}

.change .arrow {
  color: var(--color-muted);
}

.change .after {
  font-weight: 700;
}

.history-reason {
  margin-top: 6px;
  padding-left: 10px;
  border-left: 2px solid var(--color-divider);
  color: var(--color-ink-secondary);
}

.history-source {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--color-muted);
  margin-left: 6px;
}

@media (max-width: 640px) {
  .history-item {
    grid-template-columns: 1fr;
    gap: 4px;
  }
  .change {
    grid-template-columns: 1fr;
  }
  .change .arrow {
    display: none;
  }
}

/* ── 19 banners · toasts ─────────────────────────────────────────────────── */
/* Banner = persistent, in-flow, about THIS page/region. Toast = transient, about an
   action the user just took. Never a toast for an error the user must act on. */

.banner {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 12px 16px;
  border-left: 3px solid var(--status-neutral);
  background: var(--status-neutral-tint);
  font-size: 13px;
}

.banner-body {
  flex: 1;
  min-width: 0;
}

.banner-title {
  font-weight: 700;
  margin-bottom: 2px;
}

.banner .btn {
  flex: none;
}

.banner.info {
  border-left-color: var(--color-text);
}

.banner.good {
  border-left-color: var(--status-good);
  background: var(--status-good-tint);
}

.banner.warning {
  border-left-color: var(--status-warning);
  background: var(--status-warning-tint);
}

.banner.warning .banner-title {
  color: var(--status-warning);
}

.banner.critical {
  border-left-color: var(--status-critical);
  background: var(--status-critical-tint);
}

.banner.critical .banner-title {
  color: var(--status-critical);
}

.banner .status {
  margin-top: 3px;
}

.toast-region {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: var(--z-toast);
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: min(420px, calc(100vw - 32px));
  pointer-events: none;
}

.toast {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  background: var(--color-text);
  color: var(--color-bg);
  font-size: 13px;
  box-shadow: var(--shadow-overlay);
  pointer-events: auto;
  animation: toast-in 0.25s var(--ease-out);
}

.toast .msg {
  flex: 1;
}

.toast .action {
  background: none;
  border: 0;
  padding: 4px 6px;
  font-weight: 800;
  font-size: 13px;
  color: var(--color-accent-100);
  text-decoration: underline;
  cursor: pointer;
}

.toast .close {
  color: var(--color-bg);
}

.toast .close:hover {
  background: color-mix(in srgb, var(--color-bg) 15%, transparent);
}

.toast.good {
  border-left: 3px solid #5fc39a;
}

@keyframes toast-in {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
}

/* ── 20 dialog · drawer (native <dialog>) ────────────────────────────────── */

.dialog,
.drawer {
  padding: 0;
  border: 1px solid var(--color-divider-strong);
  background: var(--color-bg);
  color: var(--color-text);
  box-shadow: var(--shadow-overlay);
}

.dialog::backdrop,
.drawer::backdrop {
  background: var(--scrim);
}

.dialog {
  width: min(520px, calc(100vw - 32px));
  max-height: calc(100vh - 64px);
}

.dialog.wide {
  width: min(760px, calc(100vw - 32px));
}

.dialog-head {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 18px 20px 12px;
}

.dialog-head h2 {
  flex: 1;
  font-size: 18px;
  letter-spacing: -0.01em;
}

.dialog-body {
  padding: 0 20px 18px;
  font-size: 14px;
  overflow-y: auto;
}

.dialog-body > * + * {
  margin-top: 12px;
}

.dialog-foot {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 14px 20px;
  border-top: 1px solid var(--color-divider);
}

.dialog.destructive .dialog-head {
  border-top: 3px solid var(--status-critical);
}

.consequence {
  list-style: none;
  margin: 0;
  padding: 10px 14px;
  background: var(--color-surface);
  font-size: 13px;
}

.consequence li + li {
  margin-top: 4px;
}

.consequence .irreversible {
  color: var(--status-critical);
  font-weight: 700;
}

.drawer {
  margin: 0 0 0 auto;
  height: 100vh;
  max-height: 100vh;
  width: min(480px, 100vw);
  border-width: 0 0 0 1px;
  display: none;
  flex-direction: column;
}

/* Wide drawer: long edit forms (a catalogue item) that still keep the list visible behind them. */
.drawer.drawer-wide {
  width: min(720px, 100vw);
}

.drawer[open] {
  display: flex;
  animation: drawer-in 0.25s var(--ease-out);
}

.drawer .dialog-body {
  flex: 1;
}

@keyframes drawer-in {
  from {
    transform: translateX(24px);
    opacity: 0;
  }
}

/* ── 21 empty · loading states ───────────────────────────────────────────── */

.empty {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  padding: var(--space-8) var(--space-6);
  max-width: 560px;
}

.empty-kind {
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--color-muted);
}

.empty-title {
  font-size: 16px;
  font-weight: 700;
}

.empty-body {
  font-size: 13px;
  color: var(--color-ink-secondary);
}

.empty-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 4px;
}

.empty.error .empty-title {
  color: var(--status-critical);
}

.empty.error .empty-kind::before {
  content: "● ";
  color: var(--status-critical);
}

.empty.locked .empty-kind::before {
  content: "■ ";
}

.empty .error-ref {
  font-size: 11px;
  color: var(--color-muted);
}

.skeleton {
  display: block;
  height: 12px;
  background: linear-gradient(90deg, var(--color-surface) 0 40%, color-mix(in srgb, var(--color-surface) 50%, var(--color-bg)) 50%, var(--color-surface) 60% 100%);
  background-size: 300% 100%;
  animation: skel 1.4s linear infinite;
}

.skeleton.w-40 {
  width: 40%;
}

.skeleton.w-60 {
  width: 60%;
}

.skeleton.w-80 {
  width: 80%;
}

.skeleton.block {
  height: 180px;
}

@keyframes skel {
  from {
    background-position: 100% 0;
  }
  to {
    background-position: 0 0;
  }
}

.progress-indeterminate {
  position: relative;
  height: 2px;
  overflow: hidden;
  background: var(--color-divider);
}

.region-error {
  padding: var(--space-4);
  border-left: 3px solid var(--status-critical);
  background: var(--status-critical-tint);
  font-size: 13px;
}

.region-error strong {
  color: var(--status-critical);
}

/* ── 22 maps (Leaflet) ───────────────────────────────────────────────────── */
/* Brand overrides for Leaflet's chrome + vehicle markers. Markers encode status by
   SHAPE (same shapes as .status) and staleness by a hollow ring — never colour alone. */

.map-body {
  position: relative;
}

.map-canvas {
  width: 100%;
  background: var(--color-surface);
  border: 1px solid var(--color-divider-strong);
}

.map-notice {
  position: absolute;
  left: 56px; /* clear of the zoom control */
  right: 12px;
  top: 12px;
  z-index: 500;
  box-shadow: var(--shadow-overlay);
}

.map-notice[hidden] {
  display: none;
}

.map-list[hidden] {
  display: none;
}

/* No .viz-head (createMap's `headless: true`): the map fills its container from the top edge, no
   border or title space reserved above it. The canvas itself is still sized in pixels by the caller
   (createMap's `height` option, kept in sync on resize) - that number already accounts for whatever
   else shares the page, including a headless page's own .ambient-hud strip. */
.map-frame-headless {
  border-top: 0;
  padding-top: 0;
}

.map-frame .leaflet-container {
  font-family: var(--font);
  background: var(--color-surface);
}

/* Basemap recedes: greyscale + lifted, so only data marks carry colour. */
.map-frame .leaflet-tile-pane {
  filter: grayscale(1) contrast(0.85) brightness(1.06);
}

.map-frame .leaflet-bar {
  border: 1px solid var(--color-divider-strong);
  border-radius: 0;
  box-shadow: none;
}

.map-frame .leaflet-bar a {
  width: 32px;
  height: 32px;
  line-height: 30px;
  border-radius: 0 !important;
  color: var(--color-text);
  background: var(--color-bg);
  border-bottom-color: var(--color-divider);
}

.map-frame .leaflet-bar a:hover {
  background: var(--color-surface);
}

.map-frame .leaflet-control-attribution {
  font-size: 10px;
  background: color-mix(in srgb, var(--color-bg) 85%, transparent);
}

.map-frame .leaflet-tooltip {
  border-radius: 0;
  border: 0;
  background: var(--color-text);
  color: var(--color-bg);
  font-size: 12px;
  font-weight: 600;
  box-shadow: var(--shadow-overlay);
}

.map-frame .leaflet-tooltip-top::before {
  border-top-color: var(--color-text);
}

.map-frame .leaflet-tooltip.fence-label {
  background: none;
  box-shadow: none;
  color: var(--color-text);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 700;
}

.map-frame .leaflet-tooltip.fence-label::before {
  display: none;
}

/* Permanent vehicle labels — createMap({ permanentLabels: true }), for ambient displays where
   nobody hovers. Paper-on-ink inverted from the hover tooltip so they read as labels, not popups. */
.map-frame .leaflet-tooltip.veh-label {
  background: var(--color-bg);
  color: var(--color-text);
  border: 1px solid var(--color-divider-strong);
  box-shadow: none;
  padding: 2px 6px;
  font-size: 13px;
  font-weight: 700;
}

.map-frame .leaflet-tooltip.veh-label::before {
  display: none;
}

.veh-marker {
  position: relative;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  color: var(--status-neutral);
}

.veh-marker .veh-dot {
  width: 12px;
  height: 12px;
  background: currentColor;
  box-shadow: 0 0 0 2px var(--color-bg);
}

.veh-marker.good {
  color: var(--status-good);
}

.veh-marker.warning {
  color: var(--status-warning);
}

.veh-marker.warning .veh-dot {
  width: 0;
  height: 0;
  background: none;
  box-shadow: none;
  border-left: 7px solid transparent;
  border-right: 7px solid transparent;
  border-bottom: 12px solid currentColor;
  filter: drop-shadow(0 0 1px var(--color-bg)) drop-shadow(0 0 1px var(--color-bg));
}

.veh-marker.serious {
  color: var(--status-serious);
}

.veh-marker.serious .veh-dot {
  transform: rotate(45deg) scale(0.85);
}

.veh-marker.critical {
  color: var(--status-critical);
}

.veh-marker.critical .veh-dot {
  border-radius: 50%;
}

.veh-marker.neutral .veh-dot {
  background: var(--color-bg);
  box-shadow: inset 0 0 0 2px currentColor, 0 0 0 2px var(--color-bg);
}

/* Stale: last known position only. Hollow + dashed ring, dimmed. */
.veh-marker.stale {
  opacity: 0.7;
}

.veh-marker.stale::after,
.veh-legend-stale {
  content: "";
  position: absolute;
  inset: 0;
  border: 1.5px dashed currentColor;
  border-radius: 50%;
}

.veh-legend-stale {
  position: relative;
  display: inline-block;
  width: 14px;
  height: 14px;
  color: var(--color-ink-secondary);
}

.veh-marker.is-selected::before {
  content: "";
  position: absolute;
  inset: -5px;
  border: 2px solid var(--color-text);
}

.veh-heading {
  position: absolute;
  inset: -7px;
  pointer-events: none;
}

.veh-heading::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 0;
  transform: translateX(-50%);
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-bottom: 6px solid currentColor;
}

.track-swatch {
  display: inline-block;
  width: 22px;
  height: 0;
}

/* ── 23 dashboard layout ─────────────────────────────────────────────────── */
/* A dashboard is a monitoring page: "is anything wrong right now, and where do I look?"
   Fixed regions, in this order: attention strip → primary KPI block → 2-col evidence grid. */

.dash-attention {
  display: grid;
  gap: 8px;
  margin-bottom: var(--space-6);
}

.dash-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: 0 var(--space-8);
}

.dash-grid > .span-12 {
  grid-column: span 12;
}

.dash-grid > .span-8 {
  grid-column: span 8;
}

.dash-grid > .span-6 {
  grid-column: span 6;
}

.dash-grid > .span-4 {
  grid-column: span 4;
}

@media (max-width: 1100px) {
  .dash-grid > .span-8,
  .dash-grid > .span-6,
  .dash-grid > .span-4 {
    grid-column: span 12;
  }
}

.exceptions {
  list-style: none;
  margin: 0;
  padding: 0;
}

.exceptions li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 12px;
  align-items: center;
  padding: 10px 0;
  border-top: 1px solid var(--color-divider);
  font-size: 13px;
}

.exceptions .what {
  font-weight: 700;
}

.exceptions .why {
  display: block;
  font-weight: 400;
  color: var(--color-muted);
}

/* ── 24 simple table · badge · steps · file drop · accordion ─────────────── */
/* .table: a static, small, fully-present dataset (≤ ~20 rows, no query). Anything bigger or
   queryable is a DataTable. Same visual grammar as .dt-table so the two never look different. */

.table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}

.table caption {
  caption-side: top;
  text-align: left;
  font-size: 13px;
  font-weight: 700;
  padding-bottom: 8px;
}

.table th,
.table td {
  padding: 10px 12px;
  text-align: left;
  border-bottom: 1px solid var(--color-divider);
  vertical-align: top;
}

.table thead th {
  font-size: 11px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--color-muted);
  border-bottom: 1px solid var(--color-divider-strong);
  vertical-align: bottom;
}

.table tbody th {
  font-weight: 600;
}

.table .num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.table tfoot td,
.table tfoot th {
  font-weight: 700;
  border-top: 1px solid var(--color-divider-strong);
  border-bottom: 0;
}

.table.compact th,
.table.compact td {
  padding: 6px 10px;
  font-size: 13px;
}

.table .group-row th {
  padding-top: 18px;
  font-size: 11px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--color-muted);
  border-bottom: 1px solid var(--color-divider-strong);
}

.table .highlight td,
.table .highlight th {
  background: var(--color-accent-100);
}

.table-wrap {
  overflow-x: auto;
}

.badge {
  display: inline-grid;
  place-items: center;
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  font-size: 11px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  background: var(--color-text);
  color: var(--color-bg);
}

.badge.accent {
  background: var(--color-accent);
  color: var(--color-on-accent);
}

.badge.quiet {
  background: var(--color-surface);
  color: var(--color-text);
}

.badge.critical {
  background: var(--status-critical);
  color: var(--color-on-status);
}

.tag {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 7px;
  border: 1px solid var(--color-divider);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.02em;
}

/* Steps: for multi-step flows (import, onboarding). Current = accent; done = check; future = muted. */
.steps {
  display: flex;
  gap: 0;
  list-style: none;
  margin: 0 0 var(--space-6);
  padding: 0;
  counter-reset: step;
  border-top: 1px solid var(--color-divider-strong);
}

.steps li {
  flex: 1;
  padding: 12px 12px 0 0;
  font-size: 13px;
  font-weight: 700;
  color: var(--color-muted);
  counter-increment: step;
  border-top: 2px solid transparent;
  margin-top: -1px;
}

.steps li::before {
  content: counter(step, decimal-leading-zero);
  display: block;
  font-size: 11px;
  letter-spacing: 0.1em;
  margin-bottom: 2px;
}

.steps li[aria-current="step"] {
  color: var(--color-accent-700);
  border-top-color: var(--color-accent);
}

.steps li.done {
  color: var(--color-text);
  border-top-color: var(--color-text);
}

.steps li.done::before {
  content: "✓ " counter(step, decimal-leading-zero);
}

/* File drop: a labelled input; drag-over state; per-file progress / error rows. */
.file-drop {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  padding: 20px;
  border: 1px dashed var(--control-border);
  background: var(--control-bg);
  font-size: 13px;
  cursor: pointer;
}

.file-drop.is-over {
  border-color: var(--color-accent);
  background: var(--color-accent-100);
}

.file-drop input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
}

.file-drop:focus-within {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.file-list {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
  font-size: 13px;
}

.file-list li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 4px 12px;
  padding: 8px 0;
  border-top: 1px solid var(--color-divider);
}

.file-list .meter {
  grid-column: 1 / -1;
  height: 3px;
}

/* Accordion = a stack of details.disclose with rules between. */
.accordion > details {
  border-top: 1px solid var(--color-divider);
  padding: 10px 0;
}

.accordion > details:last-child {
  border-bottom: 1px solid var(--color-divider);
}

.accordion > details > div {
  padding: 8px 0 4px 20px;
  font-size: 14px;
  color: var(--color-ink-secondary);
  max-width: 70ch;
}

/* Metric card (for card grids of saved views / reports — still not a KPI tile). */
.card .card-metric {
  font-size: 26px;
  font-weight: 700;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

.card-actions {
  display: flex;
  gap: 6px;
  margin-top: auto;
  padding-top: 8px;
}

.card.is-empty {
  border-style: dashed;
  border-top: 2px dashed var(--color-divider-strong);
  background: transparent;
  align-items: flex-start;
  justify-content: center;
}

/* ==========================================================================
   Auth gate — the one pre-shell page. Every other page type in this system
   assumes AppShell (.shell) is already on screen; this is what the user
   sees before that's true. Deliberately NOT a `.card` (§Card's own contract:
   "Not: grouping fields") - a dedicated pair of classes instead, same shape
   as gps's own already-shipped, already-verified implementation
   (auth.js/styles.css) - this section documents that pattern as canonical
   rather than leaving it as one product's private one-off. Full-viewport,
   opaque (--color-bg, not --scrim) - this fully replaces the app while
   unauthenticated, it doesn't dim a visible app behind it the way a dialog
   does. ========================================================================== */

.auth-overlay {
  position: fixed;
  inset: 0;
  z-index: var(--z-dialog);
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-bg);
}

.auth-overlay[hidden] {
  display: none;
}

.auth-card {
  width: min(340px, 90vw);
  padding: var(--space-6) var(--space-6);
  background: var(--color-surface);
  border: 1px solid var(--color-divider-strong);
  border-radius: var(--radius);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.auth-card .logo {
  /* The card is a flex column: without these the image stretches to the card's width at 28px tall. */
  height: 28px;
  width: auto;
  max-width: 100%;
  align-self: flex-start;
  object-fit: contain;
  margin-bottom: var(--space-2);
}

.auth-card h1 {
  font-size: 20px;
  margin: 0;
}

.auth-sub {
  margin: 0 0 var(--space-2);
  font-size: 13px;
  color: var(--color-muted);
}

/* ── 25 ambient display ──────────────────────────────────────────────────── */
/* A screen nobody touches, read from a few metres away (SYSTEM.md §2 "Ambient display"). No
   AppShell: nothing to navigate to. Everything is sized for distance; the page fills the viewport
   and never scrolls. Components inside are the normal ones — only their scale changes here. */

.ambient {
  height: 100vh;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-6) var(--space-8);
  overflow: hidden;
}

.ambient-head {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding-bottom: var(--space-4);
  border-bottom: 1px solid var(--color-divider-strong);
}

.ambient-head img {
  height: 34px;
}

.ambient-head h1 {
  flex: 1;
  font-size: 26px;
}

.ambient-head .fresh {
  font-size: 16px;
}

.ambient-fill {
  flex: 1;
  min-height: 0;
}

/* The header already carries the rule; the first region under it doesn't repeat it. */
.ambient-head + .viz,
.ambient-head + .kpis {
  border-top: 0;
  padding-top: 0;
}

.ambient-grid {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-8);
}

.ambient-grid-3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.ambient-grid > * {
  min-height: 0;
  overflow: hidden;
}

.ambient .kpi-label {
  font-size: 15px;
}

.ambient .kpi-primary .kpi-value {
  font-size: clamp(5rem, 3rem + 5vw, 9rem);
}

.ambient .kpi-secondary .kpi-value {
  font-size: 56px;
}

.ambient .kpi-scope {
  font-size: 15px;
}

.ambient .viz-title {
  font-size: 22px;
}

.ambient .exceptions li {
  padding: 14px 0;
  font-size: 20px;
}

.ambient .exceptions .status {
  font-size: 16px;
}

.ambient .exceptions .why {
  font-size: 15px;
}

.ambient .map-frame .leaflet-tooltip.veh-label {
  font-size: 16px;
}

/* Shown when the session behind an unattended screen expires: the last data stays up, marked stale. */
.ambient-notice {
  position: fixed;
  right: var(--space-6);
  bottom: var(--space-6);
  z-index: var(--z-toast);
  max-width: 420px;
  box-shadow: var(--shadow-overlay);
}

/* A legal or generated document shown as written (a Drive-to-own contract): the exact text a person
   signs, so line breaks are kept and nothing is reflowed or styled. Reads as a page, not as code. */
.contract-body {
  margin: var(--space-3) 0 0;
  padding: var(--space-4) var(--space-6);
  max-width: 80ch;
  white-space: pre-wrap;
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.6;
  color: var(--color-text);
  background: var(--color-surface);
  border: 1px solid var(--color-divider-strong);
  border-radius: var(--radius);
}

/* Field tool: a page used standing up, on a phone, by an agent collecting cash (Drive to own's Field
   cash). One column, big targets, the one number that matters (the receipt) set large. */
.field-cash {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  max-width: 560px;
}

.field-cash-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-4);
  border: 1px solid var(--color-divider-strong);
  border-radius: var(--radius);
  background: var(--color-surface);
}

.field-cash-card + .field-cash-card {
  margin-top: var(--space-3);
}

.field-cash-who {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2) var(--space-3);
  font-size: 16px;
}

.field-cash .input {
  min-height: 48px;
  font-size: 18px;
}

.field-cash-card .btn {
  align-self: stretch;
  justify-content: center;
}

.field-cash-receipt {
  margin: 0;
  font-size: 28px;
  font-weight: 700;
  letter-spacing: 0.04em;
}

/* ── ambient display, headerless variant ─────────────────────────────────── */
/* No .ambient-head: the first region fills from the very top edge, no divider floating above it. */
.ambient > .kpis:first-child,
.ambient > .viz:first-child,
.ambient > .ambient-split:first-child,
.ambient > .ambient-grid:first-child {
  border-top: 0;
  padding-top: 0;
}

/* A slim strip of pills, in normal flow - not .ambient-head (no logo, no title, a fraction of the
   height: ~40px vs. a header's 90px+). Replaces its freshness readout on a headerless ambient page.
   Deliberately in-flow, not overlaid on the map: an overlay would sit above Leaflet's own GPU-composited
   tile/pane layers, which don't reliably stack under a plain sibling element in every renderer. */
.ambient-hud {
  flex: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  padding-bottom: var(--space-2);
}

.ambient-hud .pill {
  padding: 6px 14px;
  border-radius: 999px;
  background: var(--color-bg);
  border: 1px solid var(--color-divider-strong);
  box-shadow: var(--shadow-overlay);
  font-size: 15px;
  font-weight: 700;
  white-space: nowrap;
}

.ambient-hud .pill .n {
  font-variant-numeric: tabular-nums;
  margin-right: 4px;
}

.ambient-hud .pill.fresh {
  font-weight: 600;
  font-size: 13px;
  color: var(--color-muted);
}

/* Map (or any single filling region) beside a live, scrollable list - the wall map's driver sidebar.
   Fills the viewport; the list is where a tap turns into a call or a message. */
.ambient-split {
  flex: 1;
  min-height: 0;
  display: flex;
  gap: var(--space-4);
}

.ambient-split > .ambient-fill {
  flex: 1;
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

/* The filling region itself (createMap's target, before or after it runs - a stable class survives
   createMap adding its own .viz/.map-frame classes alongside it). */
.ambient-fill-item {
  flex: 1;
  min-height: 0;
}

.ambient-sidebar {
  width: 360px;
  flex: none;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.ambient-sidebar-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
  padding-bottom: var(--space-2);
}

.ambient-sidebar-title {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-muted);
}

.ambient-driver-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 10px 12px;
  border: 1px solid var(--color-divider-strong);
  border-radius: var(--radius);
  background: var(--color-surface);
}

.ambient-driver-row .who {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.ambient-driver-row .vehicle {
  font-size: 16px;
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ambient-driver-row .driver {
  font-size: 13px;
  color: var(--color-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ambient-driver-row .actions {
  display: flex;
  gap: 4px;
  flex: none;
}

.ambient-driver-row .icon-btn {
  border: 1px solid var(--color-divider-strong);
  width: 36px;
  height: 36px;
}

.ambient-empty {
  padding: var(--space-4);
  text-align: center;
  color: var(--color-muted);
  font-size: 14px;
}

.ambient-selected-meta {
  padding: 0 12px;
  font-size: 13px;
  color: var(--color-muted);
}

/* A small live-pulse dot, wall pages only - the one piece of motion on an otherwise static screen,
   so "is this actually updating?" has a visible answer from across the room. */
@keyframes ambient-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}

.ambient-hud .pill.fresh.live::before {
  content: "";
  display: inline-block;
  width: 8px;
  height: 8px;
  margin-right: 6px;
  border-radius: 50%;
  background: var(--status-good, #2f7a3d);
  animation: ambient-pulse 1.8s ease-in-out infinite;
  vertical-align: middle;
}

@media (prefers-reduced-motion: reduce) {
  .ambient-hud .pill.fresh.live::before {
    animation: none;
  }
}

/* ==========================================================================
   Financing components (2026-09-30) — the simulator, the underwriter's decision panel, an asset's
   history. All token-driven, so dark mode and reduced motion come free. Contracts: SYSTEM.md §19.
   ========================================================================== */

/* ── Concept tag: marks anything mocked, illustrative or assumed. Never decorative. ─────────────── */
.concept-tag {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 1px 6px;
  border: 1px dashed var(--color-ink-secondary);
  border-radius: var(--radius);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1.5;
  color: var(--color-ink-secondary);
  white-space: nowrap;
  vertical-align: middle;
}

/* ── Workbench: inputs on the left, live results on the right (simulator, what-if pages) ─────────── */
.workbench {
  display: grid;
  grid-template-columns: minmax(280px, 380px) minmax(0, 1fr);
  gap: var(--space-8);
  align-items: start;
}
.workbench-inputs {
  position: sticky;
  top: calc(var(--shell-top-h) + var(--space-4));
  display: grid;
  gap: var(--space-4);
}
.workbench-results {
  display: grid;
  gap: var(--space-6);
  min-width: 0;
}
@media (max-width: 860px) {
  .workbench { grid-template-columns: minmax(0, 1fr); }
  .workbench-inputs { position: static; }
}

/* ── Range: a slider with its value beside the label and its bounds beneath ───────────────────────── */
.range-field { display: grid; gap: 6px; }
.range-head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-3); }
.range-out { font-weight: 700; font-variant-numeric: tabular-nums; }
.range {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: var(--control-h);
  margin: 0;
  background: transparent;
  cursor: pointer;
}
.range::-webkit-slider-runnable-track { height: 4px; background: var(--control-border); border-radius: 0; }
.range::-moz-range-track { height: 4px; background: var(--control-border); border-radius: 0; }
.range::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 20px;
  height: 20px;
  margin-top: -8px;
  background: var(--color-accent);
  border: 2px solid var(--color-bg);
  outline: 1px solid var(--color-accent);
  border-radius: 50%;
}
.range::-moz-range-thumb {
  width: 16px;
  height: 16px;
  background: var(--color-accent);
  border: 2px solid var(--color-bg);
  outline: 1px solid var(--color-accent);
  border-radius: 50%;
}
.range:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.range-scale { display: flex; justify-content: space-between; font-size: 12px; color: var(--color-ink-secondary); font-variant-numeric: tabular-nums; }

/* ── Timeline: a vertical history with a shape per kind (never colour alone) ─────────────────────── */
.timeline { list-style: none; margin: 0; padding: 0; position: relative; }
.timeline::before {
  content: "";
  position: absolute;
  left: 7px;
  top: 8px;
  bottom: 8px;
  width: 1px;
  background: var(--color-divider-strong);
}
.timeline-item {
  position: relative;
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr) auto;
  gap: 0 var(--space-3);
  padding: 0 0 var(--space-4);
}
.timeline-item::before {
  content: "";
  grid-row: 1 / span 2;
  width: 9px;
  height: 9px;
  margin: 5px 0 0 3px;
  background: var(--color-bg);
  border: 2px solid var(--color-text);
  position: relative;
  z-index: 1;
}
.timeline-item.good::before { background: var(--status-good); border-color: var(--status-good); }
.timeline-item.warning::before { border-color: var(--status-warning); transform: rotate(0); border-radius: 0; clip-path: polygon(50% 0, 100% 100%, 0 100%); background: var(--status-warning); }
.timeline-item.serious::before { border-color: var(--status-serious); background: var(--status-serious); transform: rotate(45deg); }
.timeline-item.critical::before { border-color: var(--status-critical); background: var(--status-critical); border-radius: 50%; }
.timeline-what { font-weight: 700; font-size: 14px; }
.timeline-detail { grid-column: 2; font-size: 13px; color: var(--color-ink-secondary); overflow-wrap: anywhere; }
.timeline-when { grid-column: 3; grid-row: 1 / span 2; font-size: 12px; color: var(--color-ink-secondary); white-space: nowrap; text-align: right; }
.timeline-when time { display: block; color: var(--color-text); font-weight: 600; }

/* ── Breakdown: one weekly amount split into its parts, bar plus a labelled legend ───────────────── */
.breakdown-bar { display: flex; height: 14px; width: 100%; background: var(--color-surface); overflow: hidden; }
.breakdown-bar > span { display: block; min-width: 2px; }
.breakdown-bar > span + span { border-left: 2px solid var(--color-bg); }
.breakdown-legend { list-style: none; margin: var(--space-3) 0 0; padding: 0; display: grid; gap: 6px; }
.breakdown-legend li { display: grid; grid-template-columns: 12px minmax(0, 1fr) auto; gap: var(--space-3); align-items: baseline; font-size: 14px; }
.breakdown-legend .swatch { width: 12px; height: 12px; }
.breakdown-legend .amount { font-weight: 700; font-variant-numeric: tabular-nums; }
.breakdown-legend .total { border-top: 1px solid var(--color-divider-strong); padding-top: 6px; font-weight: 700; }
.breakdown [data-slot="finance"], .breakdown .swatch[data-slot="finance"] { background: var(--viz-single); }
.breakdown [data-slot="insurance"], .breakdown .swatch[data-slot="insurance"] { background: var(--viz-1); }
.breakdown [data-slot="maintenance"], .breakdown .swatch[data-slot="maintenance"] { background: var(--viz-4); }
.breakdown [data-slot="road_tax"], .breakdown .swatch[data-slot="road_tax"] { background: var(--viz-7); }
.breakdown [data-slot="roadside"], .breakdown .swatch[data-slot="roadside"] { background: var(--viz-5); }

/* ── Score ring: a 0-100 score with its band, the number always printed ──────────────────────────── */
.score-ring {
  --pct: 0;
  --ring: var(--status-good);
  display: inline-grid;
  place-items: center;
  width: 84px;
  height: 84px;
  border-radius: 50%;
  background: conic-gradient(var(--ring) calc(var(--pct) * 1%), var(--color-surface) 0);
  position: relative;
  flex: none;
}
.score-ring::before { content: ""; position: absolute; inset: 8px; border-radius: 50%; background: var(--color-bg); }
.score-ring > * { position: relative; text-align: center; line-height: 1.1; }
.score-ring .score-num { display: block; font-size: 24px; font-weight: 800; font-variant-numeric: tabular-nums; }
.score-ring .score-band { display: block; font-size: 11px; font-weight: 700; letter-spacing: 0.08em; color: var(--color-ink-secondary); }
.score-ring[data-band="C"] { --ring: var(--status-warning); }
.score-ring[data-band="D"] { --ring: var(--status-serious); }

/* ── Decision panel: the recommendation first, the reasons under it, the actions last ───────────── */
.decision-panel {
  border: 1px solid var(--color-divider-strong);
  padding: var(--space-6);
  display: grid;
  gap: var(--space-6);
}
.decision-head { display: flex; gap: var(--space-6); align-items: center; flex-wrap: wrap; }
.decision-head-text { min-width: 0; flex: 1 1 260px; }
.decision-kicker { font-size: 12px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-ink-secondary); }
.decision-title { margin: 2px 0 4px; font-size: 22px; font-weight: 800; line-height: 1.2; }
.decision-summary { margin: 0; color: var(--color-ink-secondary); max-width: var(--measure); }
.decision-cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr)); gap: var(--space-6); }
.decision-col h3 { margin: 0 0 8px; font-size: 12px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-ink-secondary); }
.decision-col dl { margin: 0; display: grid; gap: 6px; }
.decision-col .row { display: flex; justify-content: space-between; gap: var(--space-3); font-size: 14px; }
.decision-col .row dt { color: var(--color-ink-secondary); }
.decision-col .row dd { margin: 0; font-weight: 700; font-variant-numeric: tabular-nums; text-align: right; }
.decision-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; font-size: 14px; }
.decision-list li { display: grid; grid-template-columns: 16px minmax(0, 1fr); gap: 6px; }
.decision-list li::before { content: "•"; color: var(--color-ink-secondary); }
.decision-list li.risk::before { content: "▲"; color: var(--status-warning); font-size: 11px; line-height: 20px; }
.decision-list li.ok::before { content: "■"; color: var(--status-good); font-size: 11px; line-height: 20px; }
.decision-actions { display: flex; gap: var(--space-3); flex-wrap: wrap; align-items: center; }

/* ── Ratio bar: where a payment sits against the income it comes from, with the cap marked ──────── */
.ratio { display: grid; gap: 6px; }
.ratio-track { position: relative; height: 10px; background: var(--color-surface); }
.ratio-fill { position: absolute; inset: 0 auto 0 0; background: var(--status-good); }
.ratio[data-status="tight"] .ratio-fill { background: var(--status-warning); }
.ratio[data-status="over"] .ratio-fill { background: var(--status-serious); }
.ratio-cap { position: absolute; top: -4px; bottom: -4px; width: 2px; background: var(--color-text); }
.ratio-labels { display: flex; justify-content: space-between; font-size: 12px; color: var(--color-ink-secondary); font-variant-numeric: tabular-nums; }

/* ── Comparison: options side by side, the recommended one marked ────────────────────────────────── */
.compare { width: 100%; border-collapse: collapse; font-size: 14px; }
.compare th, .compare td { padding: 10px 12px; text-align: right; border-bottom: 1px solid var(--color-divider); font-variant-numeric: tabular-nums; }
.compare th:first-child, .compare td:first-child { text-align: left; }
.compare thead th { font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-ink-secondary); border-bottom: 1px solid var(--color-divider-strong); }
.compare tbody th { font-weight: 600; color: var(--color-ink-secondary); }
.compare .is-total td, .compare .is-total th { font-weight: 800; color: var(--color-text); border-top: 1px solid var(--color-divider-strong); }
.compare [data-pick="true"] { background: var(--color-accent-100); }

/* ── Journey: the same steps for staff and the rider. `.steps` with a vertical variant for a phone. ─── */
.steps.steps-vertical { flex-direction: column; border-top: 0; margin-bottom: 0; }
.steps.steps-vertical li { border-top: 0; border-left: 2px solid var(--color-divider); padding: 6px 0 6px 12px; margin: 0; }
.steps.steps-vertical li[aria-current="step"] { border-left-color: var(--color-accent); }
.steps.steps-vertical li.done { border-left-color: var(--color-text); }
.steps.steps-vertical li::before { display: inline; margin-right: 8px; }

/* ── Device frame: a phone-width preview of what the rider sees, inside a staff page ─────────────── */
.device-frame {
  max-width: 400px;
  margin: 0 auto;
  border: 1px solid var(--color-divider-strong);
  background: var(--color-bg);
  padding: var(--space-4) var(--space-4) var(--space-6);
  display: grid;
  gap: var(--space-6);
}
.device-frame > header { display: flex; justify-content: space-between; align-items: center; gap: var(--space-3); border-bottom: 1px solid var(--color-divider); padding-bottom: var(--space-3); font-size: 12px; color: var(--color-ink-secondary); letter-spacing: 0.08em; text-transform: uppercase; font-weight: 700; }
.device-frame h2 { margin: 0 0 8px; font-size: 20px; font-weight: 800; line-height: 1.2; }
.device-frame h3 { margin: 0 0 6px; font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-ink-secondary); }

/* ── Goal: one thing to do, how far along, what's left ─────────────────────────────────────────── */
.goal { display: grid; gap: 6px; padding: 10px 0; border-bottom: 1px solid var(--color-divider); }
.goal:last-child { border-bottom: 0; }
.goal-head { display: flex; justify-content: space-between; gap: var(--space-3); align-items: baseline; font-size: 14px; font-weight: 700; }
.goal-head .goal-num { font-variant-numeric: tabular-nums; color: var(--color-ink-secondary); font-weight: 600; white-space: nowrap; }
.goal-note { font-size: 13px; color: var(--color-ink-secondary); }
.goal.is-done .goal-head > span:first-child::before { content: "■ "; color: var(--status-good); font-size: 11px; }

/* ── Offer: a vehicle and what it would cost each week ─────────────────────────────────────────── */
.offer { border: 1px solid var(--color-divider-strong); padding: var(--space-4); display: grid; gap: 10px; }
.offer-name { font-size: 16px; font-weight: 800; }
.offer-price { font-size: 28px; font-weight: 800; font-variant-numeric: tabular-nums; line-height: 1.1; }
.offer-price small { font-size: 13px; font-weight: 600; color: var(--color-ink-secondary); }
.offer-facts { display: grid; grid-template-columns: 1fr 1fr; gap: 6px 12px; margin: 0; font-size: 13px; }
.offer-facts dt { color: var(--color-ink-secondary); }
.offer-facts dd { margin: 0; font-weight: 700; font-variant-numeric: tabular-nums; }

/* ── Photo grid: one tile per required view, filled by a camera or file picker ─────────────────── */
.photo-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: var(--space-3); }
.photo-slot { position: relative; aspect-ratio: 4 / 3; border: 1px dashed var(--control-border); background: var(--color-surface); display: grid; place-items: center; overflow: hidden; }
.photo-slot.has { border-style: solid; }
.photo-slot img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.photo-slot .photo-label { position: absolute; left: 0; right: 0; bottom: 0; padding: 6px 8px; font-size: 12px; font-weight: 700; background: color-mix(in srgb, var(--color-bg) 88%, transparent); display: flex; justify-content: space-between; gap: 6px; }
.photo-slot .photo-pick { display: grid; place-items: center; gap: 4px; text-align: center; padding: 12px; font-size: 13px; font-weight: 700; color: var(--color-ink-secondary); cursor: pointer; width: 100%; height: 100%; }
.photo-slot input[type="file"] { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; }
.photo-slot:focus-within { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.photo-slot[aria-busy="true"]::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px; background: var(--color-accent); }

/* ── Wizard section: a step of a longer task, with its state in words ──────────────────────────── */
.wizard-step { border-top: 1px solid var(--color-divider-strong); padding: var(--space-6) 0; display: grid; gap: var(--space-4); }
.wizard-step > .btn { justify-self: start; }
.wizard-step > header { display: flex; justify-content: space-between; gap: var(--space-3); align-items: baseline; flex-wrap: wrap; }
.wizard-step h2 { margin: 0; font-size: 18px; }
.wizard-actions { position: sticky; bottom: 0; background: var(--color-bg); border-top: 1px solid var(--color-divider-strong); padding: var(--space-3) 0; display: flex; gap: var(--space-3); align-items: center; flex-wrap: wrap; z-index: var(--z-sticky); }
