:root {
  --bg: #ffffff;
  --bg-page: #f6f6f7;
  --bg-subtle: #fafafa;
  --bg-row: #f7f7f8;
  --bg-head: #eeeef0;
  --bg-hover: #e9e9ec;
  --border: #e4e4e7;
  --border-soft: #ededf0;
  --border-strong: #d4d4d8;
  --text: #18181b;
  --text-secondary: #52525b;
  --text-muted: #71717a;
  --text-faint: #a1a1aa;
  --accent: #7c3aed;
  --accent-hover: #6d28d9;
  --accent-subtle: #f5f3ff;
  --accent-ring: rgba(124, 58, 237, 0.14);
  --cyan: #0891b2;
  --cyan-subtle: #ecfeff;
  --green: #16a34a;
  --green-subtle: #f0fdf4;
  --amber: #d97706;
  --amber-subtle: #fffbeb;
  --danger: #dc2626;
  --danger-subtle: #fef2f2;
  --radius-lg: 14px;
  --radius: 10px;
  --radius-sm: 8px;
  --sidebar-width: 224px;
  --fs-2xs: 0.77rem;
  --fs-xs: 0.85rem;
  --fs-sm: 0.92rem;
  --fs-base: 1rem;
  --fs-md: 1.08rem;
  --fs-lg: 1.15rem;
  --fs-xl: 1.39rem;
  --fs-2xl: 1.54rem;
  --font: "Inter", "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-display: "Inter", "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  --shadow-xs: 0 1px 2px rgba(16, 24, 40, 0.04);
  --shadow-sm: 0 1px 3px rgba(16, 24, 40, 0.07), 0 1px 2px rgba(16, 24, 40, 0.04);
  --shadow-lg: 0 12px 32px -8px rgba(16, 24, 40, 0.16), 0 2px 8px rgba(16, 24, 40, 0.06);
  --brand-gradient: linear-gradient(135deg, #8b5cf6, #6d28d9);
  --converted: #5f7488;
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }

html { font-size: 13px; }
body {
  margin: 0;
  padding: 0;
  font-family: var(--font);
  font-size: var(--fs-base);
  line-height: 1.5;
  color: var(--text);
  background: var(--bg-page);
}

a { color: inherit; text-decoration: none; }
h1, h2, h3 { margin: 0; font-weight: 500; font-family: var(--font-display); }
h1 { font-size: var(--fs-xl); }
h2 { font-size: var(--fs-lg); }

svg { flex-shrink: 0; }

.admin-shell { display: flex; min-height: 100vh; }

.sidebar {
  width: var(--sidebar-width);
  flex-shrink: 0;
  background: var(--bg);
  /* Stated, not inherited: the sidebar can carry its own palette, and text without a colour
     rule of its own would otherwise keep the page's. */
  color: var(--text);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  z-index: 10;
}

.sidebar-head { position: relative; display: flex; align-items: center; margin: 4px; }
.sidebar-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 12px;
  border-radius: var(--radius);
  flex: 1;
  min-width: 0;
  transition: background 0.12s;
}
.sidebar-brand:hover { background: var(--bg-hover); }
.sidebar-collapse {
  position: absolute;
  top: 25px;
  right: -13px;
  z-index: 5;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border: 1px solid var(--border);
  background: var(--bg);
  border-radius: 50%;
  color: var(--text-faint);
  cursor: pointer;
  box-shadow: var(--shadow-sm);
  transition: background 0.12s, color 0.12s;
}
.sidebar-collapse:hover { background: var(--bg-hover); color: var(--text-secondary); }
.sidebar-collapse svg { width: 15px; height: 15px; }
.mobile-brand { display: flex; align-items: center; gap: 8px; }
.brand-mark {
  width: 32px;
  height: 32px;
  border-radius: var(--radius-sm);
  background: var(--brand-gradient);
  box-shadow: 0 2px 6px rgba(124, 58, 237, 0.35);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--fs-md);
  font-weight: 500;
}
.brand-text { display: flex; flex-direction: column; min-width: 0; }
.brand-name { font-family: var(--font-display); font-weight: 500; font-size: var(--fs-md); line-height: 1.25; }
.brand-sub { font-size: var(--fs-xs); color: var(--text-muted); line-height: 1.3; }

.sidebar-nav { padding: 8px 12px; flex: 1; overflow-y: auto; }
.nav-group { margin-top: 10px; }
.nav-group-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  margin-bottom: 2px;
  padding: 6px 10px;
  border: 0;
  background: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
  text-align: left;
  font-family: inherit;
  /* A group heading is never smaller than the links under it. */
  font-size: var(--fs-base);
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-faint);
  transition: background 0.12s, color 0.12s;
}
.nav-group-toggle:hover { background: var(--bg-hover); color: var(--text-secondary); }
.nav-group-title { flex: 1; min-width: 0; }
.nav-group-toggle svg { width: 14px; height: 14px; transition: transform 0.18s ease; }
.nav-group.open > .nav-group-toggle svg { transform: rotate(180deg); }
/* 0fr/1fr rows let the group animate to its own height without hard-coding one. */
.nav-group-body { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.18s ease; }
.nav-group.open > .nav-group-body { grid-template-rows: 1fr; }
/* Clipped links would still take tab focus, so a closed group is hidden outright. Transitioning
   visibility keeps it rendered until the fold finishes, then drops it out of the tab order. */
.nav-group-items { overflow: hidden; min-height: 0; visibility: hidden; transition: visibility 0.18s; }
.nav-group.open > .nav-group-body > .nav-group-items { visibility: visible; }
@media (prefers-reduced-motion: reduce) {
  .nav-group-body, .nav-group-items, .nav-group-toggle svg { transition: none; }
}
.nav-item {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 6px 10px;
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  font-weight: 500;
  margin-bottom: 2px;
  transition: background 0.12s, color 0.12s;
}
.nav-item svg { width: 16px; height: 16px; color: var(--text-muted); transition: color 0.12s; }
.nav-item:hover { background: var(--bg-hover); color: var(--text); }
.nav-item:hover svg { color: var(--text-secondary); }
.nav-item.active { background: var(--accent-subtle); color: var(--accent); }
.nav-item.active svg { color: var(--accent); }
.nav-item.disabled { color: var(--text-faint); cursor: default; }
.nav-item.disabled svg { color: var(--text-faint); opacity: 0.7; }
.nav-item.disabled:hover { background: none; color: var(--text-faint); }
.nav-item.disabled:hover svg { color: var(--text-faint); }
.nav-item .badge { margin-left: auto; }
.nav-soon {
  margin-left: auto;
  font-size: var(--fs-2xs);
  font-weight: 500;
  color: var(--text-faint);
  background: var(--bg-subtle);
  border: 1px solid var(--border-soft);
  border-radius: 999px;
  padding: 0 7px;
  line-height: 16px;
}

/* Lives on the sidebar, not inside .sidebar-nav, whose vertical scroll would clip it away. */
.nav-tooltip {
  position: absolute;
  left: calc(100% + 8px);
  z-index: 30;
  transform: translateY(-50%);
  padding: 5px 10px;
  border-radius: var(--radius-sm);
  background: var(--text);
  color: var(--bg);
  font-size: var(--fs-sm);
  font-weight: 500;
  white-space: nowrap;
  pointer-events: none;
  box-shadow: var(--shadow-lg);
}

