/* ==========================================================================
   Resort Life Integration — Admin Portal
   Theme: "blueprint / system-design". See docs/ui/THEME.md for the full
   writeup. Vanilla CSS, no build step — every selector below targets a
   class name public/portal/js/** actually renders. Dead speculative
   "pass 2" rules from the previous theme (unused nav groups, a purple
   primary accent, a node/connector "blueprint diagram", a counter/
   request-feed component nothing rendered) have been deleted rather than
   layered under — see git history if any of that is wanted back.

   Visual language: light blue-grey canvas with a faint square grid; white
   cards, thin borders, 10px radius; a black top-bar identity chip; every
   button/link/nav-active state built from one neutral charcoal token
   (--btn) — blue is reserved for data (KPI numbers, request/endpoint
   chips, the active section dot, input focus ring); red = problems/
   errors, green = success, amber = admin/warning. Uppercase
   letter-spaced monospace for section labels, table headers and
   method+path rows; bold Space Grotesk headings.
   ========================================================================== */

@import 'tokens.css';
@import 'fonts.css';

* , *::before, *::after { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--text-base);
  color: var(--foreground);
  background-color: var(--background);
  background-image:
    linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
  background-size: var(--grid-size) var(--grid-size);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4 {
  margin: 0 0 var(--space-3) 0;
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.15;
  color: var(--foreground);
}
p { margin: 0 0 var(--space-3) 0; }
code {
  font-family: var(--font-mono);
  font-size: 0.9em;
  background: var(--muted);
  color: var(--foreground);
  padding: 0.1em 0.4em;
  border-radius: var(--radius-xs);
}

.tabular-nums, table { font-variant-numeric: tabular-nums; }
.num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Higher-specificity pairing so a numeric column actually wins over the
   table's own `text-align: left` default (table.data-table td already
   carries two type selectors + one class). */
table.data-table td.num, table.data-table th.num { text-align: right; }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--ink);
  color: #fff;
  padding: var(--space-2) var(--space-4);
  z-index: 1000;
  border-radius: 0 0 var(--radius-md) 0;
  font-size: var(--text-sm);
  font-weight: 600;
}
.skip-link:focus { left: 0; }

a { color: var(--btn); text-decoration: underline; text-underline-offset: 2px; }
a:hover { color: var(--btn-hover); }
a.btn-link, .brand a { text-decoration: none; }

:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--radius-sm);
}
button:focus-visible, a:focus-visible, input:focus-visible, select:focus-visible,
textarea:focus-visible, [tabindex]:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

/* ---------- Icon utilities --------------------------------------------------
   A curated set of lucide icons (ISC licence, see img/icons/LICENSE.txt) is
   vendored as static SVGs and painted with CSS mask-image, so a single
   monochrome file can be recoloured per token via `background-color`. */
.icon {
  display: inline-block;
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  background-color: currentColor;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}
.icon-sm { width: 14px; height: 14px; }
.icon-lg { width: 20px; height: 20px; }
.icon-grid { -webkit-mask-image: url('../img/icons/layout-grid.svg'); mask-image: url('../img/icons/layout-grid.svg'); }
.icon-external { -webkit-mask-image: url('../img/icons/external-link.svg'); mask-image: url('../img/icons/external-link.svg'); }

/* ---------- Utility (small helpers used directly by JS) --------------------- */
.text-muted { color: var(--muted-foreground); }
.mt-0 { margin-top: 0; }
.mb-0 { margin-bottom: 0; }
.ml-1 { margin-left: var(--space-1-5); }
.flex-gap { display: flex; gap: var(--space-3); flex-wrap: wrap; align-items: center; }
.mark, mark.mark { background: var(--mark); color: var(--foreground); padding: 0 3px; border-radius: 2px; }

/* ---------- Auth / login page ------------------------------------------------ */
.auth-page {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-5);
  position: relative;
}
.auth-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
  padding: var(--space-6);
  width: 100%;
  max-width: 400px;
  text-align: center;
}
.auth-logo { width: 40px; height: 40px; display: block; margin: 0 auto var(--space-4); border-radius: var(--radius-sm); }
.auth-title { font-family: var(--font-display); font-size: var(--text-xl); font-weight: 700; margin-bottom: var(--space-1); }
.auth-subtitle { color: var(--muted-foreground); margin-bottom: var(--space-5); font-size: var(--text-sm); }
.auth-form { display: flex; flex-direction: column; text-align: left; }
.auth-sso-btn { width: 100%; }
.auth-divider {
  display: flex;
  align-items: center;
  text-align: center;
  color: var(--muted-foreground);
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin: var(--space-4) 0;
}
.auth-divider::before, .auth-divider::after { content: ''; flex: 1; border-top: 1px dashed var(--border-strong); }
.auth-divider span { padding: 0 var(--space-3); }

/* ---------- Forms ------------------------------------------------------------ */
.form { display: flex; flex-direction: column; gap: var(--space-4); max-width: 480px; }
.form-row { display: flex; gap: var(--space-4); flex-wrap: wrap; align-items: flex-end; }
.form-row > .form-group { flex: 1 1 180px; }
/* A button (or a form-group that only wraps a button) must never grow to
   share the row's leftover space, and must never stretch to the column's
   full width — this is the global fix for "buttons are not inline". */
.form-row > .form-group:has(> .btn) { flex: 0 0 auto; }
.form > .btn, .form-group > .btn { align-self: flex-start; }

.form-group { margin-bottom: var(--space-4); display: flex; flex-direction: column; }
.form-row > .form-group { margin-bottom: 0; }
.form-label {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: var(--text-2xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-bottom: var(--space-1-5);
  color: var(--muted-foreground);
}
.form-hint { font-size: var(--text-xs); color: var(--muted-foreground); margin-top: calc(-1 * var(--space-2)); margin-bottom: var(--space-3); }

.form-input, .form-select, .form-textarea {
  font: inherit;
  font-size: var(--text-sm);
  height: var(--control-height);
  padding: 0 var(--space-3);
  border: 1px solid var(--input-border);
  border-radius: var(--radius-sm);
  background: var(--card);
  color: var(--foreground);
  transition: border-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard);
  width: 100%;
  min-width: 0;
}
.form-input::placeholder, .form-textarea::placeholder { color: var(--muted-foreground); }
.form-input:focus, .form-select:focus, .form-textarea:focus {
  border-color: var(--data);
  box-shadow: var(--focus-ring-data);
  outline: none;
}
.form-input:disabled, .form-select:disabled, .form-textarea:disabled { opacity: 0.5; cursor: not-allowed; }

