/* ============================================================================
   Hit Rail Design System — foundation
   ----------------------------------------------------------------------------
   Distilled from Hit Rail Live (~/rtmde-app/styles.css) on 2026-09-08.
   HRL is the reference implementation; this file is the cleaned-up extraction:
   the real token values, with HRL's known defects fixed and its missing token
   groups filled in (spacing, z-index, motion, font sizes).

   Drop this in as the FIRST stylesheet of a new Hit Rail service, then add a
   service-specific sheet after it. Do not edit the token block per-service —
   if a value is wrong for everyone, change it here.

   What was deliberately NOT carried over from HRL (see the Vault doc):
     - 14 undefined custom properties, one of which is a live visual bug
     - a half-finished dark theme left as orphaned tokens
     - raw Tailwind hexes bolted onto ~1/3 of the admin views
     - duplicated components (12 table styles, 5 bar charts, 3 modal shells)
   ========================================================================== */

/* ---------------------------------------------------------------- 1. TOKENS */

:root {
  /* --- Brand: olive ramp (surfaces, text, chrome) --- */
  --ht-olive-900: #1f221a;
  --ht-olive-800: #2a2d24;
  --ht-olive-700: #353930;
  --ht-olive-600: #46493d;
  --ht-olive-500: #5a5e4b;
  --ht-olive-400: #767a66;
  --ht-olive-300: #9ea28e;
  --ht-olive-200: #c7cab9;
  --ht-olive-100: #e6e8dd;
  --ht-olive-50:  #f3f4ed;

  /* --- Brand: gold ramp (accent, focus, active state) ---
     --ht-gold-400 (#f7b933) is also the PWA theme-color.
     NOTE: this ramp is NOT the same as the document-brand orange #FFC000.
     See "Rozjazd z brandem dokumentowym" in the Vault doc before changing. */
  --ht-gold-600: #c88800;
  --ht-gold-500: #f5a800;
  --ht-gold-400: #f7b933;
  --ht-gold-300: #fbd27a;
  --ht-gold-200: #fce0a0;   /* added — HRL's ramp skipped this step */
  --ht-gold-100: #fdecc0;
  --ht-gold-50:  #fff7e1;

  /* --- Surfaces ---
     0 = cards/panels/chrome · 1 = app canvas + body · 2 = hover/inset fills
     3 = deepest inset (bar tracks, wells) */
  --surface-0: #ffffff;
  --surface-1: #fafaf6;
  --surface-2: #f3f3ec;
  --surface-3: #e9e9df;

  /* --- Borders: soft = internal dividers · base = control outlines
         strong = emphasis, disabled glyphs, dot outlines --- */
  --border-soft: #e4e4d8;
  --border: #d6d6c7;
  --border-strong: #b5b6a4;

  /* --- Text --- */
  --text: #1f221a;
  --text-muted: #5a5e4b;
  --text-dim: #8a8d7a;
  --text-on-dark: #d4d6c4;

  /* --- Semantic status ---
     Triad per state: --X = saturated fill/dot · --X-bg = pale badge ground
     --X-dark = accessible text on --X-bg. Always use the triad, never a raw hex. */
  --ok: #2d9d6e;   --ok-bg: #e3f4ec;   --ok-dark: #1b6e4c;
  --warn: #e89c2a; --warn-bg: #fcefd6; --warn-dark: #8a5a0a;
  --err: #d84545;  --err-bg: #fbe4e4;  --err-dark: #8f2020;
  --info: #3a7bd5; --info-bg: #e3edfa; --info-dark: #1e4f8f; /* -dark added; HRL lacked it */

  /* --- Domain: delay semantics (railway) ---
     Deliberate: cancelled is BLACK, not red — red is reserved for delay
     severity, so a cancelled train must not read as "very delayed". */
  --delay-ontime: var(--ok);     /* < 5 min  */
  --delay-late: var(--warn);     /* >= 5 min */
  --delay-verylate: var(--err);  /* > 10 min */
  --delay-cancelled: #111111;

  /* --- Typography --- */
  --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', 'Menlo', monospace;

  /* Font scale — HRL had NO size tokens and 25 ad-hoc values incl. half-pixels.
     This is the ladder its real usage collapses to. Use these, not literals. */
  --fs-micro: 9px;    /* mono micro-labels only */
  --fs-eyebrow: 10px; /* uppercase section titles */
  --fs-label: 10.5px; /* field labels, table th */
  --fs-sm: 11px;      /* small labels, badges, meta */
  --fs-base: 12px;    /* secondary body, hints */
  --fs-md: 12.5px;    /* buttons, inputs */
  --fs-lg: 13px;      /* body / default */
  --fs-title: 14px;   /* topbar, modal titles */
  --fs-view: 16px;    /* view headings */
  --fs-kpi: 26px;     /* KPI numerals */

  --fw-regular: 400;
  --fw-medium: 500;
  --fw-semibold: 600;  /* the workhorse: labels, titles, buttons */
  --fw-bold: 700;      /* uppercase eyebrows, numerals */

  --lh-tight: 1;       /* badges, KPIs — kills leading */
  --lh-base: 1.45;
  --lh-relaxed: 1.6;   /* code blocks, dense key/value rows */

  --tracking-eyebrow: 0.08em;  /* uppercase small caps */
  --tracking-caps: 0.04em;
  --tracking-display: -0.01em; /* large numerals pull in */

  /* --- Spacing (HRL had none — these are its actual rhythm) --- */
  --sp-1: 2px;
  --sp-2: 4px;
  --sp-3: 6px;
  --sp-4: 8px;
  --sp-5: 10px;
  --sp-6: 12px;
  --sp-7: 14px;
  --sp-8: 16px;
  --sp-9: 20px;
  --sp-10: 24px;

  /* --- Radii --- */
  --r-sm: 4px;
  --r-md: 6px;
  --r-lg: 10px;
  --r-xl: 14px;
  --r-pill: 999px;

  /* --- Shadows --- */
  --shadow-sm: 0 1px 2px rgba(31, 34, 26, 0.06);
  --shadow-md: 0 2px 8px rgba(31, 34, 26, 0.08), 0 1px 2px rgba(31, 34, 26, 0.05);
  --shadow-lg: 0 12px 32px rgba(31, 34, 26, 0.12), 0 2px 6px rgba(31, 34, 26, 0.06);
  --shadow-modal: 0 14px 44px rgba(31, 34, 26, 0.28);

  /* --- Motion (HRL had none; these are its de-facto values) --- */
  --dur-fast: 0.12s;
  --dur-base: 0.2s;
  --dur-slow: 0.25s;
  --ease: ease;

  /* --- Z-index ladder (HRL used 18 bare literals) --- */
  --z-base: 1;
  --z-sticky: 10;
  --z-dropdown: 200;
  --z-bottom-nav: 90;
  --z-topbar-mobile: 100;
  --z-drawer-backdrop: 149;
  --z-drawer: 150;
  --z-overlay-map: 800;
  --z-modal: 1000;
  --z-fullscreen: 2000;
  --z-gate: 9000;      /* pre-app config/auth gate */
  --z-blocking: 10000; /* must beat the gate */
  --z-boot: 10001;
  --z-toast: 11000;

  /* --- Layout --- */
  --sidebar-w: 220px;
  --sidebar-w-collapsed: 52px;
  --sidebar-w-mobile: 240px;
  --topbar-h: 52px;
  --panel-w-right: 360px;
  --bp-mobile: 767px;  /* reference only — CSS can't use vars in media queries */
  --bp-tablet: 900px;
}