.sidebar-footer { border-top: 1px solid var(--border-soft); padding: 10px 12px; }
.user-card {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px;
  border: 0;
  border-radius: var(--radius);
  background: none;
  font: inherit;
  cursor: pointer;
  text-align: left;
  transition: background 0.12s;
}
.user-card:hover { background: var(--bg-hover); }
.avatar {
  width: 32px;
  height: 32px;
  border-radius: 999px;
  background: var(--accent-subtle);
  color: var(--accent);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--fs-sm);
  font-weight: 500;
  flex-shrink: 0;
}
.avatar-sm { width: 28px; height: 28px; font-size: var(--fs-xs); }
.avatar-0 { background: #fef2f2; color: #b91c1c; }
.avatar-1 { background: #eff6ff; color: #1d4ed8; }
.avatar-2 { background: #f0fdf4; color: #15803d; }
.avatar-3 { background: #fffbeb; color: #b45309; }
.avatar-4 { background: #f5f3ff; color: #6d28d9; }
.avatar-5 { background: #ecfeff; color: #0e7490; }
.cell-person { display: flex; align-items: center; gap: 10px; }
.user-meta { flex: 1; min-width: 0; }
.user-name { font-size: var(--fs-base); font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.user-role { font-size: var(--fs-xs); color: var(--text-muted); line-height: 1.3; }
.user-card svg { width: 15px; height: 15px; color: var(--text-faint); }

.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.content { padding: 20px 24px 32px; width: 100%; }

.mobile-bar { display: none; }
.sidebar-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(24, 24, 27, 0.4);
  z-index: 44;
  display: none;
}

@media (max-width: 900px) {
  .mobile-bar {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 16px;
    background: var(--bg);
    border-bottom: 1px solid var(--border);
    position: sticky;
    top: 0;
    z-index: 35;
  }
  .mobile-bar .brand-mark { width: 28px; height: 28px; font-size: var(--fs-sm); }
  .menu-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 6px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg);
    cursor: pointer;
  }
  .menu-btn svg { width: 20px; height: 20px; }
  .sidebar {
    position: fixed;
    left: 0;
    top: 0;
    bottom: 0;
    z-index: 45;
    transform: translateX(-100%);
    transition: transform 0.2s ease;
  }
  .sidebar-collapse { display: none; }
  .sidebar.open { transform: translateX(0); box-shadow: var(--shadow-lg); }
  .sidebar-backdrop.open { display: block; }
  .content { padding: 16px 16px 32px; }
  .page-title { font-size: var(--fs-2xl); }
  .form-grid { grid-template-columns: 1fr; }
  .card { overflow-x: auto; }
  .drawer { width: 100vw; max-width: 100vw; border-left: 0; }
}

.page-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 16px;
}
.page-title { font-family: var(--font-display); font-size: var(--fs-2xl); font-weight: 700; letter-spacing: -0.02em; line-height: 1.25; }
.page-desc { margin: 3px 0 0; color: var(--text-muted); font-size: var(--fs-base); max-width: 640px; }
.au-crumbs { margin-bottom: 4px; font-size: var(--fs-sm); color: var(--text-muted); }
.au-crumbs a { color: inherit; text-decoration: none; }
.au-crumbs a:hover { color: var(--text); text-decoration: underline; }

.menu { position: relative; }
.menu-trigger {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
  cursor: pointer;
  font: inherit;
  font-weight: 500;
}
.menu-trigger:hover { background: var(--bg-hover); }
.menu-panel {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  min-width: 210px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  padding: 5px;
  display: none;
  z-index: 30;
}
.menu.open .menu-panel { display: block; }
.menu-up .menu-panel { top: auto; bottom: calc(100% + 6px); left: 0; right: 0; }
.menu-panel .menu-label {
  padding: 7px 10px 3px;
  font-size: var(--fs-xs);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-faint);
}
.menu-item {
  display: block;
  width: 100%;
  text-align: left;
  padding: 8px 10px;
  border: 0;
  background: none;
  border-radius: var(--radius-sm);
  font: inherit;
  font-weight: 500;
  color: var(--text-secondary);
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}
.menu-item:hover { background: var(--bg-hover); color: var(--text); }
.menu-item.selected { font-weight: 500; color: var(--text); }
.menu-divider { height: 1px; background: var(--border-soft); margin: 5px 4px; }

.card {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
}
.card + .card { margin-top: 16px; }
.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border-soft);
}
.card-body { padding: 16px; }

.toolbar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.toolbar .spacer { flex: 1; }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text);
  font: inherit;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  box-shadow: var(--shadow-xs);
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.btn:hover { background: var(--bg-hover); border-color: var(--border-strong); }
.btn:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--accent-ring); border-color: var(--accent); }
.btn svg { width: 15px; height: 15px; }
.btn-primary {
  background: var(--brand-gradient);
  border-color: var(--accent-hover);
  color: #fff;
  box-shadow: 0 1px 3px rgba(124, 58, 237, 0.35);
}
.btn-primary:hover { background: linear-gradient(135deg, #a78bfa, #5b21b6); border-color: #5b21b6; }
.btn-danger { color: var(--danger); }
.btn-danger:hover { background: var(--danger-subtle); border-color: var(--danger); }
.btn-ghost { border-color: transparent; box-shadow: none; background: none; color: var(--text-secondary); }
.btn-ghost:hover { background: var(--bg-hover); border-color: transparent; color: var(--text); }
.btn-sm { padding: 5px 10px; font-size: var(--fs-base); }
.btn:disabled { opacity: 0.5; cursor: default; }

.input, .select, textarea.input {
  width: 100%;
  padding: 6px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
  font: inherit;
  color: var(--text);
  transition: border-color 0.12s, box-shadow 0.12s;
}
.input:hover, .select:hover, textarea.input:hover { border-color: var(--border-strong); }
.input:focus, .select:focus, textarea.input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-ring);
}
.input::placeholder { color: var(--text-faint); }
.input-inline { width: auto; }
textarea.input { resize: vertical; min-height: 72px; }

.stack { display: flex; flex-direction: column; gap: 16px; }
.stack-sm { display: flex; flex-direction: column; gap: 8px; }
.drawer-form { display: flex; flex-direction: column; height: 100%; }
.maxw-md { max-width: 480px; }
.mb-16 { margin-bottom: 16px; }
.note { color: var(--text-muted); font-size: var(--fs-base); }
.form-label { font-weight: 500; font-size: var(--fs-base); }

.form-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; }
.form-grid .full { grid-column: 1 / -1; }
.field { display: flex; flex-direction: column; gap: 5px; }
.field > label { font-weight: 500; font-size: var(--fs-base); }
.field .hint { font-size: var(--fs-sm); color: var(--text-muted); }
/* A value and the unit it is said in: "every 6 hours" is one answer, so it is one field. */
.input-row { display: flex; gap: 8px; }
.input-row .input { flex: 1 1 auto; min-width: 0; }
.input-row .select { flex: 0 0 auto; width: auto; }
.check {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 500;
  font-size: var(--fs-base);
  cursor: pointer;
}
.check input { width: 16px; height: 16px; accent-color: var(--accent); }

.table { width: 100%; border-collapse: collapse; }
.table th {
  text-align: left;
  padding: 10px 20px;
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 500;
  color: var(--text-muted);
  border-bottom: 1px solid var(--border);
  background: var(--bg-head);
}
.table td { padding: 12px 20px; border-bottom: 1px solid var(--border-soft); vertical-align: middle; }
.table tr:last-child td { border-bottom: 0; }
.table tbody tr { transition: background 0.1s; }
/* Alternating rows first, so a wide row can be followed across the screen; hover then has to
   be a step darker than either of them to still register. */
.table tbody tr:nth-child(even) td { background: var(--bg-row); }
.table tbody tr:hover td { background: var(--bg-hover); }
.table .cell-actions { text-align: right; white-space: nowrap; }
.table th.cell-actions { padding-right: 8px; }
.table th.cell-actions .row-menu-btn { color: var(--text-muted); }
.table .cell-actions form { display: inline-block; }
.table .muted { color: var(--text-muted); }
.table .mono { font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; font-size: var(--fs-base); }

.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: var(--fs-sm);
  font-weight: 500;
  background: var(--bg-hover);
  color: var(--text-secondary);
  border: 1px solid var(--border);
}
.badge-green, .badge-amber, .badge-red, .badge-accent { border-color: transparent; }
.badge-green::before, .badge-amber::before, .badge-red::before, .badge-accent::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 999px;
  background: currentColor;
}
.badge-green { background: var(--green-subtle); color: var(--green); }
.badge-amber { background: var(--amber-subtle); color: var(--amber); }
.badge-red { background: var(--danger-subtle); color: var(--danger); }
.badge-accent { background: var(--cyan-subtle); color: var(--cyan); }

.empty-state {
  padding: 56px 16px;
  text-align: center;
  color: var(--text-muted);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}
.empty-state svg { width: 32px; height: 32px; color: var(--text-faint); }

.pagination { display: flex; align-items: center; gap: 8px; padding: 12px 20px; }
.pagination .info { color: var(--text-muted); font-size: var(--fs-base); margin-right: auto; }


.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(24, 24, 27, 0.4);
  z-index: 50;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 16px;
}
.modal-backdrop.open { display: flex; }
.modal {
  background: var(--bg);
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
  width: 100%;
  max-width: 420px;
}
.modal-wide { max-width: 720px; }
.modal-header { padding: 16px 20px; border-bottom: 1px solid var(--border-soft); font-weight: 500; }
.modal-body { padding: 20px; overflow: auto; max-height: 60vh; }
.modal-footer { padding: 14px 20px; border-top: 1px solid var(--border-soft); display: flex; gap: 8px; justify-content: flex-end; }
/* A dialog whose fields drop a panel over what is under them cannot clip it, so its body does not scroll. */
.modal-body-open { overflow: visible; }

.toast-container {
  position: fixed;
  bottom: 20px;
  right: 20px;
  z-index: 60;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.toast {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--border);
  padding: 11px 16px;
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  font-weight: 500;
  max-width: 380px;
  animation: toast-in 0.18s ease-out;
}
.toast::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 999px;
  background: var(--text-faint);
  flex-shrink: 0;
}
.toast-error::before { background: var(--danger); }
.toast-success::before { background: var(--green); }
@keyframes toast-in {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}

.chip {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  padding: 4px 12px;
  border-radius: 999px;
  border: 1px solid var(--border-soft);
  background: var(--bg);
  color: var(--text-muted);
  font-size: var(--fs-base);
  text-decoration: none;
  transition: border-color 0.12s, background 0.12s, color 0.12s;
}
.chip:hover { border-color: var(--text-faint); color: var(--text); }
.chip-active { background: var(--accent-subtle); border-color: var(--accent); color: var(--accent); font-weight: 500; }

/* ---- List screens ---- */

/* Filter bar. One rule for every list screen: fields keep a fixed comfortable width and wrap
   onto further rows, so a screen with one filter and a screen with eight look the same. The
   action pair always closes the bar on the right. */
.filters { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px; }
.filters .field { flex: 1 1 190px; min-width: 160px; max-width: 280px; }
.filters .field-wide { flex: 2 1 300px; max-width: 460px; }
.filters .field-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
  white-space: nowrap;
}
.filters:has(.field .hint) .field-actions { padding-bottom: calc(var(--fs-sm) * 1.5 + 5px); }
@media (max-width: 700px) {
  .filters .field, .filters .field-wide { flex: 1 1 100%; max-width: none; }
  .filters .field-actions { margin-left: 0; width: 100%; }
}