.form-select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: calc(var(--space-3) * 2 + 14px);
  background-repeat: no-repeat;
  background-position: right var(--space-3) center;
  background-size: 14px 14px;
  /* A same-origin file reference, NOT a data: URI — the strict CSP here
     has no img-src (falls back to default-src 'self', which blocks
     data:), so this must be a vendored file, never an inline SVG. */
  background-image: url('../img/icons/chevron-down.svg');
}

/* ---------- Themed <select> --------------------------------------------------
   A CSP-safe vanilla-JS stand-in for the native option-list popup (see
   ui.js enhanceSelects()) — the browser can't restyle that popup to match
   the theme, so every <select> gets swapped for a themed trigger button
   (reusing .form-select for the 34px height / border / mono arrow) plus a
   listbox popover. The real <select> stays in the DOM, visually hidden. */
.select-wrap { position: relative; width: 100%; }
.select-native-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
  /* This is the standard "visually hidden, still in the accessibility
     tree" clip-rect technique — deliberately NOT display:none/
     visibility:hidden, which screen readers ignore outright. The real
     <select> also gets aria-hidden="true" in ui.js (the enhanced widget's
     accessible name/value lives on the .select-trigger button instead), so
     screen readers never announce this element at all; it stays selectable
     by mouse/keyboard text selection otherwise, though, and a <select>
     renders its own currently-chosen option text as content — so
     select-all-and-copy on the page picked up BOTH this hidden text and the
     visible trigger's label (the "(myself) (myself)" duplicate-text bug).
     user-select:none stops it from ever entering a text selection/copy,
     with no effect on the aria-hidden screen-reader story above. */
  -webkit-user-select: none;
  user-select: none;
}
.select-trigger {
  display: flex;
  align-items: center;
  width: 100%;
  text-align: left;
  cursor: pointer;
  font: inherit;
}
.select-trigger:disabled { cursor: not-allowed; }
.select-trigger-value {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--font-mono);
  color: var(--foreground);
}
.select-popover {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  z-index: 60;
  max-height: 260px;
  overflow-y: auto;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  padding: var(--space-1);
}
.select-optgroup-label {
  padding: var(--space-1-5) var(--space-2-5) var(--space-1);
  font-family: var(--font-mono);
  font-size: var(--text-3xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted-foreground);
}
.select-option {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-2-5);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  color: var(--foreground);
  cursor: pointer;
}
.select-option:hover, .select-option-active { background: var(--muted); }
.select-option[aria-selected='true'] { font-weight: 600; }
.select-option[aria-selected='true'] .select-option-check { visibility: visible; }
.select-option-check {
  visibility: hidden;
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  background-color: var(--btn);
  -webkit-mask-image: url('../img/icons/check.svg');
  mask-image: url('../img/icons/check.svg');
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}
.select-option-disabled { color: var(--muted-foreground); cursor: not-allowed; opacity: 0.6; }
.select-option-hidden { display: none; }
.select-option-label { flex: 1; min-width: 0; display: flex; align-items: baseline; gap: var(--space-1); overflow-wrap: anywhere; }
.select-option-checkbox { cursor: pointer; }
.select-option-checkbox input[type='checkbox'] { margin: 0; flex-shrink: 0; }

/* Two-part option label — client NAME (normal size/weight/colour) plus its
   id as smaller monospace secondary text, truncated with the full id in a
   tooltip (title attr). Owner decision 2026-09-26: "Partner name · rlc_x8nai…". */
.select-option-primary { color: var(--foreground); flex-shrink: 0; }
.select-option-secondary {
  min-width: 0;
  flex-shrink: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  color: var(--muted-foreground); /* #5b6477 on white — ~5.9:1, passes WCAG AA */
}

/* Searchable popover variant (select.dataset.searchable = 'true') — a
   themed search box pinned to the top of the listbox, filtering rows by
   name and/or id as the owner asked. */
.select-search {
  position: sticky;
  top: 0;
  z-index: 1;
  display: block;
  width: 100%;
  margin-bottom: var(--space-1);
  padding: var(--space-1-5) var(--space-2-5);
  font: inherit;
  font-size: var(--text-sm);
  color: var(--foreground);
  background: var(--card);
  border: 1px solid var(--input-border);
  border-radius: var(--radius-sm);
}
.select-search::placeholder { color: var(--muted-foreground); }
.select-search:focus { outline: none; border-color: var(--data); box-shadow: var(--focus-ring-data); }
.select-empty { display: none; padding: var(--space-2) var(--space-2-5); font-size: var(--text-sm); color: var(--muted-foreground); }
.select-empty.is-visible { display: block; }

.form-textarea {
  height: auto;
  min-height: 88px;
  padding-top: var(--space-2-5);
  padding-bottom: var(--space-2-5);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  line-height: 1.6;
  resize: vertical;
}

/* ---------- Themed date field ---------------------------------------------------
   A CSP-safe vanilla-JS stand-in for <input type="date"> (see ui.js
   dateField()) — the browser's native calendar popup can't be restyled to
   match the theme, so it never appears; this button + month-grid popover
   fully replaces it. */
.date-field { position: relative; }
.date-input-trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  cursor: pointer;
  text-align: left;
  font-family: var(--font-mono);
}
.date-input-value { color: var(--muted-foreground); overflow: hidden; text-overflow: ellipsis; }
.date-input-value-set { color: var(--foreground); }
.date-input-icon { color: var(--muted-foreground); -webkit-mask-image: url('../img/icons/calendar.svg'); mask-image: url('../img/icons/calendar.svg'); }
.date-input-trigger:hover .date-input-icon { color: var(--foreground); }