/* ------------------------------------------------------------ 2. BASE RESET */

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

/* Fixed application shell: the PAGE never scrolls. Every region owns its own
   overflow. This is the single most important structural decision to copy —
   it is what makes the app feel like an app instead of a document. */
html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  overflow: hidden;
}

body {
  font-family: var(--font-sans);
  font-size: var(--fs-lg);
  line-height: var(--lh-base);
  color: var(--text);
  background: var(--surface-1);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

button { font-family: inherit; }

/* One global focus ring, brand-coloured, :focus-visible only so mouse users
   don't see it. If a component must remove the outline, it MUST substitute an
   equally visible ring (see .field__input:focus below). */
:focus-visible {
  outline: 2px solid var(--ht-gold-500);
  outline-offset: 2px;
}

[hidden], .is-hidden { display: none !important; }

/* Data legibility: every ID, UUID, timestamp, RICS/UIC code and count is mono.
   This is the strongest part of the Hit Rail visual identity — keep it. */
.mono { font-family: var(--font-mono); }
.tnum { font-variant-numeric: tabular-nums; }

/* Respect the OS setting. HRL shipped 8 keyframes incl. 3 infinite animations
   and honoured this nowhere — its clearest accessibility gap. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* --------------------------------------------------------- 3. APP SKELETON */

.app {
  display: grid;
  grid-template-columns: var(--sidebar-w) 1fr;
  height: 100vh;
  background: var(--surface-1);
  overflow: hidden;
}
.app.is-sidebar-collapsed { grid-template-columns: var(--sidebar-w-collapsed) 1fr; }

.sidebar {
  display: flex;
  flex-direction: column;
  min-width: 0;
  overflow: hidden;
  background: var(--surface-0);
  border-right: 1px solid var(--border-soft);
  transition: width var(--dur-slow) var(--ease);
}
.sidebar__brand,
.sidebar__foot { flex-shrink: 0; }
.sidebar__nav {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: var(--sp-7) var(--sp-5) var(--sp-5);
}

.main {
  display: grid;
  grid-template-rows: auto 1fr;
  min-width: 0;
  overflow: hidden;
}

.topbar {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  flex-shrink: 0;
  min-height: var(--topbar-h);
  padding: var(--sp-5) var(--sp-9);
  background: var(--surface-0);
  border-bottom: 1px solid var(--border-soft);
}
.topbar__title {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  font-size: var(--fs-title);
  font-weight: var(--fw-semibold);
}
.topbar__crumb { color: var(--text-dim); font-weight: var(--fw-regular); }
.topbar__sep { color: var(--border-strong); font-weight: 300; }
.topbar__spacer { flex: 1; }

/* ★ THE VIEW SHELL — the one abstraction HRL was missing.
   HRL repeats this head/body pair under EIGHT different block names. Use this
   single component for every full-page view instead.
   Contract: .view hides overflow, .view__body is the only scroller.
   `min-height: 0` is load-bearing — without it a flex child refuses to shrink
   below its content and overflow-y never engages, so content is silently
   clipped with no way to reach it. That exact bug shipped twice in HRL. */
.view {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
  overflow: hidden;
  background: var(--surface-1);
}
.view__head {
  flex-shrink: 0;
  padding: var(--sp-7) var(--sp-8) var(--sp-4);
  border-bottom: 1px solid var(--border-soft);
}
.view__title { font-size: var(--fs-view); font-weight: var(--fw-semibold); margin: 0; }
.view__controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-6);
}
.view__body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: var(--sp-4) var(--sp-8) var(--sp-9);
}
.view__foot {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-5) var(--sp-8);
  border-top: 1px solid var(--border-soft);
  background: var(--surface-1);
}