.chip-row { display: flex; flex-wrap: wrap; gap: 6px; }
.chip .chip-count { font-size: var(--fs-sm); font-weight: 500; color: var(--text-faint); }
.chip-active .chip-count { color: inherit; }

.table-scroll { overflow-x: auto; }
.log-text { margin: 0; padding: 12px 14px; white-space: pre-wrap; overflow-wrap: anywhere; font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; font-size: var(--fs-sm); background: var(--bg-row); border: 1px solid var(--border-soft); border-radius: var(--radius-sm); }
.log-text-scroll { max-height: 520px; overflow: auto; }
.table th a { display: inline-flex; align-items: center; gap: 4px; color: inherit; }
.table th a:hover { color: var(--text); }
.table th .sort-arrow { font-size: var(--fs-2xs); color: var(--accent); }
/* A header that sorts: a link to the grid sorted by it, or a button that sorts the rows in the page. The column in
   use says which way. */
.table th .th-sort {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  color: inherit;
  cursor: pointer;
}
.table th .th-sort:hover { color: var(--text); }
.table th .th-sort:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--accent-ring); border-radius: 3px; }
.table th[aria-sort] .th-sort,
.table th.sorted > a { color: var(--text); }
.table th[aria-sort="ascending"] .th-sort::after,
.table th.sorted.asc > a::after { content: "\2191"; color: var(--accent); }
.table th[aria-sort="descending"] .th-sort::after,
.table th.sorted.desc > a::after { content: "\2193"; color: var(--accent); }
.table .num { text-align: right; white-space: nowrap; }
.table .mid { text-align: center; }
.cell-main { display: block; font-weight: 500; line-height: 1.35; }
.cell-clamp { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.cell-sub { display: block; font-size: var(--fs-sm); color: var(--text-muted); line-height: 1.35; }
.cell-sub.mono { font-size: var(--fs-xs); }

/* Operations grids carry twice the columns of a content list, so they trade the roomy
   default padding for density. Same tokens, same colours. */
.table-dense th { padding: 8px 12px; }
.table-dense td { padding: 9px 12px; font-size: var(--fs-base); }
.table-dense .cell-main { font-size: var(--fs-base); }
.table-dense .cell-sub { font-size: var(--fs-xs); }
.table-dense .badge { font-size: var(--fs-xs); padding: 1px 8px; }
.table-dense .btn-sm { padding: 4px 7px; }
.table-dense td.wrap { white-space: normal; overflow-wrap: anywhere; }

.meter { min-width: 88px; }
.meter-value { font-weight: 500; line-height: 1.3; }
.meter-value .of { color: var(--text-muted); font-weight: 400; }
/* The track is darker than the row hover it sits on, otherwise an empty meter disappears
   under the cursor. */
.meter-track { height: 4px; margin-top: 4px; border-radius: 999px; background: var(--border-strong); overflow: hidden; }
.meter-fill { height: 100%; background: var(--text-faint); }
.meter-fill.part { background: var(--cyan); }
.meter-fill.full { background: var(--green); }
.meter-note { font-size: var(--fs-xs); font-weight: 500; color: var(--green); margin-top: 2px; }

.value-up { color: var(--green); font-weight: 500; }
.value-down { color: var(--danger); font-weight: 500; }

.pagination .pages { display: flex; gap: 4px; flex-wrap: wrap; }
.pagination .pages a, .pagination .pages span {
  min-width: 30px;
  height: 30px;
  padding: 0 9px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: var(--fs-base);
  color: var(--text-secondary);
}
.pagination .pages a:hover { background: var(--bg-hover); border-color: var(--border-strong); }
.pagination .pages .current { background: var(--accent-subtle); border-color: var(--accent); color: var(--accent); font-weight: 500; }
.pagination .pages .gap { border-color: transparent; }
.pagination .rows { display: flex; align-items: center; gap: 6px; font-size: var(--fs-base); color: var(--text-muted); }
.pagination .rows .select { width: auto; padding: 5px 8px; }

/* A wide operations grid keeps its columns on narrow screens and scrolls sideways.
   The first column stays pinned so a scrolled row can still be identified. */
@media (max-width: 900px) {
  .table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .table-dense { min-width: 1040px; }
  .table-dense th:first-child, .table-dense td:first-child {
    position: sticky;
    left: 0;
    z-index: 2;
    background: var(--bg);
    box-shadow: 1px 0 0 var(--border-soft);
  }
  .table-dense th:first-child { background: var(--bg-subtle); }
  .table-dense tbody tr:hover td:first-child { background: var(--bg-subtle); }
  .pagination { flex-wrap: wrap; gap: 10px; }
  .pagination .info { margin-right: 0; width: 100%; }
}

/* ---- Stacked card header ---- */

.card-header-stacked { flex-direction: column; align-items: stretch; gap: 12px; }
.card-header-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }

/* ---- Searchable select ---- */

.combo { position: relative; }
.combo select { display: none; }
.combo-input { cursor: text; }
.combo-panel {
  position: absolute;
  z-index: 30;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  max-height: 260px;
  overflow-y: auto;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
  padding: 4px;
  display: none;
}
.combo.open .combo-panel { display: block; }
.combo-option {
  padding: 6px 9px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  overflow-wrap: anywhere;
}
.combo-option:hover, .combo-option.active { background: var(--bg-hover); }
.combo-option.selected { font-weight: 500; color: var(--accent); }
.combo-empty { padding: 8px 9px; color: var(--text-muted); }

/* ---- Row actions ---- */

.row-menu-btn { padding: 3px 6px; line-height: 1; }
.row-menu-panel {
  position: fixed;
  z-index: 60;
  min-width: 190px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  padding: 5px;
}
.row-menu-panel[hidden] { display: none; }

/* ---- Cell filter link ---- */

.cell-filter,
.cell-link {
  display: inline-flex;
  align-items: center;
  color: var(--text-faint);
  margin-left: 5px;
  vertical-align: middle;
}
.cell-filter:hover, .cell-link:hover { color: var(--accent); }
.cell-filter svg, .cell-link svg { width: 12px; height: 12px; }
.menu-item.danger { color: var(--danger); }
.menu-item.danger:hover { background: var(--danger-subtle); color: var(--danger); }

/* Money and quantity columns line up digit by digit, and the header stays visible while a long
   page is scrolled. */
.table .num, .table .meter-value, .table .mono { font-variant-numeric: tabular-nums; }
.table-dense thead th { position: sticky; top: 0; z-index: 3; }

/* A menu this long only works folded, so the groups get a visible affordance and the list
   scrolls independently of the brand and the footer. */
.sidebar-nav { padding-bottom: 12px; }
.nav-group-toggle > svg:last-child { margin-left: auto; }
/* The operator's actions sit behind the card, so the name keeps the whole footer width. */
.user-menu > .user-card {
  gap: 10px;
  padding: 8px;
  border: 0;
  border-radius: var(--radius);
  background: none;
  color: var(--text);
  font-weight: inherit;
}
.user-menu > .user-card:hover,
.user-menu.open > .user-card { background: var(--bg-hover); }
.user-menu .user-name { display: block; }
.user-card > svg { flex-shrink: 0; }
.user-menu > .menu-panel { min-width: 0; }
.user-menu .menu-label { display: none; }
.user-menu .menu-item { display: flex; align-items: center; gap: 9px; }
.user-menu .menu-item svg { width: 15px; height: 15px; flex-shrink: 0; color: var(--text-muted); }

/* ===== Collapsed sidebar: an icon rail whose groups open on hover ===== */

.sidebar-head { position: relative; }
.nav-group-toggle > svg:first-child { width: 16px; height: 16px; color: var(--text-muted); }

@media (min-width: 901px) {
  html.sidebar-collapsed .sidebar { width: 64px; }

  /* Everything in the rail is centred on one 64px column: brand, collapse control, icons,
     avatar and the footer buttons. */
  html.sidebar-collapsed .sidebar-head { margin: 4px; }
  html.sidebar-collapsed .sidebar-brand { justify-content: center; padding: 10px 0; }
  html.sidebar-collapsed .brand-text { display: none; }

  html.sidebar-collapsed .nav-group-title,
  html.sidebar-collapsed .nav-group-toggle > svg:last-child { display: none; }
  html.sidebar-collapsed .sidebar-nav { padding: 8px 8px 12px; overflow: visible; }
  html.sidebar-collapsed .nav-group-toggle,
  html.sidebar-collapsed .sidebar-nav > .nav-item {
    justify-content: center;
    padding: 8px 0;
    margin: 0;
    gap: 0;
    height: 34px;
  }
  html.sidebar-collapsed .nav-group { margin: 2px 0 0; position: relative; }
  html.sidebar-collapsed .sidebar-nav > .nav-item + .nav-group { margin-top: 2px; }

  /* Hidden from sight but not from screen readers: the label is the link's accessible name. */
  html.sidebar-collapsed .sidebar-nav > .nav-item > .nav-label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  /* A folded list has nowhere to go in the rail, so a group opens sideways instead. The panel
     starts at the rail edge and bridges the distance with its own padding, so the pointer never
     crosses a gap on the way in. */
  html.sidebar-collapsed .nav-group > .nav-group-body {
    position: absolute;
    left: 100%;
    top: -6px;
    z-index: 40;
    display: none;
    min-width: 210px;
    padding: 6px 6px 6px 14px;
    background: var(--bg);
    background-clip: padding-box;
    border: 1px solid var(--border);
    border-left-color: transparent;
    border-radius: var(--radius);
    box-shadow: var(--shadow-lg);
    grid-template-rows: none;
  }
  html.sidebar-collapsed .nav-group:hover > .nav-group-body,
  html.sidebar-collapsed .nav-group:focus-within > .nav-group-body { display: block; }
  html.sidebar-collapsed .nav-group:hover > .nav-group-body .nav-group-items,
  html.sidebar-collapsed .nav-group:focus-within > .nav-group-body .nav-group-items {
    visibility: visible;
    overflow: visible;
  }
  html.sidebar-collapsed .nav-group .nav-item { justify-content: flex-start; padding: 6px 10px; gap: 9px; }

  html.sidebar-collapsed .sidebar-footer { padding: 8px 4px; }
  html.sidebar-collapsed .user-card { justify-content: center; padding: 6px 0; }
  html.sidebar-collapsed .user-meta,
  html.sidebar-collapsed .user-card > svg { display: none; }
  html.sidebar-collapsed .user-menu > .menu-panel { left: calc(100% + 8px); right: auto; bottom: 0; min-width: 200px; }
  html.sidebar-collapsed .user-menu .menu-label {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    text-transform: none;
    letter-spacing: 0;
  }
}