.date-popover {
  position: absolute;
  top: calc(100% + var(--space-1));
  left: 0;
  z-index: 60;
  width: 248px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  padding: var(--space-3);
}
.date-popover-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-2); }
.date-popover-title { font-family: var(--font-display); font-size: var(--text-sm); font-weight: 700; }
.date-nav-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border: 1px solid var(--border);
  border-radius: var(--radius-xs);
  background: var(--card);
  color: var(--foreground);
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
}
.date-nav-btn:hover { background: var(--muted); border-color: var(--border-strong); }
.date-popover-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.date-popover-dow {
  text-align: center;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  color: var(--muted-foreground);
  padding-bottom: var(--space-1);
}
.date-popover-pad { display: block; }
.date-popover-day {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 28px;
  border: 1px solid transparent;
  border-radius: var(--radius-xs);
  background: transparent;
  color: var(--foreground);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  cursor: pointer;
  font-variant-numeric: tabular-nums;
}
.date-popover-day:hover { background: var(--muted); border-color: var(--border-strong); }
.date-popover-day-today { border-color: var(--data-strong); color: var(--data-strong); font-weight: 700; }
.date-popover-day-selected { background: var(--btn); border-color: var(--btn); color: var(--btn-foreground); font-weight: 700; }
.date-popover-clear { width: 100%; margin-top: var(--space-2); }

.form-error { color: var(--destructive); font-size: var(--text-xs); min-height: 0; }
.form-error:not(:empty) {
  background: var(--destructive-surface);
  border: 1px solid var(--destructive-border);
  padding: var(--space-3);
  border-radius: var(--radius-md);
  margin-bottom: var(--space-4);
}

.checkbox-row { display: flex; align-items: flex-start; gap: var(--space-2); margin-bottom: var(--space-2); font-size: var(--text-sm); min-height: 20px; }
.checkbox-row input { margin-top: 2px; }
.checkbox-row label { cursor: pointer; }

fieldset {
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  margin: 0 0 var(--space-4) 0;
  background: var(--muted);
}
legend { font-family: var(--font-mono); font-weight: 600; font-size: var(--text-xs); color: var(--muted-foreground); padding: 0 var(--space-1); text-transform: uppercase; letter-spacing: 0.06em; }

/* Native checkbox — square outline by default, solid charcoal fill + check
   mark when checked. Targets every bare <input type="checkbox"> too
   (module-toggle-list rows, the secret-reveal confirm box). */
input[type='checkbox'] {
  appearance: none;
  -webkit-appearance: none;
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  margin: 0;
  border: 1px solid var(--input-border);
  border-radius: var(--radius-xs);
  background: var(--card);
  position: relative;
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard);
}
input[type='checkbox']:checked { background: var(--btn); border-color: var(--btn); }
input[type='checkbox']:checked::after {
  content: '';
  position: absolute;
  inset: 0;
  background-color: var(--btn-foreground);
  -webkit-mask-image: url('../img/icons/check.svg');
  mask-image: url('../img/icons/check.svg');
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: 75%;
  mask-size: 75%;
}
input[type='checkbox']:disabled { opacity: 0.5; cursor: not-allowed; }

input[type='radio'] {
  appearance: none;
  -webkit-appearance: none;
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  margin: 0;
  border: 1px solid var(--input-border);
  border-radius: var(--radius-full);
  background: var(--card);
  position: relative;
  cursor: pointer;
}
input[type='radio']:checked { border-color: var(--btn); }
input[type='radio']:checked::after {
  content: '';
  position: absolute;
  inset: 3px;
  border-radius: var(--radius-full);
  background: var(--btn);
}

/* ---------- Buttons -----------------------------------------------------------
   Every variant is built from the single --btn charcoal token (owner
   direction: no purple/indigo/blue on any button; blue is reserved for
   data). Compact, inline-flex, never stretched — see .form-row rules
   above for the "sit inline with the inputs" fix. */
.btn {
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  height: var(--control-height);
  padding: 0 var(--space-3);
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-1-5);
  white-space: nowrap;
  flex: 0 0 auto;
  transition: background-color var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard);
}
.btn svg, .btn img.icon, .btn .icon { width: 14px; height: 14px; flex-shrink: 0; }
.btn:disabled { background: var(--btn-disabled); border-color: var(--btn-disabled); color: #fff; opacity: 1; cursor: not-allowed; pointer-events: none; }

.btn-primary { background: var(--btn); color: var(--btn-foreground); }
.btn-primary:hover:not(:disabled) { background: var(--btn-hover); }

.btn-secondary { background: var(--card); color: var(--btn); border-color: var(--btn); }
.btn-secondary:hover:not(:disabled) { background: var(--btn-surface); }
.btn-secondary:disabled { background: var(--card); color: var(--btn-disabled); border-color: var(--btn-disabled); }

.btn-ghost { background: transparent; color: var(--btn); border-color: transparent; }
.btn-ghost:hover:not(:disabled) { background: var(--btn-surface); }
.btn-ghost:disabled { background: transparent; color: var(--btn-disabled); }

.btn-danger { background: transparent; color: var(--destructive); border-color: var(--destructive); }
.btn-danger:hover:not(:disabled) { background: var(--destructive-surface); }
.btn-danger:disabled { background: transparent; color: var(--destructive); opacity: 0.4; }

.btn-outline { background: transparent; color: var(--btn); border-color: var(--border-strong); border-style: dashed; }
.btn-outline:hover:not(:disabled) { background: var(--btn-surface); border-style: solid; border-color: var(--btn); }

.btn-link {
  background: none;
  border: none;
  color: var(--btn);
  text-decoration: underline;
  text-underline-offset: 3px;
  padding: 0;
  height: auto;
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: var(--text-xs);
  text-transform: none;
  letter-spacing: 0;
  cursor: pointer;
}
.btn-link:hover { color: var(--btn-hover); }

.btn-block { width: 100%; }
.btn-sm { height: 28px; padding: 0 var(--space-2-5); font-size: 11px; gap: var(--space-1); }
.btn-sm svg, .btn-sm img.icon, .btn-sm .icon { width: 13px; height: 13px; }
.btn-lg { height: 40px; padding: 0 var(--space-5); }

/* ---------- App shell --------------------------------------------------------- */
.app-shell { min-height: 100vh; display: flex; flex-direction: column; }

/* ---- Top bar ------------------------------------------------------------------
   White strip, 1px dark bottom border. Three cells: a solid black brand
   chip (left), the current section title in mono uppercase with its
   two-digit index (centre), a right cell holding user/role/log-out
   separated by a left border. */
.topbar {
  height: var(--topbar-height);
  background: var(--card);
  color: var(--foreground);
  border-bottom: 1px solid var(--strip-border);
  display: flex;
  align-items: stretch;
  gap: var(--space-3);
  padding: 0 0 0 var(--space-3);
  position: sticky;
  top: 0;
  z-index: var(--z-topbar);
}
.brand { display: flex; align-items: center; }
.brand-name {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  height: 34px;
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--strip-foreground-strong);
  background: var(--ink);
  border-radius: var(--radius-sm);
  padding: 0 var(--space-3);
}
.brand-name .icon { color: #fff; }
.logo-mark { display: none; }

.topbar-section {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--foreground);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.topbar-section-index { color: var(--data); margin-right: var(--space-2); }

.topbar-right {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  height: 100%;
  padding: 0 var(--space-4);
  border-left: 1px solid var(--border);
  flex-shrink: 0;
}
.user-info { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-sm); color: var(--foreground); }
.user-name { font-weight: 600; color: var(--foreground); }
.topbar .badge { font-size: var(--text-3xs); }
.topbar-live {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: 700;
  color: var(--data);
}
.topbar-live::before { content: ''; width: 6px; height: 6px; border-radius: var(--radius-full); background: var(--data); flex-shrink: 0; }