/* Wide content scrolls horizontally inside its own wrapper, so the vertical
   scroll stays owned by .view__body and any sticky header stays put. */
.scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* Scrollbars. -webkit- plus the standard properties, which HRL omitted —
   without them Firefox gets default chrome. */
.thin-scroll { scrollbar-width: thin; scrollbar-color: var(--border) transparent; }
.thin-scroll::-webkit-scrollbar { width: 6px; height: 6px; }
.thin-scroll::-webkit-scrollbar-track { background: transparent; }
.thin-scroll::-webkit-scrollbar-thumb { background: var(--border); border-radius: var(--r-sm); }
.thin-scroll::-webkit-scrollbar-thumb:hover { background: var(--border-strong); }

/* ------------------------------------------------------------ 4. NAVIGATION */

.nav-section-title {
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-semibold);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-dim);
  padding: var(--sp-7) var(--sp-4) var(--sp-3);
}

/* Use a <button> or an <a href>, never a bare <a onclick> — HRL's nav items
   are not keyboard-focusable and are announced as neither link nor button. */
.nav-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  width: 100%;
  padding: var(--sp-4) var(--sp-5);
  margin-bottom: var(--sp-1);
  border: 0;
  background: transparent;
  border-radius: var(--r-md);
  font-size: var(--fs-lg);
  color: var(--text-muted);
  text-align: left;
  text-decoration: none;
  cursor: pointer;
  user-select: none;
}
.nav-item:hover { background: var(--surface-2); color: var(--text); }
.nav-item.is-active { background: var(--ht-olive-100); color: var(--text); }
/* Gold left rail. Offset must match .sidebar__nav's horizontal padding. */
.nav-item.is-active::before {
  content: '';
  position: absolute;
  left: calc(var(--sp-5) * -1);
  top: var(--sp-3);
  bottom: var(--sp-3);
  width: 3px;
  background: var(--ht-gold-500);
  border-radius: 0 2px 2px 0;
}
.nav-item__icon { display: flex; color: var(--text-dim); }
.nav-item.is-active .nav-item__icon { color: var(--ht-gold-600); }
.nav-item:disabled,
.nav-item[aria-disabled='true'] { opacity: 0.5; pointer-events: none; }