/* ===== Dark palette ===== */

html[data-theme="dark"] {
  --bg: #0e1522;
  --bg-page: #070a0f;
  --bg-subtle: #19233a;
  --bg-row: #131c2e;
  --bg-head: #1e2942;
  --bg-hover: #26344f;
  --border: rgba(255, 255, 255, 0.06);
  --border-soft: rgba(255, 255, 255, 0.045);
  --border-strong: rgba(255, 255, 255, 0.14);
  --text: #f1f5f9;
  --text-secondary: #cbd5e1;
  --text-muted: #c8ccd5;
  --text-faint: #aab4c3;
  --accent: #a78bfa;
  --accent-hover: #8b5cf6;
  --accent-subtle: rgba(139, 92, 246, 0.16);
  --accent-ring: rgba(139, 92, 246, 0.28);
  --cyan: #22d3ee;
  --cyan-subtle: rgba(6, 182, 212, 0.14);
  --green: #10b981;
  --green-subtle: rgba(16, 185, 129, 0.14);
  --amber: #fbbf24;
  --amber-subtle: rgba(251, 191, 36, 0.14);
  --danger: #f87171;
  --danger-subtle: rgba(248, 113, 113, 0.14);
  --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.5);
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.6), 0 1px 2px rgba(0, 0, 0, 0.4);
  --shadow-lg: 0 12px 32px -8px rgba(0, 0, 0, 0.8), 0 2px 8px rgba(0, 0, 0, 0.5);
  --brand-gradient: linear-gradient(135deg, #8b5cf6, #6d28d9);
  color-scheme: dark;
}

/* The primary button keeps white text on the brand gradient in both palettes. */
html[data-theme="dark"] .btn-primary { color: #fff; }
html[data-theme="dark"] .btn-primary:hover { background: linear-gradient(135deg, #a78bfa, #7c3aed); border-color: #6d28d9; }
html[data-theme="dark"] { --converted: #93a7ba; }
html[data-theme="dark"] .meter-track { background: rgba(255, 255, 255, 0.16); }

/* ---- Tags ----
   Attributes of a record (region, platform, code), as opposed to a badge, which carries state.
   Long lists of them wrap and the row keeps its height. */
.tag-row { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }
.tag {
  display: inline-flex;
  align-items: center;
  max-width: 100%;
  padding: 1px 6px;
  border: 1px solid var(--border);
  border-radius: 5px;
  background: var(--bg-subtle);
  color: var(--text-muted);
  font-size: var(--fs-2xs);
  font-weight: 500;
  line-height: 1.6;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.tag-platform { border-color: var(--accent-ring); background: var(--accent-subtle); color: var(--accent); }
.tag-code { font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; }
/* Past this count the row would out-grow the cell, so the rest collapses behind a counter. */
.tag-row .tag-more { cursor: default; }

/* ===== Dark sidebar under the light theme =====
   Only the tokens are re-declared on the sidebar; every rule inside it already reads them, so
   the rail, the flyouts and the footer follow without a single component override. */
html:not([data-theme="dark"]) .sidebar {
  --bg: #0e1522;
  --bg-subtle: #131c2c;
  --bg-row: #131c2c;
  --bg-head: #1b2437;
  --bg-hover: #1b2437;
  --border: rgba(255, 255, 255, 0.07);
  --border-soft: rgba(255, 255, 255, 0.06);
  --border-strong: rgba(255, 255, 255, 0.16);
  --text: #f1f5f9;
  --text-secondary: #cbd5e1;
  --text-muted: #a8b3c4;
  --text-faint: #8b98ab;
  --accent: #a78bfa;
  --accent-subtle: rgba(139, 92, 246, 0.18);
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.5);
  --shadow-lg: 0 12px 32px -8px rgba(0, 0, 0, 0.7), 0 2px 8px rgba(0, 0, 0, 0.5);
  color-scheme: dark;
}


/* Filter labels name the control; they are not headings, so they stay quiet and let the inputs
   carry the weight. The bar is separated from the status chips above it. */
.filters .field > label {
  font-size: var(--fs-xs);
  font-weight: 500;
  color: var(--text-muted);
}
.card-header-row + .filters {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--border-soft);
}

/* ---- Active filters ----
   Present only while the list is narrowed, so its presence is the signal that it is. Each one
   removes itself; the operator never has to guess what is being applied. */
.active-filters {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--border-soft);
}
.active-filters-label {
  font-size: var(--fs-xs);
  font-weight: 500;
  color: var(--text-muted);
  margin-right: 2px;
}
.filter-tag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  max-width: 320px;
  padding: 2px 6px 2px 8px;
  border: 1px solid var(--accent);
  border-radius: 999px;
  background: var(--accent-subtle);
  color: var(--accent);
  font-size: var(--fs-xs);
}
.filter-tag:hover { text-decoration: none; background: var(--bg-hover); }
.filter-tag-key { font-weight: 500; opacity: 0.75; }
.filter-tag-value { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.filter-tag svg { width: 12px; height: 12px; flex-shrink: 0; }
.filter-clear { font-size: var(--fs-xs); color: var(--text-muted); margin-left: 2px; }
.filter-clear:hover { color: var(--accent); }

/* ---- List screen toolbar ---- */

.toolbar-sep { width: 1px; height: 20px; background: var(--border); margin: 0 2px; }

/* ---- Row selection ---- */

.table .cell-select { width: 34px; padding-right: 0; }
.check input, .table .cell-select input, .col-menu-item input {
  appearance: none;
  width: 15px;
  height: 15px;
  margin: 0;
  border: 1px solid var(--border-strong);
  border-radius: 4px;
  background: var(--bg);
  box-shadow: none;
  cursor: pointer;
  position: relative;
  flex-shrink: 0;
}
.check input:checked, .table .cell-select input:checked, .col-menu-item input:checked {
  border-color: var(--accent);
  background: var(--accent);
}
.check input:checked::after, .table .cell-select input:checked::after, .col-menu-item input:checked::after {
  content: "";
  position: absolute;
  left: 4px;
  top: 1px;
  width: 4px;
  height: 8px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.table .cell-select input:indeterminate { border-color: var(--accent); background: var(--accent); }
.table .cell-select input:indeterminate::after {
  content: "";
  position: absolute;
  left: 3px;
  top: 6px;
  width: 7px;
  height: 2px;
  background: #fff;
}
.check input:focus-visible, .table .cell-select input:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-ring);
}
.table tbody tr.is-selected td { background: var(--accent-subtle); }

.selection-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 16px;
  background: var(--accent-subtle);
  border-bottom: 1px solid var(--border);
  font-size: var(--fs-sm);
}
.selection-bar[hidden] { display: none; }
.selection-count { font-weight: 500; color: var(--accent); }
.selection-bar .btn { margin: 0; }

/* ---- Column chooser ---- */

.col-menu-panel { max-height: 320px; overflow-y: auto; }
.col-menu-item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 6px 10px;
  border: 0;
  background: none;
  border-radius: var(--radius-sm);
  font: inherit;
  color: var(--text-secondary);
  cursor: pointer;
  text-align: left;
}
.col-menu-item:hover { background: var(--bg-hover); color: var(--text); }
.col-menu-item input { width: 14px; height: 14px; accent-color: var(--accent); pointer-events: none; }

/* The actions column is pinned to the right edge: on a grid wide enough to scroll, the row
   menu and the column chooser have to stay reachable without scrolling to the end. */
.table th.cell-actions,
.table td.cell-actions {
  position: sticky;
  right: 0;
  z-index: 2;
  box-shadow: -1px 0 0 var(--border);
}
.table th.cell-actions { z-index: 4; background: var(--bg-head); }
.table td.cell-actions { background: var(--bg); }
.table tbody tr:nth-child(even) td.cell-actions { background: var(--bg-row); }
.table tbody tr:hover td.cell-actions { background: var(--bg-hover); }
.table tbody tr.is-selected td.cell-actions { background: var(--accent-subtle); }

/* ---- Detail screens ---- */

/* The aside gives way below a wide desktop: the main column carries the tabs' own tables, which need the room. */
.detail-columns { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 16px; align-items: start; }
@media (max-width: 1500px) { .detail-columns { grid-template-columns: 1fr; } }