/* ---- Tag row — mono uppercase chip sub-nav under the top bar. Mirrors
   the primary nav (same links); the current section's chip gets a
   filled blue dot and a bolder border. */
.tag-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  padding: var(--space-2-5) var(--space-4);
  background: var(--card);
  border-bottom: 1px solid var(--border);
}
.tag-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1-5);
  padding: var(--space-1) var(--space-2-5);
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--muted-foreground);
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  text-decoration: none;
  white-space: nowrap;
}
.tag-chip:hover { color: var(--foreground); border-color: var(--border-strong); text-decoration: none; }
.tag-chip-dot { width: 6px; height: 6px; border-radius: var(--radius-full); border: 1.5px solid currentColor; flex-shrink: 0; }
.tag-chip-active { border-width: 1.5px; border-color: var(--foreground); color: var(--foreground); font-weight: 700; }
.tag-chip-active .tag-chip-dot { background: var(--data); border-color: var(--data); }

.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  align-self: center;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--foreground);
  border-radius: var(--radius-sm);
  cursor: pointer;
  position: relative;
}
.nav-toggle:hover { background: var(--muted); }
.nav-toggle span[aria-hidden='true'] { font-size: 0; line-height: 0; }
.nav-toggle::before {
  content: '';
  position: absolute;
  inset: 0;
  margin: auto;
  width: 18px;
  height: 18px;
  background-color: currentColor;
  -webkit-mask-image: url('../img/icons/menu.svg');
  mask-image: url('../img/icons/menu.svg');
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}

.app-layout { flex: 1; display: flex; align-items: stretch; }

/* ---------- Primary nav --------------------------------------------------------
   White rail; the active item is NEVER low-contrast: bold near-black text
   on a tinted background plus a solid black/charcoal left bar. */
.primary-nav {
  width: var(--nav-width);
  flex-shrink: 0;
  background: var(--nav-bg);
  border-right: 1px solid var(--nav-border);
  padding: var(--space-3) var(--space-2);
}
/* SPEC §25: nav grouped by API — "the section headings are mono uppercase
   micro-labels". Same mono/uppercase/letter-spaced treatment as <legend>. */
.nav-section {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-bottom: var(--space-3);
}
.nav-section-label {
  font-family: var(--font-mono);
  font-size: var(--text-3xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted-foreground);
  padding: var(--space-2) var(--space-3) var(--space-1);
}
.nav-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.nav-link {
  display: flex;
  align-items: center;
  gap: var(--space-2-5);
  padding: var(--space-2) var(--space-3);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  line-height: 1.4;
  color: var(--nav-foreground);
  text-decoration: none;
  font-weight: 600;
  border-radius: var(--radius-sm);
  position: relative;
  transition: background-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);
}
.nav-link:hover { background: var(--nav-hover); color: var(--nav-foreground-strong); text-decoration: none; }
.nav-link-active {
  background: var(--nav-active-bg);
  color: var(--nav-active-foreground);
  font-weight: 700;
}
.nav-link-active::before {
  content: '';
  position: absolute;
  left: 0;
  top: 4px;
  bottom: 4px;
  width: 3px;
  border-radius: var(--radius-full);
  background: var(--nav-active-mark);
}

.app-main { flex: 1; min-width: 0; padding: var(--space-5); }
.app-main:focus { outline: none; }

.page-title { font-family: var(--font-display); font-size: var(--text-xl); font-weight: 700; margin-bottom: var(--space-1); letter-spacing: -0.01em; }
.page-subtitle { color: var(--muted-foreground); margin-bottom: var(--space-5); font-size: var(--text-sm); }
.page-header { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-4); flex-wrap: wrap; }

/* ---------- Panels / cards ---------------------------------------------------- */
.panel {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
  padding: var(--space-5);
  margin-bottom: var(--space-5);
}
.panel-title { font-family: var(--font-display); font-size: var(--text-md); font-weight: 700; margin-bottom: var(--space-4); letter-spacing: -0.005em; }
/* "Table card header": a panel-title on the left, a primary action button
   (e.g. "Add user" / "Add caller") on the right — same card as the table
   below it, per the owner's table-first-then-drawer layout pattern. */