/* --------------------------------------------------------------- 5. BUTTONS */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 7px 13px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface-0);
  color: var(--text);
  font-size: var(--fs-md);
  font-weight: var(--fw-medium);
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease);
}
.btn:hover { background: var(--surface-2); }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }

.btn--primary {
  background: var(--ht-gold-500);
  border-color: var(--ht-gold-600);
  color: var(--ht-olive-900);
  font-weight: var(--fw-semibold);
}
.btn--primary:hover { background: var(--ht-gold-400); }

.btn--dark {
  background: var(--ht-olive-800);
  border-color: var(--ht-olive-900);
  color: #fff;
}
.btn--dark:hover { background: var(--ht-olive-700); }

/* Present here because HRL uses .btn--ghost 7× in markup and never defined it,
   so every "Cancel" / "Back" button silently rendered as a default button. */
.btn--ghost {
  background: transparent;
  border-color: transparent;
  color: var(--text-muted);
}
.btn--ghost:hover { background: var(--surface-2); color: var(--text); }

.btn--danger {
  background: var(--err);
  border-color: var(--err);
  color: #fff;
  font-weight: var(--fw-semibold);
}
.btn--danger:hover { background: var(--err-dark); border-color: var(--err-dark); }

.btn--sm { padding: var(--sp-2) var(--sp-5); font-size: var(--fs-base); gap: var(--sp-2); }
.btn--block { width: 100%; }

.iconbtn {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 34px;
  height: 34px;
  border: 1px solid transparent;
  border-radius: var(--r-md);
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
}
.iconbtn:hover { background: var(--surface-2); color: var(--text); border-color: var(--border); }
.iconbtn.is-active {
  color: var(--ht-gold-600);
  background: var(--ht-gold-50);
  border-color: var(--ht-gold-300);
}

/* ------------------------------------------------------------ 6. FORM FIELDS */

.field { display: flex; flex-direction: column; gap: 5px; }
.field--full { grid-column: 1 / -1; }

.field__label {
  font-size: var(--fs-label);
  font-weight: var(--fw-semibold);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--text-muted);
}

/* Mono by default. Unusual, deliberate, and correct for this domain: almost
   every input in a Hit Rail service takes an ID, code, number or timestamp. */
.field__input {
  width: 100%;
  padding: var(--sp-4) var(--sp-5);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface-0);
  color: var(--text);
  font-family: var(--font-mono);
  font-size: var(--fs-md);
}
/* Removes the global outline but substitutes an equally visible gold ring. */
.field__input:focus {
  outline: none;
  border-color: var(--ht-gold-500);
  box-shadow: 0 0 0 3px rgba(245, 168, 0, 0.15);
}
.field__input:disabled,
.field__input:read-only { background: var(--surface-2); opacity: 0.7; cursor: not-allowed; }
.field__input--sm { padding: var(--sp-3) 9px; font-size: var(--fs-base); }
.field__input--sans { font-family: var(--font-sans); }

.field__hint { font-size: var(--fs-label); color: var(--text-dim); font-family: var(--font-mono); }
.field__error { font-size: var(--fs-sm); color: var(--err-dark); }

.field-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--sp-6);
}