.kpi-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin-bottom: 16px; }
.kpi {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
  padding: 12px 14px;
}
.kpi-label { font-size: var(--fs-xs); color: var(--text-muted); font-weight: 500; }
.kpi-value {
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  font-weight: 700;
  line-height: 1.25;
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
}
.kpi-note { font-size: var(--fs-xs); color: var(--text-muted); margin-top: 2px; }

/* Label and value pairs, for the panels beside the main column. */
.facts { display: flex; flex-direction: column; }
.fact {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 7px 0;
  border-bottom: 1px solid var(--border-soft);
}
.fact:last-child { border-bottom: 0; }
.fact-key { color: var(--text-muted); flex-shrink: 0; }
.fact-value { text-align: right; overflow-wrap: anywhere; }

.section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}
.section-head h2 { font-family: var(--font-display); font-size: var(--fs-md); font-weight: 600; }
.section-head h2 .tab-count { vertical-align: 2px; }
.section-count { display: block; font-size: var(--fs-xs); color: var(--text-muted); font-weight: 500; }
/* The way to the whole of what a panel shows a slice of. */
.section-link { font-size: var(--fs-sm); font-weight: 500; color: var(--accent); white-space: nowrap; }
.section-link:hover { text-decoration: underline; }

.key-list { display: flex; flex-wrap: wrap; gap: 4px; }

/* Dark on white in both themes, since that is what a camera reads. */
.qr-code { display: block; width: 176px; height: 176px; background: #fff; border: 1px solid var(--border); border-radius: var(--radius-sm); }
.key-list .tag { font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; }

/* A record id is a handle, not information: it shows shortened and copies in full. */
.id-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  max-width: 100%;
  overflow-wrap: anywhere;
  text-align: left;
  padding: 0 5px;
  border: 1px solid transparent;
  border-radius: 4px;
  background: none;
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: var(--fs-2xs);
  color: var(--text-faint);
  cursor: pointer;
}
.id-chip:hover { border-color: var(--border); background: var(--bg-subtle); color: var(--text-muted); }
.id-chip svg { width: 11px; height: 11px; opacity: 0; }
.id-chip:hover svg { opacity: 1; }
.id-chip.is-copied { color: var(--green); border-color: var(--green); background: var(--green-subtle); }
.id-chip.is-copied::after { content: "Copied"; margin-left: 3px; font-family: var(--font); font-weight: 500; }
/* Beside a label that already names the record, only the icon is needed. */
.id-chip-icon { padding: 1px 3px; vertical-align: middle; }
.id-chip-icon svg { opacity: 0.55; }
.cell-main:hover .id-chip-icon svg { opacity: 1; }

/* ---- Tabs ----
   The open tab is carried in the URL, so a reload, a back navigation and a shared link all land
   on the same one. */
.tabs {
  display: flex;
  gap: 2px;
  flex-wrap: wrap;
  border-bottom: 1px solid var(--border);
  margin-bottom: 16px;
}
.tab {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 14px;
  margin-bottom: -1px;
  border: 1px solid transparent;
  border-bottom: 2px solid transparent;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  color: var(--text-muted);
  font-weight: 500;
}
.tab:hover { color: var(--text); background: var(--bg-hover); text-decoration: none; }
.tab.is-active { color: var(--accent); border-bottom-color: var(--accent); background: none; }
.tab-count {
  font-size: var(--fs-2xs);
  font-weight: 500;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--bg-hover);
  color: var(--text-muted);
}
.tab.is-active .tab-count { background: var(--accent-subtle); color: var(--accent); }

/* A band of label and value pairs, for the facts that head a detail screen. */
.fact-band { display: flex; gap: 0; overflow-x: auto; }
/* One row that scrolls rather than a grid that wraps: wrapping staggered the cells against
   each other and put dividers mid-band. */
/* A rule between the cells: seven label-and-value pairs in a row run together without one. */
.fact-cell {
  display: flex;
  flex-direction: column;
  gap: 1px;
  flex: 1 0 150px;
  min-width: 0;
  padding: 0 16px;
  border-left: 1px solid var(--border-soft);
}
.fact-cell:first-child { padding-left: 0; border-left: 0; }
.fact-cell .fact-key { font-size: var(--fs-xs); color: var(--text-muted); font-weight: 500; }
.fact-cell .fact-value { font-weight: 500; overflow-wrap: anywhere; text-align: left; }
.fact-cell .fact-note { font-size: var(--fs-xs); color: var(--text-muted); }

/* ---- Live region ---- */
/* A region that keeps itself up to date, and the badge that says how fresh it is. */
.live-indicator {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-sm);
  color: var(--text-muted);
  white-space: nowrap;
}
.live-indicator::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--green);
}
/* Nothing is being refreshed while the tab is in the background, so the badge stops
   claiming the page is live. */
.live-indicator.is-paused::before { background: var(--text-faint); }
/* The last refresh did not come back, so what is on screen is older than it looks. */
.live-indicator.is-error { color: var(--danger); }
.live-indicator.is-error::before { background: var(--danger); }

/* Rows that are no longer being kept up to date should not look authoritative. */
[data-poll].is-stale { opacity: 0.55; }

/* A value the browser redraws every second keeps one digit width, so the row does not shuffle. */
[data-countdown], [data-elapsed] { font-variant-numeric: tabular-nums; }
/* A note that belongs beside a value rather than under it. */
.cell-sub-inline { font-size: var(--fs-sm); color: var(--text-muted); }
/* An amount converted into the base currency, wherever one is shown. It is derived from a stored
   rate rather than transacted, so it is marked with a tilde, set in italic and given a colour of
   its own. That colour is deliberately neither the danger red nor the success green: a converted
   figure is a different kind of number, not a good or a bad one. */
.money-converted {
  font-size: var(--fs-xs);
  font-weight: 400;
  font-style: italic;
  color: var(--converted);
}

/* ---- Row state ---- */
.text-danger { color: var(--danger); }
/* A form that is one control in a cell, not a block of its own. */
.row-form { display: inline; margin: 0; }
/* An action that has been fired and is on its way out. */
.is-busy { opacity: 0.5; pointer-events: none; }
.tag-off { border-color: var(--danger); background: var(--danger-subtle); color: var(--danger); }
/* A record that is switched off still has to be readable, only not mistaken for a live one. */
.row-off .cell-main { color: var(--text-muted); font-weight: 400; }

/* ---- Bootstrap component names this template also uses ---- */
/* Bootstrap ships .modal, .toast and .table too. It loads first, so only the properties it
   introduces and this file never set need restating here. */
.toast:not(.show) { display: flex; }
.toast { width: auto; }
.modal { position: static; display: block; height: auto; overflow: visible; }
.table { margin-bottom: 0; }

/* A run that is going on carries a turning spinner in place of the dot every settled state has, so
   a row nobody is watching still reads as live. */
.badge-live::before { display: none; }
.badge-live svg { width: 11px; height: 11px; animation: badge-spin 0.8s linear infinite; }
@keyframes badge-spin {
  to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
  .badge-live svg { animation: none; }
}

/* Bootstrap paints a button from its own variables, through state selectors more specific than
   anything in this file. The variables are what has to carry this template's colours; declaring
   the colour again on :hover would still lose to Bootstrap's :active rules. */
.btn {
  --bs-btn-color: var(--text);
  --bs-btn-hover-color: var(--text);
  --bs-btn-active-color: var(--text);
  --bs-btn-disabled-color: var(--text);
  --bs-btn-bg: var(--bg);
  --bs-btn-hover-bg: var(--bg-hover);
  --bs-btn-active-bg: var(--bg-hover);
  --bs-btn-disabled-bg: var(--bg);
  --bs-btn-border-color: var(--border);
  --bs-btn-hover-border-color: var(--border-strong);
  --bs-btn-active-border-color: var(--border-strong);
  --bs-btn-disabled-border-color: var(--border);
  --bs-btn-box-shadow: none;
  --bs-btn-focus-box-shadow: none;
}
.btn-primary {
  --bs-btn-color: #fff;
  --bs-btn-hover-color: #fff;
  --bs-btn-active-color: #fff;
  --bs-btn-disabled-color: #fff;
  --bs-btn-border-color: var(--accent-hover);
  --bs-btn-hover-border-color: var(--accent-hover);
  --bs-btn-active-border-color: var(--accent-hover);
}
.btn-danger {
  --bs-btn-color: var(--danger);
  --bs-btn-hover-color: var(--danger);
  --bs-btn-active-color: var(--danger);
  --bs-btn-disabled-color: var(--danger);
  --bs-btn-hover-bg: var(--danger-subtle);
  --bs-btn-active-bg: var(--danger-subtle);
  --bs-btn-hover-border-color: var(--danger);
  --bs-btn-active-border-color: var(--danger);
}
.btn-ghost {
  --bs-btn-color: var(--text-secondary);
  --bs-btn-hover-color: var(--text);
  --bs-btn-active-color: var(--text);
  --bs-btn-bg: transparent;
  --bs-btn-border-color: transparent;
  --bs-btn-hover-border-color: transparent;
  --bs-btn-active-border-color: transparent;
}