.panel-header { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); flex-wrap: wrap; margin-bottom: var(--space-4); }
.panel-header .panel-title { margin-bottom: 0; }
.info-row { display: flex; justify-content: space-between; gap: var(--space-4); padding: var(--space-2) 0; border-bottom: 1px solid var(--border); }
.info-row:last-child { border-bottom: none; }
.info-label { color: var(--muted-foreground); font-size: var(--text-sm); }
.info-value { font-weight: 500; font-size: var(--text-sm); color: var(--foreground); }

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: var(--space-3);
  margin-bottom: var(--space-5);
}
.stat-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
  box-shadow: var(--shadow-xs);
  transition: box-shadow var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard);
}
.stat-card:hover { box-shadow: var(--shadow-sm); border-color: var(--border-strong); }
.stat-card-label {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted-foreground);
  margin-bottom: var(--space-2);
}
.stat-card-value {
  font-family: var(--font-mono);
  font-size: var(--text-3xl);
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--data);
  font-variant-numeric: tabular-nums;
}
.stat-card-sub { font-size: var(--text-xs); color: var(--muted-foreground); margin-top: var(--space-1); }

.freshness-banner {
  display: flex;
  align-items: center;
  gap: var(--space-2-5);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  margin-bottom: var(--space-5);
  font-size: var(--text-sm);
  background: var(--card);
  border: 1px solid var(--border);
  border-left: 3px solid var(--border-strong);
}
.freshness-ok { border-left-color: var(--success); color: var(--foreground); }
.freshness-ok .dot { color: var(--success); }
.freshness-stale { border-left-color: var(--warning); color: var(--foreground); }
.freshness-stale .dot { color: var(--warning); }
.freshness-unknown { border-left-color: var(--border-strong); color: var(--muted-foreground); }
.freshness-unknown .dot { color: var(--muted-foreground); }
.dot { width: 8px; height: 8px; border-radius: var(--radius-full); background: currentColor; flex-shrink: 0; }

/* ---------- Card micro-label / version badge ----------------------------------
   Optional header row for a panel: <div class="card-kicker"><span
   class="icon ..."></span>Requests</div> ... <span class="version-badge">V1</span> */
.card-kicker {
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--data-strong);
}
.version-badge {
  display: inline-flex;
  align-items: center;
  padding: 1px var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--text-3xs);
  font-weight: 700;
  color: var(--data);
  background: var(--data-surface-soft);
  border-radius: var(--radius-xs);
}

/* ---------- Tables ------------------------------------------------------------- */
.table-wrap { position: relative; overflow-x: auto; border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--card); }
table.data-table { width: 100%; min-width: max-content; border-collapse: collapse; font-size: var(--text-sm); }
table.data-table th, table.data-table td { padding: var(--space-2-5) var(--space-4); text-align: left; vertical-align: middle; border-bottom: 1px solid var(--border); white-space: nowrap; }
table.data-table th {
  background: var(--muted);
  color: var(--muted-foreground);
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: var(--text-2xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
}
table.data-table th:first-child, table.data-table td:first-child { padding-left: var(--space-5); }
table.data-table th:last-child, table.data-table td:last-child { padding-right: var(--space-5); }
table.data-table tbody tr { transition: background-color var(--duration-fast) var(--ease-standard); }
table.data-table tbody tr:not(:last-child) td { border-bottom: 1px solid var(--border); }
table.data-table tbody tr:hover { background: var(--muted); }
table.data-table tbody tr.row-clickable { cursor: pointer; }
table.data-table tbody tr.row-selected { background: var(--btn-surface); box-shadow: inset 3px 0 0 var(--btn); }
table.data-table td.wrap { white-space: normal; }

/* Allowed callers table — Client column (owner decision 2026-09-26): the
   client's name on one line, its id underneath as smaller monospace
   secondary text; both truncate with an ellipsis (title attr carries the
   full value) so a long name/id never blows out the column. */
.client-cell { display: flex; flex-direction: column; gap: 2px; min-width: 0; max-width: 260px; }
.client-cell-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--foreground); }
.client-cell-id {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  color: var(--muted-foreground);
}
.table-toolbar { display: flex; gap: var(--space-3); flex-wrap: wrap; align-items: center; margin-bottom: var(--space-4); }
.table-actions { display: flex; gap: var(--space-2); flex-wrap: wrap; align-items: center; }

.skeleton-row td { padding: var(--space-2-5) var(--space-4); }
.skeleton-bar {
  display: inline-block;
  width: 100%;
  height: 10px;
  border-radius: var(--radius-xs);
  background: linear-gradient(90deg, var(--muted) 25%, var(--border) 50%, var(--muted) 75%);
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.4s ease-in-out infinite;
}
@keyframes skeleton-shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .skeleton-bar { animation: none; }
}

.chart-loading { display: flex; align-items: center; min-height: 140px; }
.chart-loading .skeleton-bar { height: 100px; }

.empty-state {
  padding: var(--space-6) var(--space-5);
  text-align: center;
  color: var(--muted-foreground);
  font-size: var(--text-sm);
  border: 1.5px dashed var(--border-strong);
  border-radius: var(--radius-md);
}
.empty-state-title { font-family: var(--font-display); font-weight: 700; color: var(--foreground); margin-bottom: var(--space-1); font-size: var(--text-md); }
td > .empty-state { border: none; padding: var(--space-5) 0; }

/* ---------- Badges --------------------------------------------------------------
   Pill-shaped with a small filled bullet: success = green, error = red,
   admin = amber, member/neutral = charcoal tint. */
.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1-5);
  padding: 2px var(--space-2-5) 2px var(--space-2);
  border-radius: var(--radius-full);
  font-family: var(--font-mono);
  font-size: var(--text-3xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  line-height: 1.6;
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--foreground);
  white-space: nowrap;
}
.badge::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: var(--radius-full);
  background: currentColor;
  flex-shrink: 0;
}
.badge-role-admin { background: var(--warning-surface); color: var(--warning); border-color: var(--warning-border); }
.badge-role-member { background: var(--btn-surface); color: var(--btn); border-color: var(--btn-surface-strong); }
.badge-success { background: var(--success-surface); color: var(--success); border-color: var(--success-border); }
.badge-warning { background: var(--warning-surface); color: var(--warning); border-color: var(--warning-border); }
.badge-danger { background: var(--destructive-surface); color: var(--destructive); border-color: var(--destructive-border); }
.badge-info { background: var(--data-surface); color: var(--data); border-color: color-mix(in srgb, var(--data) 30%, transparent); }
.badge-neutral { background: var(--muted); color: var(--muted-foreground); border-color: var(--border); }