.check-row {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  font-size: var(--fs-md);
  cursor: pointer;
}
.check-row input[type='checkbox'] { width: 14px; height: 14px; cursor: pointer; }
.check-row__hint { font-size: var(--fs-sm); color: var(--text-dim); }

/* ------------------------------------------------------- 7. CARDS AND TABS */

.card {
  background: var(--surface-0);
  border: 1px solid var(--border-soft);
  border-radius: var(--r-lg);
  overflow: hidden;
  transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
.card:hover { border-color: var(--border); box-shadow: var(--shadow-sm); }
.card.is-selected {
  border-color: var(--ht-gold-500);
  box-shadow: 0 0 0 1px var(--ht-gold-500), var(--shadow-md);
}
.card__head {
  display: flex;
  align-items: baseline;
  gap: var(--sp-4);
  padding: var(--sp-6) var(--sp-8);
  border-bottom: 1px solid var(--border-soft);
}
.card__title { font-size: var(--fs-lg); font-weight: var(--fw-semibold); margin: 0; }
.card__sub { flex: 1; font-size: var(--fs-base); color: var(--text-dim); }
.card__body { padding: var(--sp-7) var(--sp-8); }

.tabs {
  display: flex;
  flex-shrink: 0;
  gap: var(--sp-1);
  padding: var(--sp-1);
  background: var(--surface-2);
  border-radius: var(--r-md);
}
.tabs__tab {
  flex: 1;
  padding: var(--sp-3) var(--sp-5);
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--text-muted);
  font-size: var(--fs-base);
  font-weight: var(--fw-medium);
  cursor: pointer;
}
/* State is always `is-active`. HRL also used bare `.active` in two places —
   pick one convention and never mix them. */
.tabs__tab.is-active {
  background: var(--surface-0);
  color: var(--text);
  box-shadow: var(--shadow-sm);
}

.chip {
  padding: 5px var(--sp-5);
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  background: var(--surface-0);
  color: var(--text-muted);
  font-size: 11.5px;
  font-family: inherit;
  cursor: pointer;
}
.chip:hover { background: var(--surface-2); }
.chip.is-active {
  background: var(--ht-olive-700);
  border-color: var(--ht-olive-700);
  color: #fff;
}

/* ---------------------------------------------------------------- 8. TABLES */

.table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-lg);
  background: var(--surface-0);
}
.table th {
  padding: 0 var(--sp-6) var(--sp-4);
  border-bottom: 1px solid var(--border-soft);
  font-size: var(--fs-label);
  font-weight: var(--fw-semibold);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-dim);
  text-align: left;
}
.table td {
  padding: var(--sp-5) var(--sp-6);
  border-bottom: 1px solid var(--border-soft);
  vertical-align: middle;
}
.table tbody tr:last-child td { border-bottom: none; }
.table tbody tr:hover td { background: var(--surface-1); }
.table--zebra tbody tr:nth-child(even) td { background: rgba(0, 0, 0, 0.012); }

/* Sticky header. Requires an ancestor scroller (.view__body) and, if you also
   need a sticky first column, border-collapse: separate. */
.table--sticky thead th {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  background: var(--surface-0);
}
.table--sticky-col { border-collapse: separate; border-spacing: 0; }
.table--sticky-col .is-sticky-col {
  position: sticky;
  left: 0;
  z-index: var(--z-base);
  background: var(--surface-0);
}
/* Never put overflow:hidden on an ancestor of a sticky element — it silently
   kills the stickiness. */

/* ------------------------------------------------- 9. BADGES AND INDICATORS */

.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 3px 9px;
  border-radius: var(--r-pill);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-tight);
  white-space: nowrap;
}
.badge--ok      { background: var(--ok-bg);    color: var(--ok-dark); }
.badge--warn    { background: var(--warn-bg);  color: var(--warn-dark); }
.badge--err     { background: var(--err-bg);   color: var(--err-dark); }
.badge--info    { background: var(--info-bg);  color: var(--info-dark); }
.badge--neutral { background: var(--surface-2); color: var(--text-dim); }

/* Code-ish tag for RICS/UIC codes, env names, short identifiers. */
.tag {
  display: inline-block;
  padding: var(--sp-1) var(--sp-3);
  border: 1px solid var(--border-soft);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
}

.dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.dot--ok { background: var(--delay-ontime); }
.dot--late { background: var(--delay-late); }
.dot--verylate { background: var(--delay-verylate); }
.dot--cancelled { background: var(--delay-cancelled); }
/* "No data" is an outline, never a colour — absence must not look like a state. */
.dot--none { background: var(--surface-2); border: 1.5px solid var(--border-strong); }

.live-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
  background: var(--ok);
  box-shadow: 0 0 0 3px rgba(45, 157, 110, 0.2);
  animation: hr-pulse 1.6s ease-in-out infinite;
}
.live-dot.is-off { animation: none; opacity: 0.4; }
@keyframes hr-pulse {
  0%, 100% { opacity: 1;   box-shadow: 0 0 0 3px rgba(45, 157, 110, 0.2); }
  50%      { opacity: 0.6; box-shadow: 0 0 0 6px rgba(45, 157, 110, 0); }
}

/* ------------------------------------------- 10. MODAL, MENU, EMPTY, LOADING */

.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-8);
  background: rgba(31, 34, 26, 0.5);
  backdrop-filter: blur(3px);
}
.modal {
  display: flex;
  flex-direction: column;
  max-height: 88vh;
  max-width: 95vw;
  overflow: hidden;
  background: var(--surface-0);
  border: 1px solid var(--border-soft);
  border-radius: 12px;
  box-shadow: var(--shadow-modal);
}
.modal--sm { width: 380px; }
.modal--md { width: 560px; }
.modal--lg { width: 760px; }
.modal__head {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-6);
  flex-shrink: 0;
  padding: var(--sp-7) var(--sp-8);
  border-bottom: 1px solid var(--border-soft);
}
.modal__title { font-size: var(--fs-title); font-weight: var(--fw-semibold); }
.modal__sub { font-size: var(--fs-base); color: var(--text-dim); }
.modal__body { flex: 1; min-height: 0; overflow-y: auto; padding: var(--sp-8); }
/* Defined here because HRL used .modal__foot in markup with no rule at all. */
.modal__foot {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  flex-shrink: 0;
  padding: var(--sp-6) var(--sp-8);
  border-top: 1px solid var(--border-soft);
  background: var(--surface-1);
}
.modal__foot-spacer { flex: 1; }
/* Add aria-modal="true", role="dialog" and focus trapping in JS — HRL has none. */

.menu {
  position: absolute;
  z-index: var(--z-dropdown);
  min-width: 190px;
  padding: var(--sp-2);
  background: var(--surface-0);
  border: 1px solid var(--border-soft);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
}
.menu__item {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  width: 100%;
  padding: 7px 9px;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--text);
  font-size: var(--fs-base);
  text-align: left;
  cursor: pointer;
}
.menu__item:hover { background: var(--surface-2); }
.menu__item--danger { color: var(--err-dark); }
.menu__sep { height: 1px; margin: var(--sp-2) 0; background: var(--border-soft); }

.empty {
  padding: 48px var(--sp-9);
  text-align: center;
  color: var(--text-dim);
  font-size: var(--fs-lg);
}
.empty__icon { margin-bottom: var(--sp-6); opacity: 0.5; }

.loading {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-5);
  padding: 28px 0;
  color: var(--text-muted);
  font-size: var(--fs-base);
}
.loading::before {
  content: '';
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  border: 2.5px solid rgba(0, 0, 0, 0.12);
  border-top-color: var(--ht-gold-500);
  border-radius: 50%;
  animation: hr-spin 0.7s linear infinite;
}
@keyframes hr-spin { to { transform: rotate(360deg); } }

/* Inline status message. One component, four states. */
.status-msg {
  padding: var(--sp-4) var(--sp-5);
  border-radius: var(--r-md);
  font-family: var(--font-mono);
  font-size: var(--fs-base);
  white-space: pre-wrap;
}
.status-msg--ok   { background: var(--ok-bg);   color: var(--ok-dark); }
.status-msg--warn { background: var(--warn-bg); color: var(--warn-dark); }
.status-msg--err  { background: var(--err-bg);  color: var(--err-dark); }
.status-msg--info { background: var(--info-bg); color: var(--info-dark); }
/* Put aria-live="polite" on this element — it announces async results. */