/* A toast for an action that partly succeeded. */
.toast-warning { border-color: var(--warning, #d97706); }
.toast-warning::before { background: var(--warning, #d97706); }

/* ---- Record screens ---- */

/* The identity line under a record's title: its code, kind and state side by side. */
.record-identity { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 6px; }
.record-identity .id-chip { font-size: var(--fs-xs); }
.page-title .edition { color: var(--text-muted); font-weight: 500; }

/* A picture that belongs to a record, never wider than its card. */
.media-thumb { display: block; max-width: 100%; max-height: 180px; border: 1px solid var(--border); border-radius: var(--radius-sm); }

/* A record's own fields: label over value, in as many columns as the card fits. */
.fact-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 16px 24px; }
.fact-item { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.fact-item .fact-key { font-size: var(--fs-xs); font-weight: 500; }
.fact-item .fact-value { text-align: left; overflow-wrap: anywhere; }
.fact-item.span-2 { grid-column: span 2; }
@media (max-width: 560px) { .fact-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* Several values of one field, one per line. */
.fact-lines { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; }

/* What keeps a record from working as set up, each line with the way to it: a slim bar, not a panel among the
   panels, so it reads as a notice and is gone when there is nothing to say. */
.attention { border-color: var(--border); border-left: 3px solid var(--amber); }
.attention > .card-body { padding: 10px 14px; }
.attention .section-head h2 { font-size: var(--fs-xs); font-weight: 500; text-transform: uppercase; letter-spacing: 0.04em; color: var(--amber); }
.attention h3 { font-size: var(--fs-sm); font-weight: 500; color: var(--text-secondary); }
.attention-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.attention-list li { display: flex; align-items: baseline; gap: 10px; font-size: var(--fs-base); }
.attention-list li::before { content: ""; flex: 0 0 6px; height: 6px; border-radius: 50%; background: var(--amber); transform: translateY(-2px); }
.attention-list li > span { flex: 1; min-width: 0; }
.attention-list li > a { font-weight: 500; color: var(--accent); white-space: nowrap; }
.attention-list li > a::after { content: " \2192"; }
.attention-list li > a:hover { text-decoration: underline; }

/* ---- Pickers ---- */

/* Chosen values of a multiple pick, each removable on its own. */
.combo-chips { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 6px; }
.combo-chips:empty { display: none; }
/* A chosen value is read as often as a field's value, so it is set in the body size, not a tag's. */
.combo-chips .tag { font-size: var(--fs-sm); padding: 2px 8px; color: var(--text); }
.combo-clear { border: 0; background: none; padding: 2px 6px; font: inherit; font-size: var(--fs-sm); font-weight: 500; color: var(--accent); cursor: pointer; }
.combo-chips { max-height: 132px; overflow-y: auto; }
/* A smaller empty state, for a panel that is one among several on the page. */
.empty-state-sm { padding: 18px 16px; gap: 6px; }
.empty-state-sm svg { width: 22px; height: 22px; }
details.fold.card-body > summary { font-size: var(--fs-md); font-weight: 600; color: var(--text); }
details.fold.card-body > summary::after { color: var(--accent); font-weight: 500; }
details.fold.card-body > .table-scroll { margin-top: 10px; }
.combo-clear:hover { text-decoration: underline; }
.tag-remove { border: 0; background: none; padding: 0 0 0 5px; margin: 0; font: inherit; line-height: 1; color: inherit; opacity: 0.6; cursor: pointer; }
.tag-remove:hover { opacity: 1; }
.combo-option .combo-sub { display: block; font-size: var(--fs-xs); color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; }

/* A figure worked out while the operator types, and the cost it is set against. */
.calc { display: flex; flex-wrap: wrap; gap: 4px 16px; padding: 10px 12px; border: 1px solid var(--border-soft); border-radius: var(--radius-sm); background: var(--bg-subtle); }
.calc .fact-key { font-size: var(--fs-xs); }
.calc-cell { display: flex; flex-direction: column; gap: 1px; min-width: 110px; }
.calc-value { font-weight: 500; font-variant-numeric: tabular-nums; }

/* An icon that follows a link inside a fact, such as the one to an outside store. */
.facts a svg, .fact-band a svg, .fact-grid a svg { width: 12px; height: 12px; margin-left: 2px; vertical-align: -1px; }

/* ---- Dialogs drawn by the server ---- */

html.modal-open { overflow: hidden; }
.modal-xl { max-width: 1120px; }
.modal-xl .modal-body { max-height: none; overflow: visible; }
.modal-xl .table-scroll { max-height: calc(100vh - 280px); overflow: auto; }
.modal-header { display: flex; flex-direction: column; align-items: flex-start; justify-content: flex-start; gap: 2px; }
.modal-title { font-weight: 500; }
.modal-sub { font-size: var(--fs-sm); color: var(--text-muted); font-weight: 400; }
.modal-loading { color: var(--text-muted); }
.modal-footer .modal-footer-start { margin-right: auto; }

/* One item chosen from a list held at a fixed height, so the dialog does not jump while results change. */
.chooser { display: flex; flex-direction: column; gap: 8px; }
.chooser-options {
  height: min(300px, 40vh);
  overflow-y: auto;
  padding: 4px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
/* A chooser sharing its dialog with other fields gives them the room. */
.chooser-short .chooser-options { height: min(150px, 24vh); }
.chooser-group { padding: 8px 9px 4px 9px; font-size: var(--fs-xs); font-weight: 500; color: var(--text-muted); }
.chooser-option {
  position: relative;
  padding: 7px 10px 7px 32px;
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.chooser-option::before {
  content: "";
  position: absolute;
  left: 10px;
  top: 10px;
  width: 14px;
  height: 14px;
  border: 1px solid var(--border-strong);
  border-radius: 50%;
  background: var(--bg);
}
.chooser-option:hover, .chooser-option.active { background: var(--bg-hover); }
.chooser-option[aria-selected="true"] { background: var(--accent-subtle); }
.chooser-option[aria-selected="true"]::before { border: 4px solid var(--accent); }
.chooser-option[aria-selected="true"] .cell-main { color: var(--accent); }
.chooser-option.active { box-shadow: inset 0 0 0 1px var(--border-strong); }
.chooser .note:empty { display: none; }

/* ---- Rows that act in place ---- */

/* A row is drawn again after an action, and says so briefly. */
.table tbody tr.row-refreshed td { animation: row-refreshed 1.2s ease-out; }
/* A document a provider sent, folded to its heading until it is looked at. */
details.payload > summary { list-style: none; cursor: pointer; }
details.payload > summary::-webkit-details-marker { display: none; }
details.payload:not([open]) > summary { border-bottom: 0; }
.payload-earlier { margin: 20px 0 8px; }

/* What an action changed, field by field, under its history row. */
.change-list { list-style: none; margin: 4px 0 0; padding: 0; display: flex; flex-direction: column; gap: 2px; font-size: var(--fs-sm); }
.change-list li { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 6px; }
.change-field { font-weight: 500; color: var(--text-secondary); }
.change-field::after { content: ":"; }
.change-old { color: var(--text-muted); text-decoration: line-through; overflow-wrap: anywhere; }
.change-new { color: var(--text); overflow-wrap: anywhere; }
.change-arrow, .change-note { color: var(--text-faint); }

/* A row an action moved out of the tab it is shown in stays until the list is loaded again, drawn back. */
.table tbody tr.row-left-view td:not(.cell-actions) { opacity: 0.6; }
@keyframes row-refreshed { from { background: var(--accent-subtle); } to { background: transparent; } }
@media (prefers-reduced-motion: reduce) { .table tbody tr.row-refreshed td { animation: none; } }

.buying-form { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }

/* A cost range that opens the figures behind it. */
.price-summary { display: inline-flex; flex-direction: column; align-items: flex-end; color: inherit; text-decoration: none; }
.price-summary .cell-main { color: var(--accent); }
.price-summary:hover .cell-main { text-decoration: underline; }

/* ---- Provider Prices ---- */

.table-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; margin-bottom: 10px; }
.price-table.is-grouped > tbody[data-view="rows"],
.price-table:not(.is-grouped) > tbody[data-view="groups"] { display: none; }
.price-table:not(.show-ended) tr.is-ended { display: none; }
.price-table tr.is-ended td { color: var(--text-muted); }
.coverage { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px; margin-top: 10px; font-size: var(--fs-sm); }
.coverage-missing summary { cursor: pointer; color: var(--danger); }
.coverage-missing .cell-sub { margin-top: 4px; }

/* ---- A figure corrected where it is read ---- */

.cell-edit {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  border-bottom: 1px dashed var(--border-strong);
  background: none;
  color: inherit;
  font: inherit;
  text-align: inherit;
  cursor: text;
}
.cell-edit:hover { border-bottom-color: var(--accent); }
.cell-edit .cell-sub { color: var(--text-muted); }
.input-cell {
  width: 100%;
  min-width: 64px;
  height: auto;
  padding: 2px 6px;
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
}
.num .input-cell { text-align: right; }
/* Typed and not yet saved, and refused: both stay on screen until the operator settles them. */
.input-cell.is-dirty { border-color: var(--amber); }
.input-cell.is-invalid { border-color: var(--danger); }
.cell-add { color: var(--text-faint); }

/* ---- Provider credit ----
   The band a balance is in colours the meter and the card edge, so the home cards, the lists and the
   account screen all read the same. */

.meter-fill.credit-ok { background: var(--green); }
.meter-fill.credit-watch { background: var(--amber); }
.meter-fill.credit-critical { background: var(--danger); }

.credit-badges .section-head { margin-bottom: 10px; }
.credit-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 12px; }
.credit-card {
  display: block;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-left: 3px solid var(--text-faint);
  border-radius: var(--radius-lg);
  background: var(--bg);
  box-shadow: var(--shadow-xs);
  color: inherit;
}
.credit-card:hover { border-color: var(--border-strong); text-decoration: none; }
.credit-card.is-ok { border-left-color: var(--green); }
.credit-card.is-watch { border-left-color: var(--amber); }
.credit-card.is-critical { border-left-color: var(--danger); }
.credit-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.credit-name { font-size: var(--fs-sm); color: var(--text-muted); font-weight: 500; overflow-wrap: anywhere; }
.credit-value {
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  font-weight: 700;
  line-height: 1.25;
  margin-top: 4px;
  font-variant-numeric: tabular-nums;
}
.credit-currency { font-size: var(--fs-md); color: var(--text-muted); }
.credit-note { font-size: var(--fs-xs); color: var(--text-muted); margin-top: 2px; }
.credit-card .meter { margin-top: 8px; }

/* ---- Detail screen anatomy ----
   Identity, then the figures that answer the operator's first questions, then a notice when something is
   off, then the tabs, then panels. Each block has one job and nothing below repeats what a block above says. */

/* The identity block: the picture the operator recognises the record by, beside its title. */
.record-head { display: flex; align-items: flex-start; gap: 14px; min-width: 0; }
.record-titles { min-width: 0; }
.record-cover {
  display: block;
  width: 72px;
  height: 72px;
  flex-shrink: 0;
  object-fit: cover;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-subtle);
}
a.record-cover-link { flex-shrink: 0; border-radius: var(--radius-sm); }
a.record-cover-link:hover .record-cover { border-color: var(--accent); }
.record-cover-empty { display: flex; align-items: center; justify-content: center; color: var(--text-faint); }
.record-cover-empty svg { width: 24px; height: 24px; }

/* The record's code on its own page: read at a glance and copied with one click, so it is never retyped. */
.record-code {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  max-width: 100%;
  padding: 3px 9px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg-subtle);
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: var(--fs-md);
  font-weight: 500;
  color: var(--text);
  cursor: pointer;
  overflow-wrap: anywhere;
}
.record-code .code-key { font-family: var(--font); font-size: var(--fs-2xs); font-weight: 500; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-muted); }
.record-code svg { width: 14px; height: 14px; color: var(--text-muted); }
.record-code:hover { border-color: var(--accent); color: var(--accent); }
.record-code:hover svg { color: var(--accent); }
.record-code.is-copied { border-color: var(--green); background: var(--green-subtle); color: var(--green); }
.record-code.is-copied svg { color: var(--green); }
.record-code.is-copied::after { content: "Copied"; font-family: var(--font); font-size: var(--fs-xs); font-weight: 500; }

/* The band of figures under the identity: each cell answers one question and opens the tab that goes into
   it. Rules between the cells are the gaps of the grid, so a band that wraps keeps its lines straight. */
.stat-band {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 1px;
  margin-bottom: 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--border-soft);
  box-shadow: var(--shadow-xs);
  overflow: hidden;
}
.stat {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  padding: 11px 16px 12px;
  background: var(--bg);
  color: inherit;
}
a.stat:hover { background: var(--bg-subtle); text-decoration: none; }
a.stat:hover .stat-key { color: var(--accent); }
.stat-key {
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.stat-value {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  font-weight: 600;
  line-height: 1.3;
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}
/* A name rather than a figure keeps the body size, so a long title does not shout. */
.stat-value.stat-text { font-size: var(--fs-base); font-weight: 600; }
.stat-value .unit { font-size: var(--fs-sm); font-weight: 500; color: var(--text-muted); }
.stat-value.is-empty { color: var(--text-faint); font-weight: 500; }
.stat-value .badge, .stat-value .tag { vertical-align: 2px; }
.stat-note { font-size: var(--fs-xs); color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* A code wherever it is read: the same face the tables use. */
.mono { font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; }

/* A record's fields as a definition list: the label column is as wide as its longest label and no wider,
   so values line up in one column and the eye reads down it. Two pairs to a row where the panel is wide. */
.dl-facts { display: grid; grid-template-columns: max-content minmax(0, 1fr); column-gap: 20px; margin: 0; }
.dl-facts > dt, .dl-facts > dd { margin: 0; min-width: 0; padding: 7px 0; border-top: 1px solid var(--border-soft); }
.dl-facts > dt { padding-top: 9px; font-size: var(--fs-xs); font-weight: 500; color: var(--text-muted); white-space: nowrap; max-width: 170px; overflow: hidden; text-overflow: ellipsis; }
.dl-facts > dd { overflow-wrap: anywhere; }
.dl-facts > dd .cell-sub { display: inline; margin-left: 4px; }
.dl-facts > dd .tag-row { margin-top: 2px; }
.dl-facts-2 { grid-template-columns: max-content minmax(0, 1fr) max-content minmax(0, 1fr); }
.dl-facts-2 > dd { padding-right: 16px; }
@media (max-width: 760px) { .dl-facts-2 { grid-template-columns: max-content minmax(0, 1fr); } }
/* A field with nothing in it is out of the way until asked for, so the panel shows what is known. */
.dl-facts > .is-empty { display: none; }
.dl-facts.show-empty > .is-empty { display: block; }
.dl-facts .empty-value { color: var(--text-faint); }
/* An icon that follows a link in a fact or a figure, such as the one to an outside store. */
.dl-facts a svg, .stat svg, .record-footer svg { width: 12px; height: 12px; margin-left: 2px; vertical-align: -1px; }
.check-sm { font-size: var(--fs-xs); font-weight: 500; color: var(--text-muted); }
.check-sm input { width: 13px; height: 13px; }

/* A panel that holds a table keeps the head and the table apart from the card's own padding. */
.card > .card-body + .table-scroll .table th { border-top: 1px solid var(--border-soft); }

/* The sums under a table whose figures the operator is typing. */
.table tfoot td {
  padding: 10px 12px;
  border-top: 2px solid var(--border);
  border-bottom: 0;
  background: var(--bg-subtle);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}
.table tfoot .cell-sub { font-weight: 400; }
/* A quantity typed into a table keeps to the width of a figure. */
.table .input-qty { width: 84px; padding: 4px 8px; text-align: right; font-variant-numeric: tabular-nums; }

/* The order purchases are taken in: the one taken next stands out, the ones taken are done with. */
.table tbody tr.is-next td { background: var(--accent-subtle); box-shadow: inset 3px 0 0 var(--accent); }
.table tbody tr.is-taken td { color: var(--text-muted); }
.sequence-strip { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.sequence-strip .seq {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  padding: 3px 9px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--bg);
  font-size: var(--fs-sm);
  white-space: nowrap;
}
.sequence-strip .seq-no { font-variant-numeric: tabular-nums; color: var(--text-faint); font-size: var(--fs-2xs); }
.sequence-strip .seq.is-next { border-color: var(--accent); background: var(--accent-subtle); color: var(--accent); font-weight: 500; }
.sequence-strip .seq.is-held { border-color: var(--amber); color: var(--amber); }
.sequence-strip .seq-arrow { color: var(--text-faint); }

/* Text carried for another system, shown whole with its own line breaks. */
.text-block { margin: 0; white-space: pre-line; overflow-wrap: anywhere; max-width: 80ch; }
/* A long text folded to its heading until it is looked at. */
details.fold > summary { cursor: pointer; font-size: var(--fs-xs); font-weight: 500; color: var(--accent); list-style: none; }
details.fold > summary::-webkit-details-marker { display: none; }
details.fold > summary::after { content: " \2193"; }
details.fold[open] > summary::after { content: " \2191"; }
details.fold > .text-block { margin-top: 6px; }

/* When the record was made and changed, and its id: one quiet line at the foot of the page. */
.record-footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 20px;
  margin-top: 20px;
  padding-top: 12px;
  border-top: 1px solid var(--border-soft);
  font-size: var(--fs-xs);
  color: var(--text-muted);
}
.record-footer .id-chip { font-size: var(--fs-2xs); }

/* ---- Record workspace ----
   A record's page: who it is, the figures that open its tabs, the tabs, then one panel per tab holding one table with
   its own search, filters and pages. Nothing wraps into its neighbour: a cell keeps to one line and ends in an
   ellipsis, with the whole text in its title. */

.rw-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: start; gap: 8px 16px; margin-bottom: 14px; }
.rw-crumbs { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-bottom: 4px; font-size: var(--fs-sm); color: var(--text-muted); }
.rw-crumbs a { color: inherit; }
.rw-crumbs a:hover { color: var(--text); text-decoration: underline; }
.rw-crumbs .sep { color: var(--text-faint); }
.rw-title { display: flex; align-items: center; gap: 10px; min-width: 0; margin: 0; font-family: var(--font-display); font-size: var(--fs-2xl); font-weight: 700; letter-spacing: -0.02em; line-height: 1.25; }
.rw-title-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rw-title .badge, .rw-title .tag { flex-shrink: 0; font-family: var(--font); letter-spacing: 0; }
.rw-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 16px; margin-top: 6px; font-size: var(--fs-sm); color: var(--text-muted); }
.rw-meta > * { white-space: nowrap; }
.rw-meta b { font-weight: 500; color: var(--text-secondary); }
.rw-actions { display: flex; align-items: center; gap: 8px; }
@media (max-width: 760px) {
  .rw-head { grid-template-columns: minmax(0, 1fr); }
  .rw-actions { flex-wrap: wrap; }
}