.method-badge { font-family: var(--font-mono); font-weight: 700; padding: 2px var(--space-2); border-radius: var(--radius-xs); font-size: var(--text-3xs); letter-spacing: 0.03em; border: 1px solid transparent; }
.method-get { background: var(--data-surface); color: var(--data-strong); border-color: color-mix(in srgb, var(--data-strong) 30%, transparent); }
.method-post { background: var(--success-surface); color: var(--success); border-color: var(--success-border); }
.method-patch { background: var(--warning-surface); color: var(--warning); border-color: var(--warning-border); }
.method-put { background: var(--warning-surface); color: var(--warning); border-color: var(--warning-border); }
.method-delete { background: var(--destructive-surface); color: var(--destructive); border-color: var(--destructive-border); }

/* ---------- Request / endpoint chips -------------------------------------------
   Blocks with a light-blue fill and a navy border — used on the Endpoints
   table (method+path combined) and the Overview "Top routes" list. A
   dashed border marks an inactive/unauthorised item. */
.endpoint-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-2-5);
  background: var(--data-surface);
  border: 1.5px solid var(--data-strong);
  border-radius: var(--radius-sm);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--foreground);
  white-space: nowrap;
}
.endpoint-chip-method { font-weight: 700; color: var(--data-strong); }
.endpoint-chip-inactive { border-style: dashed; opacity: 0.7; }
.route-chip {
  display: inline-flex;
  align-items: center;
  padding: var(--space-1) var(--space-2-5);
  background: var(--data-surface);
  border: 1.5px solid var(--data-strong);
  border-radius: var(--radius-sm);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--foreground);
  overflow-wrap: anywhere;
}
.route-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); }
.route-list-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
.route-list-count { font-family: var(--font-mono); font-weight: 700; color: var(--data); font-variant-numeric: tabular-nums; }

/* Generic pill tag (kept for any future filter-chip use — same visual
   language as .tag-chip). */
.pill-tag {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1-5);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-full);
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--muted-foreground);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  cursor: pointer;
  transition: border-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);
}
.pill-tag-dot { width: 6px; height: 6px; border-radius: var(--radius-full); border: 1.5px solid currentColor; flex-shrink: 0; }
.pill-tag:hover { border-color: var(--border-strong); color: var(--foreground); }
.pill-tag.active, .pill-tag[aria-pressed='true'] { border-color: var(--btn); color: var(--btn); background: var(--btn-surface); }
.pill-tag.active .pill-tag-dot, .pill-tag[aria-pressed='true'] .pill-tag-dot { background: currentColor; }

/* ---------- Callout card (rule / problem) --------------------------------------
   White card with a thick 3px left border — black for info, red for a
   problem/warning. Markup: <div class="callout"><p class="callout-label">
   <span class="icon ..."></span>Rule</p><p class="callout-title">…</p>
   </div> (add class="callout-danger" for PROBLEM). */
.callout {
  background: var(--card);
  border: 1px solid var(--border);
  border-left: 3px solid var(--ink);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
}
.callout-label {
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted-foreground);
  margin: 0 0 var(--space-1);
}
.callout-title { font-family: var(--font-display); font-size: var(--text-md); font-weight: 700; margin: 0; color: var(--foreground); }
.callout-danger { border-left-color: var(--destructive); background: var(--destructive-surface); }
.callout-danger .callout-label, .callout-danger .callout-title { color: var(--destructive); }

/* ---------- Chart ---------------------------------------------------------------
   A real SVG bar chart: faint square grid, blue bars, a mono axis line
   and mono day labels underneath — never a solid black box. */
.chart-svg { display: block; width: 100%; height: 180px; }
.chart-grid-line { stroke: var(--grid-line); stroke-width: 1; }
.chart-axis-line { stroke: var(--border-strong); stroke-width: 1; }
.chart-bar { fill: var(--data); transition: fill var(--duration-fast) var(--ease-standard); }
.chart-bar:hover { fill: var(--data-strong); }
.chart-axis-label {
  font-family: var(--font-mono);
  font-size: 9px;
  fill: var(--muted-foreground);
}
.chart-caption { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--muted-foreground); margin-top: var(--space-2); }

/* ---------- Tabs ----------------------------------------------------------------- */
.tabs { display: flex; flex-direction: column; gap: var(--space-2); }
.tab-list { display: flex; flex-wrap: wrap; gap: var(--space-5); border-bottom: 1px solid var(--border); }
.tab-btn {
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  height: 32px;
  padding: 0 1px;
  margin-bottom: -1px;
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  cursor: pointer;
  color: var(--muted-foreground);
  transition: color var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard);
}
.tab-btn:hover { color: var(--foreground); }
.tab-btn[aria-selected='true'] { color: var(--foreground); border-bottom-color: var(--btn); }
.tab-panel { padding-top: var(--space-4); }
.tab-panel[hidden] { display: none; }

/* ---------- Code blocks ----------------------------------------------------------
   Dark panel, readable light mono text, a thin header strip with the
   language label and a copy button (never just a floating button over
   bare text). */
.code-block-wrap {
  position: relative;
  background: #0f172a;
  border-radius: var(--radius-md);
  overflow: hidden;
}
.code-block-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-1-5) var(--space-3);
  background: #182338;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.code-block-lang {
  font-family: var(--font-mono);
  font-size: var(--text-3xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: #94a3b8;
}
.code-copy-btn {
  height: 22px;
  padding: 0 var(--space-2);
  font-size: 10px;
  background: transparent;
  color: #cbd5e1;
  border-color: rgba(255, 255, 255, 0.25);
}
.code-copy-btn:hover:not(:disabled) { background: rgba(255, 255, 255, 0.1); }