/* --------------------------------------------------- 11. PRE-APP GATE SCREEN */

/* Sign-in / config gate. The 45° gold pinstripe over olive is a cheap, very
   recognisable brand signature — reuse it for every service's gate. */
.gate {
  position: fixed;
  inset: 0;
  z-index: var(--z-gate);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-8);
  background: var(--ht-olive-900);
  background-image: repeating-linear-gradient(
    45deg, transparent 0 24px, rgba(245, 168, 0, 0.04) 24px 25px
  );
}
.gate__card {
  width: 480px;
  max-width: 94vw;
  padding: 40px 48px;
  background: var(--surface-0);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-lg);
  text-align: center;
}
.gate__logo { height: 36px; margin-bottom: var(--sp-10); }
.gate__title {
  font-size: 22px;
  font-weight: var(--fw-bold);
  letter-spacing: var(--tracking-display);
  margin: 0 0 var(--sp-3);
}
.gate__sub { font-size: var(--fs-lg); color: var(--text-muted); }

/* ------------------------------------------------------------ 12. RESPONSIVE */

/* Written desktop-first to match HRL, which is why the mobile block needs a few
   overrides. In a brand-new service prefer mobile-first: HRL needed ~35
   `!important` declarations purely to undo desktop rules at this breakpoint. */

@media (max-width: 900px) {
  .split-2 { grid-template-columns: 1fr; }
}

@media (max-width: 767px) {
  /* Sidebar becomes an off-canvas drawer. */
  .app { grid-template-columns: minmax(0, 1fr); }
  .sidebar {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    z-index: var(--z-drawer);
    width: var(--sidebar-w-mobile);
    transform: translateX(-100%);
    transition: transform var(--dur-slow) var(--ease);
  }
  .sidebar.is-open { transform: translateX(0); box-shadow: 4px 0 32px rgba(0, 0, 0, 0.4); }
  .sidebar-backdrop {
    position: fixed;
    inset: 0;
    z-index: var(--z-drawer-backdrop);
    background: rgba(0, 0, 0, 0.55);
  }

  /* Sticky topbar, or mobile Safari scrolls it away. */
  .topbar {
    position: sticky;
    top: 0;
    z-index: var(--z-topbar-mobile);
    padding: var(--sp-4) var(--sp-5);
    gap: var(--sp-3);
  }
  .topbar__crumb, .topbar__sep { display: none; }
  .topbar__title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  .view__head, .view__body { padding-left: var(--sp-6); padding-right: var(--sp-6); }

  /* Touch targets. Deliberate and worth keeping. */
  .nav-item { min-height: 44px; }
  .btn { min-height: 40px; }
  .tabs__tab { min-height: 40px; }
  .iconbtn { width: 40px; height: 40px; }

  .modal { max-width: 95vw; }

  /* Data table → stacked cards. */
  .table--cards thead { display: none; }
  .table--cards, .table--cards tbody, .table--cards tr, .table--cards td { display: block; width: 100%; }
  .table--cards tr {
    margin-bottom: var(--sp-4);
    padding: var(--sp-4) 11px;
    border: 1px solid var(--border-soft);
    border-radius: var(--r-lg);
  }
  .table--cards td { border: 0; padding: var(--sp-1) 0; }
}

/* Installed-PWA notch handling only — must not affect desktop. */
@media (display-mode: standalone) {
  .topbar { padding-top: calc(var(--sp-5) + env(safe-area-inset-top)); }
  .sidebar { padding-bottom: env(safe-area-inset-bottom); }
}

/* ---------------------------------------------------------------- 13. PRINT */

/* HRL has no print styles at all, in an app full of tables people want on
   paper. This is the minimum: drop the chrome, let content flow. */
@media print {
  html, body { height: auto; overflow: visible; background: #fff; }
  .app { display: block; height: auto; }
  .sidebar, .topbar, .bottom-nav, .modal-overlay, .menu, .iconbtn, .btn { display: none !important; }
  .view, .view__body { height: auto; overflow: visible; }
  .card, .table { break-inside: avoid; }
  .table th { color: #000; }
  a[href]::after { content: ' (' attr(href) ')'; font-size: 90%; color: #555; }
}