.rw-figures { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 1px; margin-bottom: 14px; border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--border-soft); overflow: hidden; box-shadow: var(--shadow-xs); }
.rw-figures-compact { grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); margin-bottom: 0; }
/* Six figures break three and three, never four and two with empty cells. */
.rw-figures-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
@media (max-width: 1200px) { .rw-figures-6 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 640px) { .rw-figures-6 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.rw-figure { display: flex; flex-direction: column; gap: 3px; min-width: 0; padding: 10px 14px 11px; background: var(--bg); color: inherit; }
a.rw-figure:hover { background: var(--bg-subtle); text-decoration: none; }
a.rw-figure:hover .rw-figure-label { color: var(--accent); }
.rw-figure-label { font-size: var(--fs-2xs); font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rw-figure-value { font-size: var(--fs-lg); font-weight: 600; line-height: 1.35; font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rw-figure-value.is-text { font-size: var(--fs-base); line-height: 1.6; }
.rw-figure-note { font-size: var(--fs-xs); color: var(--text-muted); overflow-wrap: anywhere; }
.rw-figure-note.value-up { color: var(--green); }
.rw-figure-note.value-down { color: var(--danger); }
.record-platform { font-size: var(--fs-sm); color: var(--text-muted); }
.rw-figure.is-warn .rw-figure-value { color: var(--amber); }
.rw-figure.is-bad .rw-figure-value { color: var(--danger); }
.rw-figure.is-good .rw-figure-value { color: var(--green); }
.rw-figure .is-none { color: var(--text-faint); font-weight: 500; }

.skeleton { display: inline-block; width: 3.2em; height: 0.85em; border-radius: 4px; vertical-align: -1px;
  background: linear-gradient(90deg, var(--bg-hover) 25%, var(--bg-subtle) 40%, var(--bg-hover) 65%); background-size: 400% 100%; animation: skeleton 1.3s ease infinite; }
@keyframes skeleton { from { background-position: 100% 50%; } to { background-position: 0 50%; } }
@media (prefers-reduced-motion: reduce) { .skeleton { animation: none; } }

.rw-tabs { display: flex; gap: 2px; margin-bottom: 14px; box-shadow: inset 0 -1px 0 var(--border); overflow-x: auto; overflow-y: hidden; scrollbar-width: thin; }
.rw-tab { display: inline-flex; align-items: center; gap: 6px; padding: 9px 12px 10px; font-weight: 500; color: var(--text-muted); white-space: nowrap; }
.rw-tab:hover { color: var(--text); text-decoration: none; }
.rw-tab.is-active { color: var(--accent); box-shadow: inset 0 -2px 0 var(--accent); }
.rw-tab-count { padding: 0 7px; border-radius: 999px; background: var(--bg-hover); font-size: var(--fs-2xs); font-weight: 600; line-height: 1.6; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.rw-tab.is-active .rw-tab-count { background: var(--accent-subtle); color: var(--accent); }

.rw-panel { background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow-xs); }
.rw-panel + .rw-panel { margin-top: 14px; }
.rw-panel > :last-child { border-bottom-left-radius: var(--radius-lg); border-bottom-right-radius: var(--radius-lg); }
.rw-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; padding: 12px 14px; border-bottom: 1px solid var(--border-soft); }
.rw-bar-start { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; flex: 1 1 auto; min-width: 0; }
.rw-bar-end { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-left: auto; }
.rw-bar-title { margin: 0; font-size: var(--fs-md); font-weight: 600; white-space: nowrap; }
.rw-search { position: relative; flex: 0 1 300px; min-width: 190px; }
.rw-search > svg { position: absolute; left: 10px; top: 50%; width: 15px; height: 15px; transform: translateY(-50%); color: var(--text-faint); pointer-events: none; }
.rw-search > .input { padding-left: 32px; }
.rw-filters { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px 12px; padding: 12px 14px; border-bottom: 1px solid var(--border-soft); background: var(--bg-subtle); }
.rw-filters[hidden] { display: none; }
.rw-filters .field { flex: 0 1 210px; min-width: 150px; }
.rw-filters .field-narrow { flex: 0 1 110px; min-width: 90px; }
.rw-filters .field > label { font-size: var(--fs-sm); font-weight: 500; color: var(--text-secondary); }
.rw-filters .field-actions { display: flex; align-items: flex-end; gap: 8px; }
.label-note { margin-left: 4px; font-size: var(--fs-sm); font-weight: 400; color: var(--text-muted); }
.rw-active { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: 8px 14px; border-bottom: 1px solid var(--border-soft); }
.rw-selection { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 8px 14px; border-bottom: 1px solid var(--border); background: var(--accent-subtle); }
.rw-selection[hidden] { display: none; }
.rw-selection-count { margin-right: 4px; font-weight: 600; color: var(--accent); white-space: nowrap; }

/* The table scrolls inside its panel, so its head and the pages under it stay in view. */
.rw-scroll { overflow: auto; max-height: max(320px, calc(100vh - 210px)); }
.rw-scroll .table th { position: sticky; top: 0; z-index: 3; }
.rw-scroll .table th.cell-actions { z-index: 5; }
@media (max-width: 760px) { .rw-scroll { max-height: none; } }
.table-fixed { table-layout: fixed; }
.one-line { display: block; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* A SKU is read and typed in full: it wraps inside its cell and is never cut. */
.sku { font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; font-variant-numeric: tabular-nums; white-space: normal; overflow-wrap: anywhere; }
.stat-note.is-full { white-space: normal; overflow: visible; text-overflow: clip; overflow-wrap: anywhere; }
.cell-sub .sku { font-size: var(--fs-xs); }
.is-discounted { color: #b45309; }
html[data-theme="dark"] .is-discounted { color: var(--amber); }
.table .one-line.cell-main, .table .one-line.cell-sub { display: block; }
.table tr.row-group td { padding: 7px 12px; background: var(--bg-subtle); border-bottom: 1px solid var(--border-soft); font-size: var(--fs-2xs); font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--text-muted); }
.table tbody tr.row-group:hover td { background: var(--bg-subtle); }
.table .unit { margin-left: 3px; font-size: var(--fs-xs); font-weight: 500; color: var(--text-muted); }
.empty-state .btn { margin-top: 2px; }

/* One choice out of a few; the fields under it follow the choice. */
.seg { align-self: flex-start; display: inline-flex; flex-wrap: wrap; gap: 2px; padding: 3px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--bg-subtle); }
.seg label { position: relative; display: inline-flex; margin: 0; cursor: pointer; }
.seg input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.seg span { padding: 5px 12px; border-radius: 6px; font-weight: 500; color: var(--text-secondary); white-space: nowrap; }
.seg label:hover span { color: var(--text); }
.seg input:checked + span { background: var(--bg); color: var(--accent); box-shadow: var(--shadow-sm); }
.seg input:focus-visible + span { box-shadow: 0 0 0 3px var(--accent-ring); }

/* A form on its own page: sections one under another, the buttons at its foot. */
.rw-form { max-width: 780px; }
.rw-section { padding: 16px 18px; border-top: 1px solid var(--border-soft); }
.secret { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 2px 6px; min-width: 0; max-width: 100%; }
.secret-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* A key shown whole is read whole: it wraps rather than ending in an ellipsis. */
[data-secret].is-shown [data-secret-text] { white-space: normal; overflow-wrap: anywhere; user-select: all; }
.rw-section:first-child { border-top: 0; }
.rw-section-title { margin: 0 0 12px; font-size: var(--fs-md); font-weight: 600; }
.rw-fields { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px 16px; }
.rw-fields-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.rw-fields .span-all { grid-column: 1 / -1; }
.rw-fields > [hidden] { display: none; }
@media (max-width: 640px) { .rw-fields, .rw-fields-3 { grid-template-columns: minmax(0, 1fr); } }
.rw-form-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 12px 18px; border-top: 1px solid var(--border-soft); background: var(--bg-subtle); }
.rw-form-foot .spacer { flex: 1; }
.input-affix { position: relative; }
.input-affix > .input { padding-right: 38px; }
.input-affix > .affix { position: absolute; right: 11px; top: 50%; transform: translateY(-50%); font-size: var(--fs-sm); font-weight: 500; color: var(--text-muted); pointer-events: none; }
.rw-note { padding: 8px 12px; border: 1px solid var(--border-soft); border-radius: var(--radius-sm); background: var(--bg-subtle); font-size: var(--fs-sm); color: var(--text-secondary); }
.rw-note b { font-weight: 600; color: var(--text); }
.rw-error { padding: 8px 12px; border: 1px solid var(--danger); border-radius: var(--radius-sm); background: var(--danger-subtle); color: var(--danger); font-size: var(--fs-sm); }

/* ---- Dialogs keep to the screen ----
   The dialog is never taller than the window: its head and buttons stay put and its body scrolls. Lists that drop
   from a field are placed over the page, so no scrolling body cuts them off. */
.modal { display: flex; flex-direction: column; max-height: calc(100vh - 32px); }
.modal > form { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.modal .modal-body, .modal .modal-body-open, .modal-xl .modal-body { flex: 1 1 auto; min-height: 0; max-height: none; overflow: auto; }
.modal-header, .modal-footer { flex-shrink: 0; }
.modal-wide { max-width: 760px; }
.modal-xl .table-scroll { max-height: none; }
.combo-panel { position: fixed; top: auto; right: auto; bottom: auto; left: auto; z-index: 80; }