pre.code-block {
  background: transparent;
  color: #e2e8f0;
  padding: var(--space-4);
  padding-bottom: var(--space-3);
  border-radius: 0;
  overflow-x: auto;
  font-family: var(--font-mono);
  font-size: var(--text-code);
  line-height: 1.65;
  margin: 0;
  white-space: pre;
  scrollbar-width: thin;
  scrollbar-color: rgba(226, 232, 240, 0.55) rgba(255, 255, 255, 0.06);
}
/* A long line (a full request URL, a wrapped JSON error envelope) is meant
   to overflow horizontally rather than wrap — this scrollbar is the only
   affordance for that, so it's kept visible at rest (a lit track, not just
   a thumb) rather than the browser's default near-invisible thin style. */
pre.code-block::-webkit-scrollbar { height: 9px; }
pre.code-block::-webkit-scrollbar-track { background: rgba(255, 255, 255, 0.06); border-radius: var(--radius-full); }
pre.code-block::-webkit-scrollbar-thumb { background: rgba(226, 232, 240, 0.55); border-radius: var(--radius-full); border: 2px solid transparent; background-clip: padding-box; }
pre.code-block::-webkit-scrollbar-thumb:hover { background: rgba(226, 232, 240, 0.8); background-clip: padding-box; }

/* Same treatment for a wide table's own horizontal scroll (e.g. the audit
   log's 8 columns, one a full UUID) — visible at rest, not just on hover. */
.table-wrap { scrollbar-width: thin; scrollbar-color: var(--border-strong) var(--muted); }
.table-wrap::-webkit-scrollbar { height: 10px; }
.table-wrap::-webkit-scrollbar-track { background: var(--muted); border-radius: var(--radius-full); }
.table-wrap::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: var(--radius-full); border: 2px solid var(--muted); background-clip: padding-box; }
.table-wrap::-webkit-scrollbar-thumb:hover { background: var(--muted-foreground); }

/* Belt-and-braces "there's more, scroll →" affordance, toggled by ui.js
   (ResizeObserver-driven, only present while there really is unscrolled
   content) — a themed scrollbar alone can be too subtle to notice (some
   browsers/OSes auto-hide it, and it doesn't show at all in a static
   screenshot), so this persistent edge fade is the primary signal. */
.code-block-wrap.has-more-x::after {
  content: '';
  position: absolute;
  top: 34px;
  right: 0;
  bottom: 0;
  width: 28px;
  background: linear-gradient(to right, rgba(15, 23, 42, 0), #0f172a 80%);
  pointer-events: none;
}
.table-wrap.has-more-x::after {
  /* A fade TO the card's own colour would be nearly invisible on a white
     row — this one darkens toward the edge instead, so it reads clearly
     regardless of what's under it. */
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 24px;
  background: linear-gradient(to right, rgba(15, 23, 42, 0), rgba(15, 23, 42, 0.16));
  pointer-events: none;
}

/* ---------- Steps (How to call) — numbered "blueprint" cards --------------------
   A square charcoal numbered badge, a mono uppercase kicker, a bold
   Space Grotesk heading (the step title here doubles as both), body
   text, and a "↓" connector between steps. Dashed border by default
   (upcoming); solid on hover/focus (active). */
.steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); counter-reset: step; }
.steps > li {
  position: relative;
  background: var(--card);
  border: 1.5px dashed var(--border-strong);
  border-radius: var(--radius-lg);
  padding: var(--space-5) var(--space-5) var(--space-5) 64px;
  transition: border-style var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard);
}
.steps > li:not(:last-child)::after {
  content: '↓';
  display: block;
  text-align: center;
  color: var(--border-strong);
  font-family: var(--font-mono);
  font-size: var(--text-md);
  margin: var(--space-1) 0;
}
.steps > li:hover, .steps > li:focus-within {
  border-style: solid;
  border-color: var(--border);
  box-shadow: var(--shadow-sm);
}
.steps > li::before {
  counter-increment: step;
  content: counter(step);
  position: absolute;
  left: var(--space-5);
  top: var(--space-5);
  width: 26px;
  height: 26px;
  border-radius: var(--radius-sm);
  background: var(--btn);
  color: var(--btn-foreground);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: var(--text-sm);
}
.step-title {
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: var(--text-2xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted-foreground);
  margin-bottom: var(--space-1);
}
.howto-content { max-width: 760px; }
.howto-content > p { margin-bottom: var(--space-4); }

/* ---------- Modal ---------------------------------------------------------------- */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgb(15 23 42 / 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
  z-index: var(--z-modal);
}
.modal {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  width: 100%;
  max-width: 520px;
  max-height: calc(100vh - 64px);
  display: flex;
  flex-direction: column;
}
.modal-header { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); padding: var(--space-4) var(--space-5); border-bottom: 1px solid var(--border); }
.modal-title { margin: 0; font-family: var(--font-display); font-size: var(--text-lg); font-weight: 700; }
.modal-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  background: transparent;
  border: none;
  font-size: 0;
  cursor: pointer;
  color: var(--muted-foreground);
  border-radius: var(--radius-sm);
  position: relative;
}
.modal-close:hover { background: var(--muted); color: var(--btn); }
.modal-close::before {
  content: '';
  position: absolute;
  inset: 0;
  margin: auto;
  width: 16px;
  height: 16px;
  background-color: currentColor;
  -webkit-mask-image: url('../img/icons/x.svg');
  mask-image: url('../img/icons/x.svg');
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}
.modal-body { padding: var(--space-5); overflow-y: auto; }
.modal-footer { display: flex; justify-content: flex-end; gap: var(--space-3); padding: var(--space-4) var(--space-5); border-top: 1px solid var(--border); }
body.modal-open { overflow: hidden; }

.secret-box {
  background: var(--muted);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-3);
}
.secret-label { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--muted-foreground); text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: var(--space-1); }
.secret-value-row { display: flex; align-items: center; gap: var(--space-2); }
.secret-value { font-family: var(--font-mono); font-size: var(--text-xs); word-break: break-all; flex: 1; }

/* ---------- Alerts --------------------------------------------------------------- */
.alert { padding: var(--space-3) var(--space-4); border-radius: var(--radius-md); margin-bottom: var(--space-4); font-size: var(--text-sm); background: var(--card); border: 1px solid var(--border); border-left: 3px solid var(--border-strong); }
.alert-warning { border-left-color: var(--warning); }
.alert-danger { background: var(--destructive-surface); border-color: var(--destructive-border); border-left-color: var(--destructive); color: var(--destructive); }
.alert-info { border-left-color: var(--data); }

/* ---------- Toast ------------------------------------------------------------------ */
.toast-region {
  position: fixed;
  bottom: var(--space-5);
  right: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  z-index: var(--z-toast);
  max-width: 360px;
}
.toast {
  background: var(--popover);
  color: var(--popover-foreground);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  border: 1px solid var(--border);
  border-left: 3px solid var(--border-strong);
  box-shadow: var(--shadow-md);
  font-size: var(--text-sm);
  display: flex;
  align-items: center;
  gap: var(--space-3);
  opacity: 0;
  transform: translateY(8px);
  transition: opacity var(--duration-base) var(--ease-standard), transform var(--duration-base) var(--ease-standard);
}
.toast-show { opacity: 1; transform: translateY(0); }
.toast-success { border-left-color: var(--success); }
.toast-error { border-left-color: var(--destructive); }
.toast-info { border-left-color: var(--data); }
.toast-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  background: transparent;
  border: none;
  color: var(--muted-foreground);
  cursor: pointer;
  margin-left: auto;
  padding: 0;
  border-radius: var(--radius-xs);
  flex-shrink: 0;
  font-size: 0;
  position: relative;
}
.toast-close:hover { background: var(--muted); color: var(--btn); }
.toast-close::before {
  content: '';
  position: absolute;
  inset: 0;
  margin: auto;
  width: 14px;
  height: 14px;
  background-color: currentColor;
  -webkit-mask-image: url('../img/icons/x.svg');
  mask-image: url('../img/icons/x.svg');
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}

/* ---------- Audit table: show every column in full, wrap instead of clip ------------
   Body cells wrap and top-align (some values, like the JSON actor id or a
   long route, run to multiple lines); header cells stay on the base
   table.data-table th rule (vertical-align: middle, no forced height) so
   the header band always hugs its own text. */
table.audit-table tbody td { white-space: normal; vertical-align: top; }
table.audit-table td.cell-id {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--muted-foreground);
  overflow-wrap: anywhere;
  word-break: break-word;
}
table.audit-table td.cell-nowrap { white-space: nowrap; }

/* ---------- Slide-in drawer ---------------------------------------------------------- */
.drawer-backdrop {
  position: fixed;
  inset: 0;
  background: rgb(15 23 42 / 0.45);
  z-index: var(--z-drawer-backdrop);
  opacity: 0;
  transition: opacity var(--duration-slow) ease-out;
}
.drawer-backdrop.drawer-open { opacity: 1; }
.drawer {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: 480px;
  max-width: 100%;
  background: var(--card);
  border-left: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
  transform: translateX(100%);
  transition: transform var(--duration-slow) ease-out;
  z-index: var(--z-drawer);
  display: flex;
  flex-direction: column;
}
.drawer.drawer-open { transform: translateX(0); }
@media (prefers-reduced-motion: reduce) {
  .drawer, .drawer-backdrop { transition: none; }
}
@media (max-width: 520px) {
  .drawer { width: 100%; }
}
.drawer-header {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  background: var(--muted);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.drawer-header-title { flex: 1; min-width: 0; display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.drawer-title { margin: 0; font-family: var(--font-mono); font-size: var(--text-md); font-weight: 700; text-transform: uppercase; letter-spacing: 0.02em; overflow-wrap: anywhere; }
.drawer-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  background: transparent;
  border: none;
  font-size: 0;
  cursor: pointer;
  color: var(--muted-foreground);
  padding: 0;
  border-radius: var(--radius-sm);
  flex-shrink: 0;
  position: relative;
}
.drawer-close:hover { background: var(--card); color: var(--btn); }
.drawer-close::before {
  content: '';
  position: absolute;
  inset: 0;
  margin: auto;
  width: 16px;
  height: 16px;
  background-color: currentColor;
  -webkit-mask-image: url('../img/icons/x.svg');
  mask-image: url('../img/icons/x.svg');
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}
.drawer-body { padding: var(--space-5); overflow-y: auto; flex: 1; }
.drawer-section-title { font-family: var(--font-mono); font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted-foreground); margin: var(--space-5) 0 var(--space-2) 0; font-weight: 700; }
.drawer-section-title:first-child { margin-top: 0; }
.drawer .info-row { gap: var(--space-3); }
.drawer .info-row .info-label { font-family: var(--font-mono); font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.04em; }
.drawer .info-value.mono { font-family: var(--font-mono); font-size: var(--text-xs); overflow-wrap: anywhere; text-align: right; }
body.drawer-open-body { overflow: hidden; }
pre.detail-json {
  background: #0f172a;
  color: #e2e8f0;
  border: none;
  border-radius: var(--radius-md);
  padding: var(--space-3);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  overflow-x: auto;
  white-space: pre-wrap;
  word-break: break-word;
}

/* ---------- Endpoints / params table --------------------------------------------------- */
.param-desc { color: var(--muted-foreground); font-size: var(--text-xs); }

.module-toggle-list { display: flex; flex-direction: column; gap: var(--space-2); }

/* ---------- Responsive ------------------------------------------------------------------- */
@media (max-width: 860px) {
  .nav-toggle { display: inline-flex; }
  .app-layout { position: relative; }
  .topbar-section { display: none; }
  .primary-nav {
    position: fixed;
    top: var(--topbar-height);
    left: 0;
    bottom: 0;
    transform: translateX(-100%);
    transition: transform var(--duration-base) var(--ease-standard);
    z-index: var(--z-nav);
    box-shadow: var(--shadow-md);
    overflow-y: auto;
    background: var(--card);
  }
  .primary-nav.nav-open { transform: translateX(0); }
  .app-main { padding: var(--space-3); }
  .app-main, .table-wrap { max-width: 100vw; }
}

@media (max-width: 520px) {
  .auth-card { padding: var(--space-5); }
  .topbar { padding-left: var(--space-2); }
  .topbar-right { padding: 0 var(--space-2); gap: var(--space-2); }
  .user-info .user-name { display: none; }
  .modal-body, .modal-header, .modal-footer { padding: var(--space-4); }
}
