/* ============================================================
   ES-Management admin suite — Radar-style design system
   Dark-first, light-mode toggle via [data-theme="light"].
   Brand: Xerox red #D92231. Type: Space Grotesk / IBM Plex.
   ============================================================ */

:root {
  color-scheme: dark;

  /* surfaces — Radar-style layered, blue-tinted navy */
  --bg: #0b0f1e;
  --bg-inset: #080b16;
  --panel: #14192a;
  --panel-2: #1e2338;
  --panel-3: #282e48;
  --border: #222840;
  --border-strong: #2c324a;

  /* text */
  --text: #f5f6f8;
  --text-muted: #b0b5c0;
  --text-faint: #6a7080;

  /* brand */
  --accent: #d92231;
  --accent-hover: #e8323f;
  --accent-text: #ffffff;
  --accent-tint: rgba(217, 34, 49, 0.14);
  --accent-tint-strong: rgba(217, 34, 49, 0.24);
  --focus-ring: rgba(217, 34, 49, 0.55);

  /* status */
  --success: #3fb27f;
  --warning: #d98a2b;
  --danger: #e0524a;
  --info: #4a90d9;
  --success-tint: rgba(63, 178, 127, 0.14);
  --warning-tint: rgba(217, 138, 43, 0.14);
  --danger-tint: rgba(224, 82, 74, 0.14);
  --info-tint: rgba(74, 144, 217, 0.14);
  --neutral-tint: rgba(139, 144, 154, 0.16);

  /* elevation — Radar's layered depth: lit top edge (inset white ring) + soft
     ambient shadow; the drawer carries a deep left-cast shadow */
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.3), 0 1px 2px rgba(0, 0, 0, 0.2), 0 0 0 1px rgba(255, 255, 255, 0.06);
  --shadow-md: 0 4px 12px -2px rgba(0, 0, 0, 0.35), 0 2px 4px rgba(0, 0, 0, 0.15), 0 0 0 1px rgba(255, 255, 255, 0.06);
  --shadow-lg: 0 12px 32px -6px rgba(0, 0, 0, 0.3), 0 4px 8px rgba(0, 0, 0, 0.1);
  --shadow-drawer: -12px 0 36px rgba(0, 0, 0, 0.45), -4px 0 14px rgba(0, 0, 0, 0.3), 0 0 0 1px rgba(255, 255, 255, 0.06);

  /* brand glow + selection + scrollbar + motion (Radar's signature feel) */
  --border-subtle: rgba(255, 255, 255, 0.04);
  --border-emphasis: rgba(255, 255, 255, 0.22);
  --bg-hover: #282e48;
  --bg-active: #1c2840;
  --glow-accent-sm: 0 0 8px rgba(217, 34, 49, 0.25);
  --glow-accent-md: 0 0 16px rgba(217, 34, 49, 0.25);
  --scrollbar-track: #0f1322;
  --scrollbar-thumb: #2c324a;
  --scrollbar-thumb-hover: #484c55;
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-drawer: cubic-bezier(0.2, 0.8, 0.2, 1);

  /* sidebar stays dark in both themes (Radar look) */
  --sidebar-bg: #0e1014;
  --sidebar-bg-2: #121419;
  --sidebar-text: #c7cbd3;
  --sidebar-muted: #6d727c;
  --sidebar-border: #1e2128;
  --sidebar-hover: #1a1d24;
  --sidebar-active-bg: rgba(217, 34, 49, 0.14);
  --sidebar-active-text: #f4f5f7;

  /* metrics */
  --radius-sm: 6px;
  --radius: 8px;
  --radius-lg: 12px;
  --sidebar-width: 232px;
  --sidebar-rail: 64px;
  --topbar-height: 56px;
  --topbar-control-height: 34px;

  --font-display: "DM Sans", system-ui, sans-serif;
  --font-body: "DM Sans", system-ui, sans-serif;
  --font-mono: "DM Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
}

[data-theme="light"] {
  color-scheme: light;
  --bg: #f6f7f9;
  --bg-inset: #eef0f3;
  --panel: #ffffff;
  --panel-2: #f2f4f7;
  --panel-3: #e9ecf0;
  --border: #e4e7ec;
  --border-strong: #d0d5dd;

  --text: #16181d;
  --text-muted: #5b6068;
  --text-faint: #6b7078;

  --accent-hover: #c01d2b;
  --focus-ring: rgba(217, 34, 49, 0.35);

  --success: #12805c;
  --warning: #b54708;
  --danger: #b42318;
  --info: #175cd3;
  --success-tint: rgba(18, 128, 92, 0.1);
  --warning-tint: rgba(181, 71, 8, 0.1);
  --danger-tint: rgba(180, 35, 24, 0.09);
  --info-tint: rgba(23, 92, 211, 0.1);
  --neutral-tint: rgba(91, 96, 104, 0.1);

  --shadow-sm: 0 1px 3px rgba(16, 24, 40, 0.08), 0 1px 2px rgba(16, 24, 40, 0.04), 0 0 0 1px rgba(0, 0, 0, 0.06);
  --shadow-md: 0 4px 12px -2px rgba(16, 24, 40, 0.12), 0 2px 4px rgba(16, 24, 40, 0.06), 0 0 0 1px rgba(0, 0, 0, 0.06);
  --shadow-lg: 0 12px 32px -6px rgba(16, 24, 40, 0.16), 0 4px 8px rgba(16, 24, 40, 0.06);
  --shadow-drawer: -12px 0 36px rgba(16, 24, 40, 0.18), -4px 0 14px rgba(16, 24, 40, 0.1), 0 0 0 1px rgba(0, 0, 0, 0.06);

  --border-subtle: rgba(0, 0, 0, 0.04);
  --border-emphasis: rgba(0, 0, 0, 0.18);
  --bg-hover: #e9ecf0;
  --bg-active: #eef0f3;
  --glow-accent-sm: 0 0 8px rgba(217, 34, 49, 0.18);
  --glow-accent-md: 0 0 16px rgba(217, 34, 49, 0.18);
  --scrollbar-track: #eef0f3;
  --scrollbar-thumb: #d0d5dd;
  --scrollbar-thumb-hover: #b0b5c0;
}

/* ---------- light mode: public auth + portal surfaces ----------
   The shared palette above already swaps every token (bg/panel/text/border/
   shadow), and the public + portal chrome is token-driven, so those pages
   inherit a complete light theme. This scoped block carries the small
   public-only refinements: the red .brand-panel stays identical in both
   themes (its gradient is literal, untouched), while the paper-white cards
   get a touch more elevation so they don't flatten against the white page. */
[data-theme="light"] .public-card,
[data-theme="light"] .login-card,
[data-theme="light"] .onboarding-card {
  box-shadow: var(--shadow-lg);
}

/* ---------- base ---------- */

* { box-sizing: border-box; }

html { height: 100%; }

/* Themed scrollbars (Radar's thin, tinted rails). */
* { scrollbar-width: thin; scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track); }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: var(--scrollbar-track); }
::-webkit-scrollbar-thumb { background: var(--scrollbar-thumb); border-radius: 999px; border: 2px solid var(--scrollbar-track); }
::-webkit-scrollbar-thumb:hover { background: var(--scrollbar-thumb-hover); }

body {
  margin: 0;
  min-height: 100%;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -0.01em;
  margin: 0;
}

/* Radar pairs a big bold display weight with a quiet body: page titles get a
   heavier, tighter treatment for strong size/weight contrast. */
h1 { font-weight: 700; letter-spacing: -0.02em; }

a { color: var(--info); text-decoration: none; transition: color 150ms ease; }
a:hover { color: var(--accent); }

code, .mono { font-family: var(--font-mono); font-size: 12.5px; font-variant-numeric: tabular-nums; }

:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 1px;
  border-radius: 4px;
}

/* ---------- app shell ---------- */

.app-shell {
  display: grid;
  grid-template-columns: var(--sidebar-width) 1fr;
  min-height: 100vh;
  transition: grid-template-columns 200ms ease;
}

body.sidebar-collapsed .app-shell { grid-template-columns: var(--sidebar-rail) 1fr; }

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

.app-content {
  padding: 24px 28px 48px;
  /* Every admin surface fills the content width like the Radar resources
     pages (registrations/organizations/users); no centered 1280px column. */
  max-width: none;
  width: 100%;
  margin: 0 auto;
}

.page-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 20px;
  flex-wrap: wrap;
}

.page-title { font-size: 26px; font-weight: 700; letter-spacing: -0.02em; }
.page-sub { color: var(--text-muted); font-size: 13px; margin-top: 2px; }

/* ---------- sidebar ---------- */

.sidebar {
  background: linear-gradient(180deg, var(--sidebar-bg) 0%, var(--sidebar-bg-2) 100%);
  border-right: 1px solid var(--sidebar-border);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: hidden;
}

.sidebar-brand {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 10px;
  padding: 0 16px;
  height: var(--topbar-height);
  box-sizing: border-box;
  flex: none;
}

/* Official Xerox wordmark (app/static/xerox-logo.svg). Xerox red on
   transparent, so it reads on the dark sidebar and light cards alike. */

.brand-logo {
  display: block;
  height: 22px;
  width: auto;
  flex: none;
}

.brand-logo-on-red { height: 38px; filter: brightness(0) invert(1); }

/* On the red public panel the official wordmark (Xerox red on transparent)
   would vanish, so .brand-logo-on-red inverts it to white above. The wrap
   only handles placement and spacing — no chip background. */
.brand-logo-wrap {
  align-self: flex-start;
  display: inline-block;
  margin-bottom: 26px;
}

.sidebar-nav-wrap {
  flex: 1;
  min-height: 0;
  position: relative;
  display: flex;
  flex-direction: column;
}

.sidebar-nav {
  flex: 1;
  min-height: 0;
  padding: 14px 10px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  overflow-y: auto;
  /* The scrollbar is hidden (scrolling fully preserved) — the more-below
     affordance replaces it as the scroll cue. */
  scrollbar-width: none;
}

.sidebar-nav::-webkit-scrollbar { display: none; }

/* More-below affordance: a fade-out gradient over the nav's bottom edge with
   a gently nudging chevron. Shown only while the nav is scrollable and NOT
   scrolled to the end (app.js toggles .visible on scroll/resize/collapse).
   pointer-events: none — it never blocks nav clicks. The fade ends on
   --sidebar-bg-2, the sidebar's bottom gradient stop, so it blends in both
   themes (the sidebar stays dark in light mode too). */
.sidebar-more-hint {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 56px;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding-bottom: 6px;
  background: linear-gradient(180deg, transparent 0%, var(--sidebar-bg-2) 78%);
  color: var(--sidebar-muted);
  pointer-events: none;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 200ms var(--ease-out), transform 200ms var(--ease-out);
}

.sidebar-more-hint.visible { opacity: 1; transform: none; }

.sidebar-more-hint svg { animation: sidebar-hint-nudge 1.6s ease-in-out infinite; }

@keyframes sidebar-hint-nudge {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(4px); }
}

.nav-item {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 8px 12px;
  border-radius: var(--radius);
  color: var(--sidebar-muted);
  font-weight: 500;
  font-size: 13.5px;
  position: relative;
  white-space: nowrap;
  transition: background 150ms ease, color 150ms ease;
  background: transparent;
  border: 0;
  cursor: pointer;
  font-family: inherit;
  text-align: left;
  width: 100%;
}

.nav-item svg { flex: none; opacity: 0.85; }

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

.nav-item.active {
  background: var(--sidebar-active-bg);
  color: var(--sidebar-active-text);
}

.nav-item.active::before {
  content: "";
  position: absolute;
  left: -10px;
  top: 8px;
  bottom: 8px;
  width: 3px;
  border-radius: 0 3px 3px 0;
  background: var(--accent);
}

.nav-item.active svg { opacity: 1; }

.nav-label { overflow: hidden; text-overflow: ellipsis; }

.nav-count {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--sidebar-muted);
  background: rgba(255, 255, 255, 0.05);
  border-radius: 999px;
  padding: 1px 7px;
}

.nav-item.active .nav-count { color: var(--sidebar-active-text); background: rgba(255, 255, 255, 0.1); }

.nav-badge { color: var(--warning); background: var(--warning-tint); font-weight: 600; }

.nav-badge[data-nav-badge="registrations"] { color: var(--danger); background: var(--danger-tint); }

.nav-badge-info { color: var(--info); background: var(--info-tint); }

/* Consolidated nav apps: a labelled group of related menus. The group label is
   a small uppercase caption; its children are the regular .nav-item links. */
.nav-group { display: flex; flex-direction: column; gap: 2px; margin-top: 12px; }
.nav-group:first-of-type { margin-top: 6px; }
.nav-group-label {
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--sidebar-text-faint, var(--text-faint));
  padding: 0 12px 4px;
}

.sidebar-footer {
  padding: 10px;
  border-top: 1px solid var(--sidebar-border);
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* Drawer-only extras (global search + preferences): hidden on desktop; the
   off-canvas nav shows them at <=980px, where the topbar is a single dense
   row and cannot carry them. */
.drawer-extras { display: none; }

/* collapsed rail */
body.sidebar-collapsed .nav-label,
body.sidebar-collapsed .nav-count { display: none; }

body.sidebar-collapsed .nav-group-label { display: none; }
body.sidebar-collapsed .nav-group { margin-top: 8px; }

body.sidebar-collapsed .sidebar-brand { align-items: center; justify-content: center; padding: 0 8px; }
body.sidebar-collapsed .brand-logo { display: none; }
body.sidebar-collapsed .nav-item { justify-content: center; padding: 10px; }
body.sidebar-collapsed .nav-item.active::before { left: -6px; }

/* The collapse toggle's chevron always points the way the ACTION goes:
   collapsed → flip to point right (the expand direction), expanded →
   point left (the collapse direction). The arrow is currentColor, so it
   follows both themes automatically. */
#collapse-btn .collapse-arrow { transform-origin: center; transition: transform 150ms ease; }
body.sidebar-collapsed #collapse-btn .collapse-arrow { transform: scaleX(-1); }

/* ---------- top bar ---------- */

.topbar {
  position: sticky;
  top: 0;
  z-index: 40;
  height: var(--topbar-height);
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 0 20px;
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--border);
}

.scope-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: var(--topbar-control-height);
  box-sizing: border-box;
  padding: 0 12px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  background: var(--panel);
  color: var(--text-muted);
  font-size: 12.5px;
  white-space: nowrap;
}
.scope-chip .mono { color: var(--text); }

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

/* Session-scoped CrushFTP instance selector in the topbar (replaces the static
   server-group chip). A native <select> posts to /admin/instances/select and
   re-renders the users view for the chosen instance. */
.instance-selector {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: var(--topbar-control-height);
  box-sizing: border-box;
  padding: 0 8px 0 12px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  background: var(--panel);
  color: var(--text-muted);
  font-size: 12.5px;
  white-space: nowrap;
}
.instance-selector select {
  background: transparent;
  color: var(--text);
  border: none;
  font: inherit;
  font-family: var(--font-mono, monospace);
  max-width: 240px;
  cursor: pointer;
}
.instance-selector select:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* Instance edit row on /admin/instances reuses .domain-edit-row; the form wraps
   its six inputs + save button across the wide row. */
.instance-edit-form { margin-top: 0; flex-wrap: wrap; align-items: flex-start; }
.instance-edit-form > input { flex: 1 1 180px; }

.status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--text-faint);
  flex: none;
}

.status-dot[data-state="ok"] {
  background: var(--success);
  animation: dot-pulse 2.2s ease-in-out infinite;
}

.status-dot[data-state="warn"] { background: var(--warning); animation: dot-pulse-warn 1.6s ease-in-out infinite; }
.status-dot[data-state="down"] { background: var(--danger); animation: dot-pulse-down 1.2s ease-in-out infinite; }

@keyframes dot-pulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--success) 45%, transparent); }
  50% { box-shadow: 0 0 0 5px transparent; }
}

@keyframes dot-pulse-warn {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--warning) 50%, transparent); }
  50% { box-shadow: 0 0 0 5px transparent; }
}
@keyframes dot-pulse-down {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--danger) 50%, transparent); opacity: 1; }
  50% { box-shadow: 0 0 0 5px transparent; opacity: 0.5; }
}

.session-timeout {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: var(--topbar-control-height);
  box-sizing: border-box;
  padding: 0 11px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  background: var(--panel);
  color: var(--text-muted);
  font-size: 12.5px;
  white-space: nowrap;
}
.session-timeout .mono { color: var(--text); }

.session-timeout[data-state="warn"] {
  border-color: color-mix(in srgb, var(--warning) 55%, transparent);
  color: var(--warning);
}

.session-timeout[data-state="warn"] .mono { color: var(--warning); }

.session-timeout[data-state="danger"],
.session-timeout[data-state="expired"] {
  border-color: color-mix(in srgb, var(--danger) 55%, transparent);
  color: var(--danger);
}

.session-timeout[data-state="danger"] .mono,
.session-timeout[data-state="expired"] .mono { color: var(--danger); }

.command-search {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 10px;
  height: var(--topbar-control-height);
}

.command-search svg { flex: none; color: var(--text-faint); }

/* The wrap is the visual bar: the help icon sits inside it (right of the
   input, before the border). flex:1 grows it to fill the space between
   the left topbar controls and the right-pinned .topbar-actions — no
   max-width cap, so the bar fills all available width at any viewport. */
.command-search-wrap {
  position: relative;
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  background: var(--bg-inset);
  color: var(--text-faint);
  transition: border-color 150ms ease, background 150ms ease;
}

.command-search-wrap:focus-within {
  border-color: var(--accent);
  background: var(--panel);
}

.command-search-help {
  flex: none;
  width: 28px;
  height: 26px;
  margin-right: 5px;
  border: 0;
  background: transparent;
  color: var(--text-faint);
}

.command-search-help:hover { background: var(--bg-hover); color: var(--text); border-color: transparent; }

/* Higher specificity than the generic form-field rule below (which styles
   input[type="search"]) so the topbar input stays a borderless flex child
   inside the .command-search-wrap bar. width:0 lets flex:1 cleanly grow
   the input to fill all available space (width:auto resolves to the
   browser's intrinsic default ~150px and fights flex sizing on focus). */
.command-search-wrap .command-search input {
  flex: 1;
  min-width: 0;
  width: 0;
  padding: 0;
  border: 0;
  outline: 0;
  background: transparent;
  color: var(--text);
  font-family: var(--font-body);
  font-size: 13px;
}

.command-search input::placeholder { color: var(--text-faint); }

/* The outer .command-search-wrap:focus-within glow is the single focus
   indicator; suppress the global input:focus ring inside the command search. */
.command-search input:focus { outline: none; box-shadow: none; }

.kbd-chip {
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--text-faint);
  border: 1px solid var(--border-strong);
  border-bottom-width: 2px;
  border-radius: 5px;
  padding: 1px 6px;
  background: var(--panel);
  white-space: nowrap;
}

/* ---------- live search typeahead ----------
   Grouped result rows rendered by GET /admin/search/live into the command
   palette's results group. Theme-aware (panel/border/accent tokens). */

.search-live-group + .search-live-group { border-top: 1px solid var(--border); margin-top: 6px; padding-top: 6px; }

.search-live-group-label {
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-faint);
  padding: 4px 8px;
}

.search-live-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 8px;
  border-radius: 6px;
  text-decoration: none;
  color: var(--text);
  cursor: pointer;
}

.search-live-item:hover,
.search-live-item.active { background: var(--bg-hover); }
.search-live-item.active { box-shadow: inset 2px 0 0 var(--accent); }

.search-live-type {
  flex: none;
  width: 22px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
}
.search-live-type-reg { color: var(--info); background: var(--info-tint); }
.search-live-type-domain { color: var(--accent); background: var(--danger-tint); }
.search-live-type-user { color: var(--success); background: var(--success-tint); }

.search-live-text { display: flex; flex-direction: column; min-width: 0; }
.search-live-label { font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.search-live-hint { font-size: 11.5px; color: var(--text-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.search-live-more {
  display: block;
  padding: 6px 8px;
  font-size: 12px;
  color: var(--accent);
  text-decoration: none;
}
.search-live-more:hover { text-decoration: underline; }

.search-live-empty { padding: 14px 10px; color: var(--text-faint); font-size: 13px; text-align: center; }

.topbar-actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 6px;
}

.icon-btn {
  display: inline-grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: var(--radius);
  border: 1px solid transparent;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  transition: background 150ms ease, color 150ms ease, transform 150ms ease, border-color 150ms ease;
}

.icon-btn:hover {
  background: var(--panel-2);
  color: var(--text);
  border-color: var(--border);
  transform: translateY(-1px);
}

/* ---------- Consolidated user menu (identity card + absorbed prefs) ----------
   ONE card button in the topbar (avatar + name + unread badge + chevron)
   opens a menu holding: identity header, notifications (the bell endpoints,
   lazy-loaded inline), language + theme segmented controls. Settings and
   sign out live in the icon-only topbar buttons BESIDE the card. Shared by
   the admin topbar and the portal topbar. */

/* Topbar icon-only actions (gear = user settings, exit = sign out) that sit
   BESIDE the user card. House icon-btn chrome, theme-aware hover/focus; the
   sign-out icon submits the hidden logout form (POST + CSRF on admin). */
.topbar-action-form { display: inline-flex; margin: 0; }
.topbar-action-btn {
  width: 36px;
  height: 36px;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--panel);
  color: var(--text-muted);
  display: inline-grid;
  place-items: center;
  cursor: pointer;
  transition: background 160ms var(--ease-out), color 160ms var(--ease-out),
    border-color 160ms var(--ease-out), transform 160ms var(--ease-out),
    box-shadow 160ms var(--ease-out);
}
.topbar-action-btn:hover {
  background: var(--panel-2);
  color: var(--text);
  border-color: var(--border-strong);
  transform: translateY(-1px);
  box-shadow: var(--shadow-sm);
}
.topbar-action-btn:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}
.topbar-action-btn.danger:hover {
  color: var(--danger);
  border-color: var(--danger-tint);
  background: var(--danger-tint);
}
/* Settings-dialog extras (restored modal + the 528-added mute block). */
.portal-prefs-dialog-body { padding-bottom: 6px; }

.user-menu { position: relative; }

.user-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 10px 4px 5px;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--panel);
  color: var(--text);
  cursor: pointer;
  font-family: var(--font-body);
  font-size: 13px;
  transition:
    border-color 150ms var(--ease-out),
    background 150ms var(--ease-out),
    box-shadow 150ms var(--ease-out);
}

.user-btn:hover { border-color: var(--border-strong); background: var(--panel-2); }
.user-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.user-menu.open .user-btn {
  border-color: var(--border-strong);
  background: var(--panel-2);
  box-shadow: var(--glow-accent-sm);
}

.user-avatar {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--accent-tint-strong);
  color: var(--accent);
  display: grid;
  place-items: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 12px;
  flex: none;
}

.user-avatar-lg {
  width: 36px;
  height: 36px;
  font-size: 15px;
}

.user-btn-name {
  font-weight: 600;
  max-width: 160px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.user-card-badge {
  position: absolute;
  top: -5px;
  right: -5px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--danger);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  line-height: 16px;
  text-align: center;
  pointer-events: none;
}

.user-chevron {
  color: var(--text-faint);
  transition: transform 200ms var(--ease-drawer);
}

.user-menu.open .user-chevron { transform: rotate(180deg); }

.user-dropdown {
  position: absolute;
  right: 0;
  top: calc(100% + 8px);
  width: min(372px, 92vw);
  background: var(--panel);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: 0;
  display: none;
  z-index: 70;
  transform-origin: top right;
}

.user-menu.open .user-dropdown {
  display: block;
  animation: user-menu-in 200ms var(--ease-drawer);
}

@keyframes user-menu-in {
  from { opacity: 0; transform: translateY(-6px) scale(0.98); }
  to { opacity: 1; transform: none; }
}

/* NO identity header in the flyout (v3): identity lives on the topbar card;
   the flyout is actions only. */

/* Menu action rows (Docs link, log off): icon + label, full-width hit area. */
.user-dropdown .dropdown-item {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  text-align: left;
  border: 0;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 12.5px;
  cursor: pointer;
  padding: 9px 14px;
  text-decoration: none;
}

.user-dropdown .dropdown-item svg { flex: 0 0 auto; color: var(--text-muted); }


.menu-divider {
  height: 1px;
  background: var(--border-subtle);
  margin: 6px 0;
}

/* Notifications inside the menu: the same rows the standalone bell served,
   now inline with a bounded scroll region (the global themed scrollbar). */
.user-notif { display: flex; flex-direction: column; }

.user-notif-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 10px 14px 6px;
}

.user-notif-head .panel-title { font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-faint); font-weight: 700; }

.user-notif-body {
  max-height: 264px;
  overflow-y: auto;
  min-height: 44px;
  border-block: 1px solid var(--border-subtle);
}

.user-notif .notif-row { padding: 9px 14px; }
.user-notif .notif-day-label { padding: 8px 14px 4px; }

.user-notif-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 8px 12px 12px;
}

/* Segmented controls (language EN/NL + theme Dark/Light). The language
   control reuses the .lang-switch form class so lang-switch.js's cookie
   mirror + stale-variant purge keep firing verbatim. */
.menu-segs {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 8px 14px;
}

.menu-seg-block { display: flex; flex-direction: column; gap: 6px; }

.menu-seg-label {
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-faint);
}

.menu-seg {
  display: flex;
  width: 100%;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--bg-inset);
}

.menu-seg > button {
  flex: 1 1 0;
  border: 0;
  background: transparent;
  color: var(--text-muted);
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.05em;
  padding: 6px 10px;
  cursor: pointer;
  transition: background 140ms var(--ease-out), color 140ms var(--ease-out);
}

.menu-seg > button:hover { background: var(--bg-hover); color: var(--text); }
.menu-seg > button.active { background: var(--accent-tint); color: var(--accent); }
.menu-seg > button:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.user-dropdown .lang-switch { border: 0; overflow: visible; display: flex; }
.user-dropdown .lang-switch .lang-opt { border: 1px solid var(--border); }
.user-dropdown .lang-switch .lang-opt:first-child { border-radius: var(--radius-sm) 0 0 var(--radius-sm); }
.user-dropdown .lang-switch .lang-opt:last-child { border-radius: 0 var(--radius-sm) var(--radius-sm) 0; border-left: 0; }
.user-dropdown .lang-globe { display: none; }

.theme-switch { display: flex; }

.user-dropdown form { margin: 0; }
.user-dropdown .menu-logout { display: block; }
.user-dropdown .dropdown-item:hover { background: var(--bg-hover); }
.user-dropdown .dropdown-item.danger { color: var(--danger); }
.user-dropdown .dropdown-item.danger:hover { background: var(--danger-tint); }
.user-dropdown .menu-logout .dropdown-item { border-radius: 0 0 var(--radius-lg) var(--radius-lg); }

/* In-flyout settings panel (v4): the Settings row slides the flyout body
   from the main rows to the per-user settings fields (house easing); Back
   returns to the main rows. Same interaction grammar as the drawer. */
.user-dropdown { overflow: hidden; }
.user-dropdown .menu-settings-panel { display: none; }
.user-dropdown[data-view="settings"] .menu-main { display: none; }
.user-dropdown[data-view="settings"] .menu-settings-panel {
  display: block;
  animation: menu-settings-in 200ms var(--ease-drawer);
}
@keyframes menu-settings-in {
  from { opacity: 0; transform: translateX(24px); }
  to { opacity: 1; transform: none; }
}
.menu-settings-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border-subtle);
}
.menu-settings-back {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
}
.menu-settings-back:hover { background: var(--bg-hover); color: var(--text); }
.menu-settings-title {
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
  font-weight: 700;
}
.menu-settings-body {
  padding: 12px 14px 14px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  max-height: 62vh;
  overflow-y: auto;
}
.menu-settings-section { display: flex; flex-direction: column; gap: 6px; }
.menu-settings-section .form-hint { margin: 0; }
.menu-settings .dropdown-item { border-radius: var(--radius-sm); }


.user-dropdown :is(a, button, [data-menu-item]):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

/* The per-user settings page reuses the segmented controls in a wider
   layout (no card constraint). */
.profile-segs { flex-direction: row; flex-wrap: wrap; gap: 24px; }
.profile-segs .menu-seg { max-width: 240px; }
.profile-segs .menu-seg-block { min-width: 200px; }

@media (max-width: 980px) {
  /* The anchored dropdown becomes a near-full-width sheet under the topbar
     (mirrors the notification panel's mobile treatment). */
  .user-dropdown {
    position: fixed;
    top: 56px;
    left: 8px;
    right: 8px;
    width: auto;
  }
}

@media (prefers-reduced-motion: reduce) {
  .user-dropdown { animation: none; }
  .user-chevron { transition: none; }
  .menu-seg > button { transition: none; }
}

/* ---------- panels & layout ---------- */

.panel {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}

.panel + .panel { margin-top: 20px; }

.panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
  flex-wrap: wrap;
}

.panel-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.panel-title {
  font-size: 14px;
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: 8px;
}

.count-chip {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-muted);
  background: var(--panel-2);
  border-radius: 999px;
  padding: 1px 8px;
}

.panel-body { padding: 18px; }
.panel-body.flush { padding: 0; }

/* Email template preview: the full branded HTML document (its own background,
   600px content width) is rendered in a sandboxed iframe so its inline styles
   display faithfully without leaking into the admin chrome. */
.email-template-frame {
  display: block;
  width: 100%;
  height: 720px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: #f4f4f5;
}
.email-template-subject {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-muted);
  max-width: 60%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.grid-2 {
  display: grid;
  grid-template-columns: 1.4fr 1fr;
  gap: 18px;
  align-items: start;
}

/* ---------- stat tiles ---------- */

.stat-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 14px;
  margin-bottom: 22px;
}

.stat-tile {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 16px 18px 14px;
  position: relative;
  overflow: hidden;
  display: block;
  color: var(--text);
  transition: transform 160ms ease, border-color 160ms ease, box-shadow 160ms ease;
}

.stat-tile::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 3px;
  background: var(--tile-accent, var(--border-strong));
}

.stat-tile:hover {
  transform: translateY(-2px);
  border-color: var(--border-strong);
  box-shadow: var(--shadow-md);
  color: var(--text);
}

.stat-value {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 2.4rem;
  line-height: 1.05;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}

.stat-label {
  margin-top: 6px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.tone-success { --tile-accent: var(--success); }
.tone-warning { --tile-accent: var(--warning); }
.tone-danger { --tile-accent: var(--danger); }
.tone-info { --tile-accent: var(--info); }
.tone-brand { --tile-accent: var(--accent); }
.tone-muted { --tile-accent: var(--text-faint); }

/* ---------- dashboard quick actions ---------- */

.quick-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.quick-actions .btn:hover { color: var(--text); }
.quick-actions .btn-primary:hover { color: var(--accent-text); }
.quick-actions .btn-danger:hover { color: var(--danger); }
.quick-actions .btn-success:hover { color: var(--success); }

/* ---------- stats bars ---------- */

.bar-row {
  display: grid;
  grid-template-columns: 110px 1fr 44px;
  align-items: center;
  gap: 12px;
  padding: 5px 0;
  font-size: 13px;
}

.bar-row .bar-label { color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bar-row .bar-count { text-align: right; font-family: var(--font-mono); font-size: 12.5px; }

.bar-track {
  background: var(--bg-inset);
  border-radius: 999px;
  height: 10px;
  overflow: hidden;
}

.bar-fill {
  height: 100%;
  border-radius: 999px;
  background: var(--accent);
  min-width: 2px;
}

.bar-fill.fill-success { background: var(--success); }
.bar-fill.fill-warning { background: var(--warning); }
.bar-fill.fill-danger { background: var(--danger); }
.bar-fill.fill-info { background: var(--info); }
.bar-fill.fill-muted { background: var(--text-faint); }
.fill-success { background: var(--success); }
.fill-warning { background: var(--warning); }
.fill-danger { background: var(--danger); }
.fill-info { background: var(--info); }
.fill-muted { background: var(--text-faint); }

/* ---------- tables ---------- */

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

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

.table th {
  text-align: left;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

.table td {
  padding: 11px 14px;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}

.table tbody tr { transition: background 140ms ease; }
.table tbody tr:hover { background: var(--panel-2); }
.table tbody tr:last-child td { border-bottom: 0; }

.table .cell-main { font-weight: 500; }
.table .cell-muted { color: var(--text-muted); }
.table .cell-mono { font-family: var(--font-mono); font-size: 12.5px; }
.table .cell-actions { white-space: nowrap; text-align: right; }
.table .cell-ua { max-width: 280px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

tr.row-flash { animation: row-flash 1.4s ease-out 1; }

@keyframes row-flash {
  0% { background: var(--accent-tint-strong); }
  100% { background: transparent; }
}

.table-toolbar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  flex-wrap: wrap;
}

.table-toolbar .spacer { flex: 1; }

.toolbar-check {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12.5px;
  color: var(--text-muted);
  white-space: nowrap;
  cursor: pointer;
}

.field-inline {
  font-size: 12px;
  color: var(--text-muted);
  white-space: nowrap;
}
.export-toolbar { border-top: 1px solid var(--border); }
.export-toolbar .export-label { font-size: 12.5px; color: var(--text-muted); }
.export-toolbar .export-sep { color: var(--text-muted); }
.export-toolbar input[type="date"] { width: auto; }

.cell-check { width: 32px; text-align: center; }
.table th.cell-check, .table td.cell-check { padding-left: 14px; padding-right: 4px; }
.table input[type="checkbox"] { accent-color: var(--accent); width: 15px; height: 15px; cursor: pointer; }

.bulk-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px;
  border-bottom: 1px solid var(--border);
  background: var(--panel-2);
}
.bulk-bar[hidden] { display: none; }
.bulk-bar [data-bulk-count] { font-size: 12px; color: var(--text-muted); margin-right: auto; }

/* ---------- badges ---------- */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 2.5px 10px;
  border-radius: 999px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
  white-space: nowrap;
}

.badge::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}

.badge-success { background: var(--success-tint); color: var(--success); }
.badge-warning { background: var(--warning-tint); color: var(--warning); }
.badge-danger { background: var(--danger-tint); color: var(--danger); }
.badge-info { background: var(--info-tint); color: var(--info); }
.badge-neutral { background: var(--neutral-tint); color: var(--text-muted); }

.badge-pulse::before { animation: badge-blink 1.4s ease-in-out infinite; }

@keyframes badge-blink {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.25; }
}

/* ---------- tag chips ---------- */

.tag-chips {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 5px;
}

.tag-chip {
  display: inline-flex;
  align-items: center;
  padding: 1.5px 9px;
  border-radius: 999px;
  background: var(--neutral-tint);
  color: var(--text-muted);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.02em;
  white-space: nowrap;
  text-decoration: none;
}

a.tag-chip:hover {
  color: var(--text);
}

/* ---------- buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 7px 14px;
  border-radius: var(--radius);
  border: 1px solid var(--border-strong);
  background: var(--panel-2);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  transition: background 150ms ease, border-color 150ms ease, transform 150ms ease, box-shadow 150ms ease;
}

.btn:hover { transform: translateY(-1px); box-shadow: var(--shadow-sm); border-color: var(--text-faint); }
.btn:active { transform: translateY(0); }
.btn:disabled { opacity: 0.55; cursor: not-allowed; transform: none; box-shadow: none; }

.btn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-text);
}
.btn-primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); box-shadow: var(--glow-accent-sm); }
.btn-primary:focus-visible { box-shadow: var(--glow-accent-md); }

/* Language switch + theme toggle float top-right on the full-bleed public
   pages (no topbar). The toggle pairs visually with the lang-switch box. */
.public-lang { position: fixed; top: 14px; right: 16px; z-index: 30; display: flex; align-items: center; gap: 8px; }

.public-lang .theme-toggle { background: var(--panel); border-color: var(--border); }

.btn-danger {
  background: var(--danger-tint);
  border-color: color-mix(in srgb, var(--danger) 45%, transparent);
  color: var(--danger);
}

.btn-danger:hover { background: color-mix(in srgb, var(--danger) 22%, transparent); border-color: var(--danger); }

.btn-success {
  background: var(--success-tint);
  border-color: color-mix(in srgb, var(--success) 45%, transparent);
  color: var(--success);
}

.btn-success:hover { background: color-mix(in srgb, var(--success) 22%, transparent); border-color: var(--success); }

.btn-sm { padding: 4px 10px; font-size: 12px; border-radius: var(--radius-sm); }
.btn-ghost { background: transparent; border-color: transparent; }
.btn-ghost:hover { background: var(--panel-2); border-color: var(--border); }

/* ---------- forms ---------- */

.form-field { display: flex; flex-direction: column; gap: 5px; margin-bottom: 14px; }

.form-field label, .form-label {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-muted);
  letter-spacing: 0.02em;
}

.form-field .hint { font-size: 11.5px; color: var(--text-faint); }

/* Consent checkbox on the public register form: label wraps the input so the
   whole line is clickable; the inline link opens the /terms page. */
.form-check label {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
  letter-spacing: 0;
  cursor: pointer;
  line-height: 1.45;
}
.form-check input[type="checkbox"] {
  accent-color: var(--accent);
  width: 16px;
  height: 16px;
  margin-top: 2px;
  flex: 0 0 auto;
  cursor: pointer;
}
.form-check a { color: var(--accent); }

.code-block {
  margin: 0.75rem 0 0;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-inset);
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.5;
  overflow-x: auto;
  white-space: pre;
}

.input, .select, input[type="text"], input[type="email"], input[type="password"], input[type="search"], input[type="date"], select, textarea {
  width: 100%;
  padding: 8px 11px;
  border-radius: var(--radius);
  border: 1px solid var(--border-strong);
  background: var(--bg-inset);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 13.5px;
  transition: border-color 150ms ease, box-shadow 150ms ease;
}

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

.input.mono, input.mono { font-family: var(--font-mono); font-size: 12.5px; }

select { appearance: auto; }

.form-error {
  font-size: 12px;
  color: var(--danger);
  display: flex;
  align-items: center;
  gap: 5px;
}

.domain-hint { font-size: 12px; display: flex; align-items: center; gap: 5px; }
.domain-hint[hidden] { display: none; }
.domain-hint[data-state="ok"] { color: var(--success); }
.domain-hint[data-state="bad"] { color: var(--danger); }
.domain-hint[data-state="new"] { color: var(--info); }

.password-meter { display: flex; align-items: center; gap: 8px; margin-top: 6px; }
.password-meter-track {
  flex: 1;
  height: 6px;
  border-radius: 3px;
  background: var(--border);
  overflow: hidden;
}
.password-meter-fill { height: 100%; width: 0; border-radius: 3px; transition: width 0.15s ease; }
.password-meter-label { font-size: 11.5px; font-weight: 600; min-width: 44px; text-align: right; }
.password-meter-message { font-size: 11.5px; color: var(--danger); }
.password-meter[data-state="weak"] .password-meter-fill,
.password-meter[data-state="weak"] .password-meter-label { background: var(--danger); color: var(--danger); }
.password-meter[data-state="fair"] .password-meter-fill,
.password-meter[data-state="fair"] .password-meter-label { background: var(--warning); color: var(--warning); }
.password-meter[data-state="good"] .password-meter-fill,
.password-meter[data-state="good"] .password-meter-label { background: var(--info); color: var(--info); }
.password-meter[data-state="strong"] .password-meter-fill,
.password-meter[data-state="strong"] .password-meter-label { background: var(--success); color: var(--success); }
.password-meter[data-state="invalid"] .password-meter-fill,
.password-meter[data-state="invalid"] .password-meter-label { background: var(--danger); color: var(--danger); }


/* Instance Email/SMTP editor (instance flyout): the inline fields wrap
   cleanly without cramping — each field keeps a comfortable minimum width
   and the full-width checkbox row + right-aligned save button sit on their
   own lines at 1280-1440px and below. */
.smtp-form { align-items: flex-end; row-gap: 12px; }
.smtp-form > .form-field { flex: 1 1 180px; min-width: 150px; margin: 0; }
.smtp-form > .form-field input { width: 100%; }
.smtp-form > .btn { align-self: flex-end; flex: none; }
.form-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 14px;
}

.inline-form { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.inline-form .input, .inline-form input { width: auto; flex: 1; min-width: 140px; }
.inline-form input[type="checkbox"] { width: auto; flex: 0 0 auto; min-width: 0; }

.checkbox-group { display: flex; flex-direction: column; gap: 6px; border: 0; padding: 0; margin: 0; }
.checkbox-group legend { font-size: 12px; font-weight: 600; color: var(--text-muted); letter-spacing: 0.02em; padding: 0; margin-bottom: 2px; }
.checkbox-inline { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 500; color: var(--text); margin-right: 12px; }

/* ---------- banners ---------- */

.banner {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 11px 14px;
  border-radius: var(--radius);
  border: 1px solid;
  font-size: 13px;
  margin-bottom: 16px;
  animation: banner-in 220ms ease-out;
}

@keyframes banner-in {
  from { opacity: 0; transform: translateY(-6px); }
  to { opacity: 1; transform: translateY(0); }
}

.banner svg { flex: none; margin-top: 1px; }

.banner-success { background: var(--success-tint); border-color: color-mix(in srgb, var(--success) 40%, transparent); color: var(--success); }
.banner-error { background: var(--danger-tint); border-color: color-mix(in srgb, var(--danger) 40%, transparent); color: var(--danger); }
.banner-warning { background: var(--warning-tint); border-color: color-mix(in srgb, var(--warning) 40%, transparent); color: var(--warning); }
.banner-info { background: var(--info-tint); border-color: color-mix(in srgb, var(--info) 40%, transparent); color: var(--info); }

.banner-row td { padding: 8px 14px 0 !important; border-bottom: 0 !important; }
.banner-row .banner { margin-bottom: 0; }

.session-toast {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 90;
  display: flex;
  align-items: center;
  gap: 10px;
  max-width: 420px;
  padding: 12px 16px;
  border: 1px solid color-mix(in srgb, var(--warning) 45%, transparent);
  border-radius: var(--radius);
  background: var(--panel);
  box-shadow: var(--shadow-md);
  color: var(--text);
  font-size: 13.5px;
}

/* The base rule above sets display:flex, which overrides the UA [hidden]{display:none};
   this higher-specificity rule restores hidden semantics so the empty toast never renders. */
.session-toast[hidden] { display: none; }

.session-toast > svg { color: var(--warning); flex: none; }

.session-toast-action {
  flex: none;
  color: var(--accent);
  font-weight: 600;
  text-decoration: none;
}

.session-toast-action:hover { text-decoration: underline; }

.announcement-banner {
  margin: 0;
  border-radius: 0;
  border-width: 0 0 1px;
  justify-content: center;
  text-align: center;
  font-weight: 500;
}

/* Public-page support/contact footer. Rendered only when SUPPORT_EMAIL or
   SUPPORT_URL is configured (see public_base.html). Fixed to the viewport
   bottom so it overlays the full-bleed .public-shell without disturbing its
   grid layout. */
.public-contact {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 5;
  padding: 8px 16px;
  text-align: center;
  font-size: 12.5px;
  color: var(--text-muted);
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: blur(6px);
  border-top: 1px solid var(--border);
}

.public-contact a { color: var(--accent); text-decoration: none; }
.public-contact a:hover { text-decoration: underline; }

/* ---------- 14. Cookie consent (public pages) ----------
   A non-modal bottom strip + a native <dialog> preferences panel, styled on
   the shared tokens so both themes match the public design language. The
   banner is position:fixed (never pushes the form — no layout shift) and is
   revealed by cookie-consent.js only when a fresh decision is needed. */
.consent-banner {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  padding: 14px 22px;
  background: color-mix(in srgb, var(--panel) 94%, transparent);
  backdrop-filter: blur(8px);
  border-top: 1px solid var(--border-strong);
  box-shadow: var(--shadow-lg);
  animation: esr-consent-rise 260ms var(--ease-out) both;
}
/* `display:flex` on the banner/dialog overrides the UA [hidden] rule (same
   sharp edge as .banner elsewhere) — restore hidden semantics explicitly. */
.consent-banner[hidden] { display: none; }
.consent-dialog:not([open]) { display: none; }

@keyframes esr-consent-rise {
  from { transform: translateY(12px); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}

.consent-banner-text { min-width: 0; }
.consent-banner-title { display: block; font-size: 13.5px; font-weight: 600; margin-bottom: 2px; }
.consent-banner-text p { margin: 0; font-size: 12.5px; color: var(--text-muted); max-width: 640px; }

.consent-banner-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  justify-content: flex-end;
}
.consent-policy-link {
  font-size: 12.5px;
  color: var(--accent);
  text-decoration: none;
  white-space: nowrap;
}
.consent-policy-link:hover { text-decoration: underline; }

/* The persistent "Cookie settings" affordance — a quiet chip bottom-right,
   hidden while the banner is pending a first decision (body.consent-pending,
   toggled by cookie-consent.js) so the two affordances never stack. */
.consent-footer-btn {
  position: fixed;
  right: 14px;
  bottom: 12px;
  z-index: 55;
  display: inline-grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: var(--radius);
  border: 1px solid transparent;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  transition: background 150ms ease, color 150ms ease, transform 150ms ease, border-color 150ms ease;
}
.consent-footer-btn:hover {
  background: var(--panel-2);
  color: var(--text);
  border-color: var(--border);
  transform: translateY(-1px);
}
body.consent-pending .consent-footer-btn { display: none; }
/* Keep the chip above the fixed public-contact support line when present. */
body:has(.public-contact) .consent-footer-btn { bottom: 44px; }

/* Preferences dialog — native <dialog>, styled like the other modals
   (accent top border, panel surface, blurred backdrop). */
.consent-dialog {
  border: 1px solid var(--border-strong);
  border-top: 3px solid var(--accent);
  border-radius: var(--radius-lg);
  background: var(--panel);
  color: var(--text);
  width: min(560px, calc(100vw - 32px));
  max-height: calc(100vh - 64px);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding: 20px 22px;
  box-shadow: var(--shadow-lg);
}
.consent-dialog-scroll { overflow-y: auto; min-height: 0; padding-right: 4px; }
.consent-dialog::backdrop {
  background: rgba(4, 6, 10, 0.6);
  backdrop-filter: blur(2px);
}
.consent-dialog-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.consent-dialog-head h2 { margin: 0; font-size: 16px; font-weight: 700; letter-spacing: -0.01em; }
.consent-dialog-lead { margin: 8px 0 14px; font-size: 13px; color: var(--text-muted); }

.consent-categories { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.consent-category {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-inset);
  padding: 12px 14px;
}
.consent-category-head { display: flex; align-items: center; gap: 10px; }
.consent-category-name { font-size: 13.5px; font-weight: 600; }
.consent-always { margin-left: auto; }
.consent-toggle { margin-right: 0; }
.consent-category-desc { margin: 6px 0 0; font-size: 12.5px; color: var(--text-muted); }

.consent-policy-note { margin: 14px 0 0; font-size: 12.5px; color: var(--text-faint); }
.consent-policy-note a { color: var(--accent); text-decoration: none; }
.consent-policy-note a:hover { text-decoration: underline; }
/* Inventory of first-party cookies/browser storage (dialog + terms table). */
.consent-inventory { margin: 14px 0 0; font-size: 12.5px; }
.consent-inventory summary {
  cursor: pointer;
  font-weight: 600;
  color: var(--text-muted);
  padding: 4px 0;
}
.consent-inventory summary:hover { color: var(--text); }
.consent-inventory-table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 8px;
  font-size: 12.5px;
}
.consent-inventory-table th,
.consent-inventory-table td {
  text-align: left;
  vertical-align: top;
  padding: 8px 10px;
  border-top: 1px solid var(--border);
}
.consent-inventory-table thead th {
  border-top: 0;
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-faint);
}
.consent-inventory-table tbody th { font-weight: 600; white-space: nowrap; }
.consent-inventory-table td { color: var(--text-muted); }

.terms-cookie-list .consent-inventory-table { margin: 10px 0 20px; }

.consent-dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 16px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
  background: var(--panel);
  flex: none;
}

@media (max-width: 720px) {
  .consent-banner { flex-direction: column; align-items: stretch; gap: 10px; padding: 12px 16px; }
  .consent-banner-actions { justify-content: stretch; }
  .consent-banner-actions .btn { flex: 1 1 auto; }
  body:has(.public-contact) .consent-footer-btn { bottom: 44px; }
}

/* Cookie consent settings panel: category summary list + version row. */
.settings-consent-categories { list-style: none; margin: 6px 0 0; padding: 0; font-size: 12.5px; color: var(--text-muted); }
.settings-consent-categories li { padding: 3px 0; }
.settings-consent-version {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}

/* ---------- empty states ---------- */

.empty-state {
  padding: 44px 20px;
  text-align: center;
  color: var(--text-muted);
}

.empty-state .empty-icon {
  width: 44px;
  height: 44px;
  margin: 0 auto 12px;
  border-radius: 50%;
  background: var(--panel-2);
  display: grid;
  place-items: center;
  color: var(--text-faint);
}

.empty-state .empty-title { font-family: var(--font-display); font-weight: 600; color: var(--text); margin-bottom: 4px; }
.empty-state .empty-sub { font-size: 12.5px; max-width: 380px; margin: 0 auto; }

/* ---------- pagination ---------- */

.pagination {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 16px;
  border-top: 1px solid var(--border);
  font-size: 12.5px;
  color: var(--text-muted);
}

.pagination .pager { display: flex; gap: 6px; }

/* ---------- timeline ---------- */

.timeline { list-style: none; margin: 0; padding: 4px 0; }

.timeline li {
  position: relative;
  padding: 0 0 18px 26px;
}

.timeline li::before {
  content: "";
  position: absolute;
  left: 5px;
  top: 16px;
  bottom: -2px;
  width: 1px;
  background: var(--border-strong);
}

.timeline li:last-child::before { display: none; }

.timeline li::after {
  content: "";
  position: absolute;
  left: 0;
  top: 5px;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--panel);
  border: 2px solid var(--accent);
}

.timeline .tl-label { font-weight: 500; }
.timeline .tl-note { color: var(--text-muted); font-size: 12.5px; }
.timeline .tl-time { font-family: var(--font-mono); font-size: 11.5px; color: var(--text-faint); }

/* Timeline marker tones (shared `timeline(events)` macro). */
.timeline li.tl-success::after { border-color: var(--success); }
.timeline li.tl-warning::after { border-color: var(--warning); }
.timeline li.tl-danger::after { border-color: var(--danger); }
.timeline li.tl-info::after { border-color: var(--info); }

/* ---------- audit feed ---------- */

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

.feed li {
  display: flex;
  gap: 10px;
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
  font-size: 12.5px;
}

.feed li:last-child { border-bottom: 0; }

.feed .feed-action {
  font-family: var(--font-mono);
  font-size: 11px;
  padding: 1px 7px;
  border-radius: 5px;
  background: var(--panel-2);
  color: var(--text-muted);
  height: fit-content;
  white-space: nowrap;
}

.feed .feed-body { min-width: 0; }
.feed .feed-meta { color: var(--text-faint); font-family: var(--font-mono); font-size: 11px; margin-top: 2px; }

/* Scrollable activity log (shared `activity_log(scrollable=true)` macro). */
.feed-scroll { max-height: 320px; overflow-y: auto; padding-right: 4px; }

/* ---------- app page shell + tab bar (app-consolidation foundation) ----------
   Shared `app_shell` / `app_tabs` macros: a page header over an in-page tab bar
   that switches sub-views of one consolidated app. Reuses page-title/page-sub. */
.app-page { display: flex; flex-direction: column; gap: 16px; }
.app-page-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.app-page-actions { display: flex; align-items: center; gap: 8px; flex: none; }

.tab-bar {
  display: flex;
  align-items: center;
  gap: 2px;
  border-bottom: 1px solid var(--border);
  overflow-x: auto;
}
.tab {
  appearance: none;
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  color: var(--text-muted);
  font: inherit;
  font-size: 13px;
  font-weight: 500;
  padding: 9px 14px;
  margin-bottom: -1px;
  cursor: pointer;
  white-space: nowrap;
  text-decoration: none;
  transition: color 120ms var(--ease-out, ease), border-color 120ms var(--ease-out, ease);
}
.tab:hover { color: var(--text); }
.tab.active { color: var(--text); border-bottom-color: var(--accent); }
.tab:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: 4px 4px 0 0; }
/* Tab content wrapper (shared `_app_page.html` shell): a flex child of
   `.app-page`, so min-width:0 keeps wide data-tables from overflowing. */
.app-tab-content { min-width: 0; }

.note-history { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--border); }
.note-history-title { font-size: 12px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); margin-bottom: 6px; }
.note-history-value { font-size: 13px; margin-top: 2px; }

/* ---------- settings ---------- */

.settings-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 20px;
  align-items: start;
}

.kv { margin: 0; }

.kv div {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
}

/* Editable settings forms: dense 2-3 column field grid + right-aligned save. */
.settings-form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 14px 18px;
  margin-bottom: 12px;
}
.settings-form-grid .form-field { margin: 0; }
.settings-form-grid .form-field-wide { grid-column: 1 / -1; }
.settings-form label.checkbox-inline { margin: 4px 0; }
.settings-form-actions { display: flex; justify-content: flex-end; margin-top: 12px; }

.kv div:last-child { border-bottom: 0; }
.kv dt { color: var(--text-muted); }
.kv dd { margin: 0; font-family: var(--font-mono); font-size: 12px; text-align: right; word-break: break-all; }

.config-ok { color: var(--success); }
.config-bad { color: var(--danger); }
/* Redesigned settings page: sticky in-page nav on the left, uniformly styled
   section cards in a single content column on the right. */
.settings-layout {
  display: grid;
  grid-template-columns: 200px minmax(0, 1fr);
  gap: 20px;
  align-items: start;
}
.settings-nav {
  position: sticky;
  top: 72px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--panel);
}
.settings-nav-title {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
  padding: 4px 8px 8px;
}
.settings-nav a {
  color: var(--text-muted);
  text-decoration: none;
  font-size: 13px;
  padding: 6px 8px;
  border-radius: 6px;
  border-left: 2px solid transparent;
}
.settings-nav a:hover { color: var(--text); background: var(--bg-hover); }
.settings-content { display: flex; flex-direction: column; gap: 18px; min-width: 0; }
.settings-content .panel { margin: 0; }
.settings-content .panel-header { padding: 12px 16px; }
.settings-content .panel-body + .panel-body { border-top: 1px solid var(--border); }

/* Email template manager: card actions row + the toggled editor form. */
.email-template-card .email-template-subject { margin: 0 0 10px; font-size: 12.5px; color: var(--text-muted); word-break: break-word; }
.email-template-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; }
.email-template-inline { margin: 0; }
.email-template-edit-form { display: none; flex-direction: column; gap: 10px; margin-top: 8px; align-items: stretch; }
.email-template-edit-form.open { display: flex; }
.email-template-edit-form .form-field { margin: 0; }
.email-template-edit-form textarea { width: 100%; resize: vertical; min-height: 180px; font-size: 12px; line-height: 1.5; }
.email-template-edit-actions { display: flex; justify-content: flex-end; }

/* ---------- detail page ---------- */

.detail-grid {
  display: grid;
  grid-template-columns: 1.5fr 1fr;
  gap: 18px;
  align-items: start;
}

.detail-fields {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px 20px;
}

.detail-field .df-label {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: 3px;
}

.detail-field .df-value { font-size: 13.5px; word-break: break-word; }
.detail-field .df-value.mono { font-family: var(--font-mono); font-size: 12.5px; }

.action-bar {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
}

/* ---------- reject inline form ---------- */

.reject-form {
  display: none;
  gap: 6px;
  margin-top: 6px;
}

.reject-form.open { display: flex; }
.reject-form input { flex: 1; min-width: 120px; }

/* The canned-reason dropdown keeps its natural width; only the free-text
   reason field stretches to fill the reject form. */
.reject-form select.reject-reason-select { flex: 0 0 auto; max-width: 220px; }

/* Domain VFS and API-token rename edit rows reuse .reject-form; the form
   sits alone in its table row, so it needs no top margin (unlike the reject
   form, which follows an inline button). */
.domain-edit-form,
.token-edit-form { margin-top: 0; }

/* The registration detail danger zone: a bordered block holding the
   type-to-confirm delete form. The form reuses .reject-form's show/hide
   toggle; it stacks vertically and the confirm button stays disabled until
   the typed email matches (app.js). */
.danger-zone { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border); }
.delete-form { margin-top: 6px; flex-direction: column; align-items: stretch; gap: 8px; max-width: 520px; }
.delete-form-hint { margin: 0; font-size: 12.5px; color: var(--danger); }
.delete-form label { font-size: 12.5px; color: var(--text-muted); }
.delete-form input[type=text] { flex: none; width: 100%; }
.delete-form .form-check { margin-top: 2px; }
.delete-form .form-check label { display: flex; align-items: flex-start; gap: 8px; color: var(--text); }
.delete-form-actions { display: flex; gap: 6px; }

/* Webhook edit row reuses .reject-form; the URL input and the events
   checkbox group sit side by side and wrap on narrow viewports. */
.webhook-edit-form { margin-top: 0; flex-wrap: wrap; align-items: flex-start; }
.webhook-edit-form > input[type=text] { flex: 1 1 260px; }
.webhook-edit-events { flex: 2 1 320px; flex-direction: row; flex-wrap: wrap; align-items: center; }
.webhook-edit-events legend { flex-basis: 100%; }
.webhook-edit-domains { flex: 1 1 260px; margin-bottom: 0; }

/* Domain notes row also reuses .reject-form; the textarea needs a little
   height and the action buttons sit on their own line beneath it. */
.domain-notes-form { margin-top: 0; flex-direction: column; align-items: stretch; }
.domain-notes-form textarea { width: 100%; resize: vertical; min-height: 64px; }
.domain-notes-actions { display: flex; gap: 6px; }

/* Domain provisioning policy form: a multi-fieldset form with a responsive
   grid of labeled inputs. Each fieldset groups related fields (security,
   quotas, lifecycle, UX) and the grid wraps on narrow screens. */
.domain-policy-form { margin-top: 0; flex-direction: column; align-items: stretch; gap: 12px; }
.policy-fieldset {
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 10px 12px;
  margin: 0;
}
.policy-fieldset legend {
  font-weight: 600;
  font-size: 12.5px;
  color: var(--text-muted);
  padding: 0 6px;
}
.policy-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 10px;
  margin-top: 8px;
}
.policy-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.policy-field--wide { grid-column: 1 / -1; }
.policy-field > span {
  font-size: 12px;
  font-weight: 500;
  color: var(--text-muted);
}
.policy-field input[type=text],
.policy-field input[type=number],
.policy-field textarea {
  width: 100%;
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: 3px;
  background: var(--bg-inset);
  color: var(--text);
  font-size: 13px;
}
.policy-field textarea { resize: vertical; min-height: 48px; }
.policy-field .hint {
  font-size: 11px;
  color: var(--text-faint);
  line-height: 1.3;
}
.policy-field--check {
  flex-direction: row;
  align-items: center;
  gap: 8px;
}
.policy-field--check input[type=checkbox] {
  width: 16px;
  height: 16px;
  cursor: pointer;
}
.policy-field--check > span {
  font-size: 13px;
  font-weight: 400;
  color: var(--text);
  cursor: pointer;
}

/* Domain template edit row reuses .reject-form; the name/group/vfs inputs,
   the notes textarea, and the action buttons wrap across the wide row. */
.domain-template-edit-form { margin-top: 0; flex-wrap: wrap; align-items: flex-start; }
.domain-template-edit-form > input[type=text] { flex: 1 1 180px; }
.domain-template-edit-form > textarea { flex: 1 1 100%; resize: vertical; min-height: 48px; }
/* Domain ownership-verification hint row: a read-only DNS TXT record the
   operator publishes to prove they control the domain. The token itself is
   shown only once (at creation); this standing hint uses a <token> placeholder. */
.domain-verify-hint {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 8px 0;
  font-size: 12.5px;
}
.domain-verify-label { color: var(--text-muted); white-space: nowrap; }
.domain-verify-record {
  padding: 2px 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-inset);
  color: var(--text);
  word-break: break-all;
}
/* Domain provisioning preview row: a read-only summary of the three-layer
   CrushFTP model (group template / group root user / per-user VFS) the service
   will create for the domain, resolved from its vfs_base_path + group. Toggled
   via .reject-form (hidden until the Preview button opens it). */
.domain-preview { padding: 8px 0; font-size: 12.5px; }
.domain-preview-title { color: var(--text-muted); margin-bottom: 8px; }
.domain-preview-grid {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 6px 16px;
  margin: 0;
}
.domain-preview-grid dt { color: var(--text-muted); white-space: nowrap; }
.domain-preview-grid dd { margin: 0; }
.domain-preview-grid code {
  padding: 1px 6px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-inset);
  color: var(--text);
  word-break: break-all;
}

/* Add-organization form: the common case (name + first email domain) stays
   visible; the provisioning defaults collapse into a native disclosure. */
.org-advanced { flex-basis: 100%; border: 0; margin: 0; }
.org-advanced > summary {
  cursor: pointer;
  color: var(--text-muted);
  font-size: 12px;
  user-select: none;
  padding: 2px 0;
}
.org-advanced > summary:hover { color: var(--text); }
.org-advanced-fields {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 8px;
}

/* Organization flyout: child email-domain rows (name / verification /
   created / per-domain actions) + the inline add-domain form. Actions
   refresh the whole flyout body (hx-target [data-flyout-body]). */
.org-domain-rows { display: flex; flex-direction: column; gap: 6px; margin: 0 0 10px; }
.org-domain-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-inset);
}
.org-domain-row .mono { word-break: break-all; }
.org-domain-meta { color: var(--text-muted); font-size: 11.5px; }
.org-domain-actions { display: flex; gap: 4px; margin-left: auto; flex-wrap: wrap; }
.org-domain-add { display: flex; align-items: flex-end; gap: 8px; flex-wrap: wrap; }
.org-domain-add .form-field { margin: 0; flex: 1; min-width: 180px; }
/* Robot / service-account rows in the org flyout: like org-domain rows but
   the name + badges + meta + actions wrap onto two lines, and the inline
   edit/keys/delete forms (.reject-form, div-based) stack their fields. */
.org-domain-row.robot-row { flex-wrap: wrap; }
.robot-edit-row { flex-direction: column; align-items: stretch; }
.robot-edit-row .form-field { width: 100%; }
.robot-edit-row textarea { min-height: 64px; resize: vertical; }
.robot-create-form { margin-top: 10px; }
.robot-create-form form { display: flex; flex-direction: column; gap: 8px; margin-top: 8px; }
/* Portal service-account cards keep the key material + password blocks legible. */
.robot-card textarea[readonly] { width: 100%; resize: vertical; }
/* Registration list notes cell: a truncated preview (full note in the title
   tooltip) with an inline editor that reuses .reject-form. The editor stacks
   vertically inside the narrow cell; the toggle button sits beside the preview. */
.cell-notes { max-width: 220px; }
.notes-preview { display: inline-block; max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: middle; }
.notes-edit-toggle { margin-left: 4px; }
.notes-edit-form { margin-top: 6px; flex-direction: column; align-items: stretch; }
.notes-edit-form textarea { width: 100%; resize: vertical; min-height: 56px; }
.notes-edit-actions { display: flex; gap: 6px; }

/* ---------- public pages ---------- */

.public-shell {
  min-height: 100vh;
  display: grid;
  grid-template-columns: minmax(280px, 36%) 1fr;
}

.brand-panel {
  position: relative;
  background: linear-gradient(180deg, #e02535 0%, #b91a27 55%, #8a131d 100%);
  color: #fff;
  padding: 56px 52px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.brand-panel > * { position: relative; z-index: 1; }

.brand-eyebrow {
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.72);
  font-weight: 600;
}

.brand-title {
  font-family: var(--font-display);
  font-size: clamp(30px, 3.4vw, 44px);
  font-weight: 700;
  line-height: 1.1;
  margin: 14px 0 12px;
}

.brand-lead {
  font-size: 15px;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.85);
  max-width: 420px;
}

.steps {
  list-style: none;
  margin: auto 0 0;
  padding: 36px 0 0;
  display: flex;
  flex-direction: column;
  gap: 18px;
  counter-reset: step;
}

.steps li {
  counter-increment: step;
  display: flex;
  gap: 14px;
  align-items: flex-start;
  max-width: 420px;
}

.steps li::before {
  content: counter(step, decimal-leading-zero);
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 500;
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.4);
  border-radius: var(--radius-sm);
  padding: 3px 7px;
  flex: none;
  margin-top: 1px;
}

.steps .step-title { font-weight: 600; font-size: 14px; }
.steps .step-sub { color: rgba(255, 255, 255, 0.72); font-size: 12.5px; }

.brand-foot {
  margin-top: 40px;
  font-family: var(--font-mono);
  font-size: 11px;
  color: rgba(255, 255, 255, 0.55);
}

.public-form-side {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 48px 32px;
  background: var(--bg);
}

.public-card {
  width: 100%;
  max-width: 480px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  padding: 34px 36px;
}

.public-card h1 {
  font-size: 24px;
  margin-bottom: 6px;
}

.public-card .public-sub { color: var(--text-muted); font-size: 13.5px; margin-bottom: 24px; }

.public-card .btn-primary { width: 100%; padding: 10px; font-size: 14px; margin-top: 6px; }

/* The /terms acceptable-use page: a wider prose card with readable headings. */
.public-card--prose { max-width: 620px; }
.terms-body h2 {
  font-size: 14.5px;
  margin: 20px 0 6px;
  color: var(--text);
}
.terms-body p {
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--text-muted);
  margin: 0;
}

.public-form-side--column { flex-direction: column; }

/* ---------- utility login (operator variant) ----------
   The operator sign-in is deliberately NOT the split-shell brand panel:
   a single quiet column, top-anchored, with a compact wordmark row above
   one plain card. Keeps the same tokens/card system — just no decoration. */
.public-shell--utility { grid-template-columns: 1fr; }

.public-shell--utility .public-form-side {
  align-items: flex-start;
  padding: 9vh 32px 56px;
}

/* End-user login pages (instance + portal): the card is top-anchored in the
   form column instead of dead-centered — the content reads as a page, not a
   floating modal. Padding caps on short viewports so nothing clips. */
.public-form-side--login {
  align-items: flex-start;
  justify-content: center;
  padding: min(11vh, 132px) 32px 56px;
}

.utility-login {
  width: 100%;
  max-width: 400px;
}

.utility-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 22px;
}

.utility-brand-logo { flex: none; }

.utility-brand-name {
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
}

/* Anti-spam honeypot: rendered invisibly so real users never see or fill it,
   while naive bots that auto-fill every field trip the server-side check. */
.hp-field {
  position: absolute;
  left: -9999px;
  top: auto;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.public-faq {
  width: 100%;
  max-width: 480px;
  margin-top: 24px;
}

.public-faq-title {
  font-size: 15px;
  margin-bottom: 12px;
}
.inline-terms {
  margin-top: 6px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--panel);
}

.inline-terms summary {
  padding: 9px 12px;
  font-size: 12.5px;
  cursor: pointer;
  list-style: none;
  user-select: none;
  color: var(--text-faint);
}

.inline-terms summary::before {
  content: "▸ ";
}

.inline-terms[open] summary::before {
  content: "▾ ";
}

.inline-terms-body {
  padding: 0 12px 12px;
  font-size: 12.5px;
  color: var(--text);
}

.inline-terms-body p { margin: 0 0 8px; }

.inline-terms-body a { color: var(--accent); }


.faq-item {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  margin-bottom: 8px;
  overflow: hidden;
  transition: border-color 150ms ease;
}

.faq-item:hover { border-color: var(--border-strong); }

.faq-item[open] .faq-question { background: var(--panel-2); }

.faq-question {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 13px 16px;
  font-size: 13.5px;
  font-weight: 500;
  cursor: pointer;
  list-style: none;
  user-select: none;
}

.faq-question::-webkit-details-marker { display: none; }

.faq-question::after {
  content: "";
  flex: none;
  width: 8px;
  height: 8px;
  border-right: 2px solid var(--text-muted);
  border-bottom: 2px solid var(--text-muted);
  transform: rotate(45deg);
  transition: transform 150ms ease;
}

.faq-item[open] .faq-question::after { transform: rotate(-135deg); }

.faq-question:hover { color: var(--accent); }

.faq-answer {
  padding: 0 16px 14px;
  color: var(--text-muted);
  font-size: 13px;
  line-height: 1.55;
}

.faq-answer p { margin: 0; }

.result-icon {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  margin-bottom: 18px;
}

.result-icon.success { background: var(--success-tint); color: var(--success); }
.result-icon.info { background: var(--info-tint); color: var(--info); }
.result-icon.warning { background: var(--warning-tint); color: var(--warning); }
.result-icon.danger { background: var(--danger-tint); color: var(--danger); }

/* ---------- login ---------- */

.login-card {
  width: 100%;
  max-width: 400px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  padding: 32px 34px;
}
.login-card h1 { font-size: 24px; margin-bottom: 6px; }

.login-card .public-sub { color: var(--text-muted); font-size: 13.5px; margin-bottom: 24px; }

.login-card .btn-primary { width: 100%; padding: 10px; font-size: 14px; margin-top: 6px; }

/* ---------- instance login (unified XCS login) ---------- */

.login-card .instance-links {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin-top: 16px;
  font-size: 13px;
}

.login-card .instance-links a { color: var(--accent); text-decoration: none; }
.login-card .instance-links a:hover { text-decoration: underline; }
.login-card .instance-links-sep { color: var(--text-muted); }

.login-card .instance-switch { margin-top: 14px; text-align: center; font-size: 13px; }
.login-card .instance-switch a { color: var(--accent); text-decoration: none; }
.login-card .instance-switch a:hover { text-decoration: underline; }

.login-card .banner { margin-bottom: 16px; }

/* ---------- AVG (GDPR) acknowledgment notice ----------
   Shared chrome for the verbatim Dutch legal notice (_avg_notice.html):
   the login-card panel and the portal interstitial. Tokens only — theme
   aware, reduced-motion safe. */
.avg-notice {
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius);
  background: var(--bg-inset);
  padding: 14px 16px;
  margin: 14px 0;
  font-size: 13px;
  line-height: 1.55;
  color: var(--text-muted);
}
.avg-notice-title {
  margin: 0 0 8px;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--text);
}
.avg-notice p { margin: 0 0 8px; }
.avg-notice p:last-child { margin-bottom: 0; }
.avg-language-note { margin-top: 10px; }
.avg-confirm-form { margin-top: 14px; }
.avg-decline-hint { margin-top: 10px; color: var(--text-faint); }
/* Portal Home acknowledgment state: the versioned evidence panel shown to
   every signed-in user (confirmation + UTC timestamp + collapsible notice).
   Tokens only — theme aware, reduced-motion safe. */
.avg-ack-details { margin-top: 10px; }
.avg-ack-details summary {
  cursor: pointer;
  color: var(--text-muted);
  font-size: 13px;
}
.avg-ack-details[open] summary { margin-bottom: 4px; }
.avg-panel .panel { max-width: 720px; margin: 0 auto; }

/* ---------- embedded portal panel (login-card portal transform) ----------
   After a successful instance login the card transforms in place into a
   compact self-service portal (the fourth server-rendered panel). The wider
   card carries a greeting + status head, the hero "Open files" action, and
   in-card section tabs sharing the /portal content partials. All tokens are
   theme-agnostic; motion is disabled by the global reduced-motion block. */

.login-card--portal { max-width: 720px; }

.login-card--portal .login-portal { animation: esr-portal-in 420ms var(--ease-out) both; }

@keyframes esr-portal-in {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

.login-portal-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 14px;
  margin-bottom: 16px;
}

.login-portal-id { display: flex; align-items: center; gap: 12px; min-width: 0; }

.login-portal-avatar {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  flex: none;
  border-radius: 50%;
  background: var(--accent-tint);
  color: var(--accent);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 35%, transparent);
}

.login-portal-id-text { min-width: 0; }

.login-portal-title { font-size: 20px; margin: 0; line-height: 1.25; }

.login-portal-sub { margin: 2px 0 0; font-size: 12.5px; color: var(--text-muted); overflow-wrap: anywhere; }

/* Account status: a compact inline dot + label under the identity line (the
   head's top-right corner now belongs to the sign-out button). */
.login-portal-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 5px;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
}

.login-portal-status .dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.login-portal-status--success .dot { animation: dot-pulse 2.2s ease-in-out infinite; }

.login-portal-status--success { color: var(--success); background: var(--success-tint); }
.login-portal-status--danger { color: var(--danger); background: var(--danger-tint); }
.login-portal-status--neutral { color: var(--text-muted); background: var(--neutral-tint, var(--panel-2)); }

.login-portal-logout { margin: 0; flex: none; }

.login-portal-hero {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  border-radius: var(--radius);
  border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent);
  background: linear-gradient(
    135deg,
    color-mix(in srgb, var(--accent) 16%, transparent),
    color-mix(in srgb, var(--accent) 6%, transparent)
  );
  color: var(--text);
  text-decoration: none;
  transition: transform 160ms var(--ease-out), box-shadow 160ms var(--ease-out), border-color 160ms;
}

.login-portal-hero:hover,
.login-portal-hero:focus-visible {
  border-color: var(--accent);
  box-shadow: var(--glow-accent-sm, var(--shadow-md));
  transform: translateY(-1px);
}

.login-portal-hero:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.login-portal-hero-icon {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  flex: none;
  border-radius: var(--radius);
  background: var(--accent);
  color: #fff;
}

.login-portal-hero-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }

.login-portal-hero-title { font-family: var(--font-display); font-weight: 600; font-size: 15px; }

.login-portal-hero-sub { font-size: 12.5px; color: var(--text-muted); }

.login-portal-hero-arrow { margin-left: auto; flex: none; color: var(--text-muted); }

/* Sticky tab bar: the tabs sit ABOVE the scroll region, so they stay
   pinned while long panes (Account) scroll underneath them. */
.login-portal { display: flex; flex-direction: column; min-height: 0; }

.login-portal-tabs {
  position: sticky;
  top: 0;
  z-index: 3;
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin: 16px 0 0;
  padding: 8px 0 10px;
  border-bottom: 1px solid var(--border);
  background: var(--panel);
}

.login-portal-tab {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 13px;
  border-radius: var(--radius);
  font-size: 13px;
  font-weight: 500;
  color: var(--text-muted);
  text-decoration: none;
  transition: color 140ms, background 140ms;
}
.login-portal-tab.is-active { color: var(--accent-text); background: var(--accent); }
.login-portal-tab:hover { color: var(--text); background: var(--panel-2); }

.login-portal-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Unread-count badge on the chat tab. */
.login-portal-tab-badge {
  min-width: 18px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--info);
  color: #fff;
  font-size: 10.5px;
  font-weight: 700;
  line-height: 16px;
  text-align: center;
}
.login-portal-tab.is-active .login-portal-tab-badge { background: rgba(255, 255, 255, 0.92); color: var(--accent); }

.login-portal-body {
  overflow-y: auto;
  max-height: min(430px, 62vh);
  padding: 14px 6px 4px 2px;
  scrollbar-width: thin;
}

.login-portal-pane { display: flex; flex-direction: column; gap: 14px; animation: esr-pane-in 200ms var(--ease-out) both; }

@keyframes esr-pane-in {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}

/* Compact the shared portal content inside the card. */
.login-portal .panel { margin: 0; }
.login-portal .p-grid-2 { grid-template-columns: 1fr; gap: 14px; }
.login-portal .p-fields { grid-template-columns: 1fr; }
.login-portal .p-status { padding: 12px 14px; }
.login-portal-pane[hidden] { display: none; }

/* ---- chat pane ----
   The chat fills the pane's visible height: header + scrollable message
   list + pinned composer, all on one screen (a real chat app never makes
   you page-scroll past the composer). `.login-portal-body` is the scroll
   region for the OTHER panes; the chat pane matches its height exactly. */
.login-portal-chat { display: flex; flex-direction: column; min-height: 0; height: 430px; max-height: 62vh; }

.login-portal-chat-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 8px;
}

.login-portal-chat-title { font-weight: 600; font-size: 13.5px; }

.login-portal-msg-list {
  flex: 1;
  min-height: 120px;
  height: auto;
  max-height: none;
  margin: 0;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--panel-2) 40%, transparent);
}

.login-portal-composer textarea { font-size: 13px; }

.login-portal-composer .msg-composer-hint { font-size: 11px; }

/* Skeleton shimmer while the history loads (messaging.js removes the
   wrapper once the fetch settles). */
.msg-skeleton { list-style: none; display: flex; flex-direction: column; gap: 10px; padding: 4px; }

.msg-skeleton-bubble {
  display: block;
  height: 34px;
  width: 62%;
  border-radius: 12px;
  background: linear-gradient(90deg, var(--panel-2) 25%, color-mix(in srgb, var(--text-muted) 22%, var(--panel-2)) 50%, var(--panel-2) 75%);
  background-size: 300% 100%;
  animation: esr-skeleton 1.2s ease-in-out infinite;
}

.msg-skeleton-bubble--mine { margin-left: auto; }
.msg-skeleton-bubble--short { width: 38%; }

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

.login-portal-chat-error {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 12px;
  border-radius: var(--radius);
  border: 1px solid var(--danger);
  background: var(--danger-tint);
  color: var(--text);
  font-size: 12.5px;
  margin-bottom: 10px;
}

.login-portal-chat-error[hidden] { display: none; }

.login-portal-chat-error p { margin: 0; }

.login-portal-chat-unavailable { margin: 0; padding: 8px 0; }

.login-portal .msg-new-pill { align-self: center; }

@media (max-width: 640px) {
  .login-card--portal { max-width: 100%; }
  .login-portal-head { flex-wrap: wrap; }
  .login-portal-logout { margin-left: auto; }
  .login-portal-body { max-height: none; overflow: visible; padding-right: 0; }
  .login-portal-tabs { position: static; flex-wrap: nowrap; overflow-x: auto; }
  .login-portal-chat { height: 400px; max-height: 58vh; }
  .login-portal-chat-error { flex-direction: column; align-items: flex-start; }
}

.portal-page--narrow { max-width: 520px; margin: 0 auto; }
.p-loading { display: flex; align-items: center; gap: 10px; color: var(--text-muted); font-size: 14px; }

/* ---------- keyboard shortcuts ---------- */

.shortcuts-hint[aria-expanded="true"] {
  color: var(--accent);
  border-color: var(--accent-tint-strong);
  background: var(--accent-tint);
}

.shortcuts-dialog {
  border: 1px solid var(--border-strong);
  border-top: 3px solid var(--accent);
  border-radius: var(--radius-lg);
  background: var(--panel);
  color: var(--text);
  padding: 0;
  width: min(560px, calc(100vw - 32px));
  box-shadow: var(--shadow-md);
}

.shortcuts-dialog::backdrop {
  background: rgba(4, 6, 10, 0.6);
  backdrop-filter: blur(2px);
}

.shortcuts-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 16px 20px 12px;
  border-bottom: 1px solid var(--border);
}

.shortcuts-head h2 { font-size: 16px; }

.shortcuts-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px 28px;
  padding: 14px 20px 4px;
}

.shortcuts-group {
  font-family: var(--font-mono);
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-faint);
  margin: 8px 0 2px;
}

.shortcut-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 5px 0;
  font-size: 13px;
  color: var(--text-muted);
  transition: color 120ms ease;
}

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

.shortcut-keys { display: flex; gap: 4px; flex: none; }

.shortcuts-dialog kbd {
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--text-muted);
  border: 1px solid var(--border-strong);
  border-bottom-width: 2px;
  border-radius: 5px;
  padding: 1px 6px;
  background: var(--panel-2);
  white-space: nowrap;
}

.shortcuts-foot {
  margin: 0;
  padding: 12px 20px 16px;
  font-size: 12px;
  color: var(--text-faint);
}

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

/* The per-user settings live in the user menu's IN-FLYOUT settings panel
   (v4) — the old <dialog> modal is gone; only the shared form + feedback
   rules remain. */
.profile-form { padding: 16px 20px 4px; }
.profile-form .form-field { margin-bottom: 12px; }
.profile-form .form-hint { font-size: 11.5px; color: var(--text-faint); margin: 2px 0 0; }
.profile-form .form-actions { display: flex; justify-content: flex-end; padding-bottom: 4px; }

#profile-feedback,
#profile-dialog-feedback { padding: 0 14px 10px; }
#profile-feedback:empty,
#profile-dialog-feedback:empty { display: none; }
#profile-feedback .banner,
#profile-dialog-feedback .banner { margin: 0; }

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

/* ---------- 8. Dashboard redesign (Radar-style bento) ----------
   Role-tailored bento grids over the shared .panel/.stat-tile chrome.
   Pure CSS motion (entrance stagger, bar fills, hover lift, live pulse),
   all ≤ 400ms and disabled by the global prefers-reduced-motion block. */

.dash-grid {
  display: grid;
  gap: 18px;
  align-items: stretch;
  position: relative;
}
/* (ambient glow removed with the Radar-style hero redesign — flat panels only) */
.dash-grid > * { position: relative; z-index: 1; }
.dash-grid .panel { margin-top: 0; }
/* Cells stretch to their row's height and fill it with the panel card, so a
   short panel reads as a deliberate rectangle (Grafana-style) instead of a
   transparent void. The body grows to absorb the extra height. */
.dash-cell { min-width: 0; display: flex; }
.dash-cell > .panel { flex: 1 1 auto; display: flex; flex-direction: column; width: 100%; }
.dash-cell > .panel > .panel-body { flex: 1 1 auto; }

/* ---------- 8b. Card grid system (house standard) ----------
   Extracted from the dashboard bento above: ONE gap scale (18px desktop,
   14px ≤980px), stretch-aligned card cells (equal-height rows, Grafana-style),
   and one card base. Every card-bearing surface consumes these utilities
   instead of re-declaring its own grid; cards keep the shared .panel chrome. */

.card-grid {
  display: grid;
  gap: 18px;
  align-items: stretch;
}
.card-grid > * { min-width: 0; }
/* Cells stretch to their row's height; the card fills it as a column so a
   short card reads as a deliberate rectangle, never a floating stub. */
.card-grid > .panel,
.card-grid > .card,
.card-grid > article,
.card-grid > a {
  display: flex;
  flex-direction: column;
  height: 100%;
}
.card-grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr)); }
.card-grid--3 { grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr)); }

@media (max-width: 980px) {
  .card-grid { gap: 14px; }
}

.card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 16px;
  min-width: 0;
}


/* Entrance stagger: cells fade/rise once, delayed by their inline --d. */
.dash-reveal {
  animation: dash-rise 380ms var(--ease-out) both;
  animation-delay: var(--d, 0ms);
}
@keyframes dash-rise {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}

/* ---- per-role bento layouts (named areas keep each role's shape distinct) ---- */

.dash-role-admin {
  grid-template-columns: repeat(12, 1fr);
  grid-template-areas:
    "actions actions actions actions actions actions actions actions overview overview overview overview"
    "attention attention attention attention attention attention attention attention activity activity activity activity"
    "reminders reminders reminders reminders reminders reminders recent recent recent recent recent recent"
    "instances instances instances instances instances instances instances status status status status status"
    "messaging messaging messaging messaging messaging messaging messaging messaging messaging messaging messaging messaging";
}
.dash-role-admin > [style*="actions"] { grid-area: actions; }

.dash-role-support {
  grid-template-columns: repeat(12, 1fr);
  grid-template-areas:
    "reminders reminders reminders reminders reminders reminders reminders reminders status status status status"
    "failures failures failures failures failures failures failures failures recent recent recent recent"
    "messaging messaging messaging messaging messaging messaging messaging messaging messaging messaging messaging messaging";
}

.dash-role-manager {
  grid-template-columns: repeat(12, 1fr);
  grid-template-areas:
    "domains domains domains domains domains domains domains domains domains domains domains domains"
    "pending pending pending pending pending pending failures failures failures failures failures failures"
    "recent recent recent recent recent recent recent recent recent recent recent recent"
    "messaging messaging messaging messaging messaging messaging messaging messaging messaging messaging messaging messaging";
}

.dash-role-auditor {
  grid-template-columns: repeat(12, 1fr);
  grid-template-areas:
    "funnel funnel funnel funnel funnel funnel funnel compliance compliance compliance compliance compliance"
    "activity activity activity activity activity activity activity activity exports exports exports exports";
}

@media (max-width: 1180px) {
  .dash-role-admin {
    grid-template-areas:
      "actions actions actions actions actions actions actions actions actions actions actions actions"
      "overview overview overview overview overview overview overview overview overview overview overview overview"
      "attention attention attention attention attention attention attention attention attention attention attention attention"
      "reminders reminders reminders reminders reminders reminders reminders reminders reminders reminders reminders reminders"
      "recent recent recent recent recent recent recent recent recent recent recent recent"
      "instances instances instances instances instances instances instances instances instances instances instances instances"
      "status status status status status status status status status status status status"
      "messaging messaging messaging messaging messaging messaging messaging messaging messaging messaging messaging messaging";
  }
  .dash-role-support {
    grid-template-areas:
      "reminders reminders reminders reminders reminders reminders reminders reminders reminders reminders reminders reminders"
      "failures failures failures failures failures failures failures failures failures failures failures failures"
      "status status status status status status status status status status status status"
      "recent recent recent recent recent recent recent recent recent recent recent recent"
      "messaging messaging messaging messaging messaging messaging messaging messaging messaging messaging messaging messaging";
  }
  .dash-role-auditor {
    grid-template-areas:
      "funnel funnel funnel funnel funnel funnel funnel funnel funnel funnel funnel funnel"
      "compliance compliance compliance compliance compliance compliance compliance compliance compliance compliance compliance compliance"
      "activity activity activity activity activity activity activity activity activity activity activity activity"
      "exports exports exports exports exports exports exports exports exports exports exports exports";
  }
}

@media (max-width: 980px) {
  .dash-grid { gap: 14px; }
  .dash-role-manager {
    grid-template-areas:
      "domains domains domains domains domains domains domains domains domains domains domains domains"
      "pending pending pending pending pending pending pending pending pending pending pending pending"
      "failures failures failures failures failures failures failures failures failures failures failures failures"
      "recent recent recent recent recent recent recent recent recent recent recent recent"
      "messaging messaging messaging messaging messaging messaging messaging messaging messaging messaging messaging messaging";
  }
}

/* ---- stacked status bar + legend ---- */

.dash-statusbar {
  display: flex;
  height: 14px;
  border-radius: 999px;
  overflow: hidden;
  background: var(--bg-inset);
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.35);
}
.dash-statusbar-empty { border: 1px dashed var(--border-strong); background: transparent; box-shadow: none; }
.dash-statusbar-seg {
  height: 100%;
  min-width: 6px;
  transform-origin: left center;
  animation: dash-seg 460ms var(--ease-out) both;
  animation-delay: calc(var(--i, 0) * 60ms);
  transition: width 400ms var(--ease-out);
}
@keyframes dash-seg { from { transform: scaleX(0); } }
.dash-statusbar-seg + .dash-statusbar-seg { border-left: 1px solid color-mix(in srgb, var(--panel) 70%, transparent); }

.dash-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 14px;
  margin-top: 12px;
}
.dash-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--text-muted);
  text-decoration: none;
  padding: 2px 4px;
  border-radius: var(--radius-sm);
  transition: background 140ms var(--ease-out), color 140ms var(--ease-out);
}
.dash-legend-item:hover { background: var(--bg-hover); color: var(--text); }
.dash-legend-count { font-family: var(--font-mono); font-size: 12px; color: var(--text); }

/* ---- 14-day sparkline (CSS bars) ---- */

.dash-spark-block {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}
.dash-spark-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 8px;
}
.dash-spark-title {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.dash-spark-total { font-size: 12px; color: var(--text-muted); }
.dash-spark {
  display: flex;
  align-items: flex-end;
  gap: 3px;
  height: 44px;
}
.dash-spark-bar {
  flex: 1 1 0;
  min-width: 2px;
  border-radius: 2px 2px 0 0;
  background: var(--panel-3);
  transition: height 380ms var(--ease-out), background 140ms var(--ease-out);
}

/* ---- portal messaging overview (dashboard + stats share the tokens) ---- */

.dash-msg-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 10px;
}
.dash-msg-tile {
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px 14px 10px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.dash-msg-value {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.5rem;
  line-height: 1.1;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}
.dash-msg-label {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.dash-msg-tile.tone-warning {
  border-color: color-mix(in srgb, var(--warning) 45%, var(--border));
}
.dash-msg-tile.tone-warning .dash-msg-value { color: var(--warning); }
.count-chip-warn { background: var(--warning-tint); color: var(--warning); }
.dash-spark-bar.has-count { background: color-mix(in srgb, var(--accent) 62%, var(--panel-3)); }
.dash-spark-bar:hover { background: var(--accent); }

/* ---- compliance funnel ---- */

.dash-funnel { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.dash-funnel-stage {
  display: grid;
  grid-template-columns: 96px 1fr 40px 44px;
  align-items: center;
  gap: 10px;
  font-size: 13px;
}
.dash-funnel-label { color: var(--text-muted); }
.dash-funnel-track {
  height: 12px;
  border-radius: 999px;
  background: var(--bg-inset);
  overflow: hidden;
}
.dash-funnel-fill {
  display: block;
  height: 100%;
  width: var(--w, 0%);
  border-radius: 999px;
  background: linear-gradient(90deg, color-mix(in srgb, var(--accent) 78%, var(--panel-3)), var(--accent));
  animation: dash-grow 400ms var(--ease-out) both;
  animation-delay: var(--d, 0ms);
}
@keyframes dash-grow { from { width: 0; } }
.dash-funnel-count { text-align: right; font-family: var(--font-mono); font-size: 12.5px; }
.dash-funnel-pct { text-align: right; color: var(--text-faint); font-family: var(--font-mono); font-size: 11.5px; }
.dash-funnel-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 16px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
  font-size: 12.5px;
  color: var(--text-muted);
}
.dash-verify-summary { display: inline-flex; align-items: center; gap: 8px; }
.dash-verify-link { color: var(--warning); text-decoration: none; }
.dash-verify-link:hover { text-decoration: underline; }

/* ---- system health rows ---- */

.dash-health { list-style: none; margin: 0; padding: 0; }
.dash-health li {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 0;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
}
.dash-health li:last-child { border-bottom: 0; }
.dash-health-name { flex: 1; color: var(--text-muted); }

/* ---- org-manager domain health cards ---- */

.dash-domain-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(215px, 1fr));
  gap: 12px;
}
.dash-domain-card {
  display: flex;
  flex-direction: column;
  gap: 9px;
  padding: 13px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--panel-2);
  color: var(--text);
  text-decoration: none;
  transition: transform 160ms var(--ease-out), border-color 160ms var(--ease-out), box-shadow 160ms var(--ease-out);
}
.dash-domain-card:hover {
  transform: translateY(-2px);
  border-color: var(--border-strong);
  box-shadow: var(--shadow-md);
  color: var(--text);
}
.dash-domain-card-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.dash-domain-name { font-weight: 600; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dash-domain-card-meta { display: flex; flex-wrap: wrap; gap: 6px; }
.dash-domain-card-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 14px;
  font-size: 12px;
  color: var(--text-muted);
  border-top: 1px solid var(--border);
  padding-top: 8px;
}
.dash-domain-card-stats strong { color: var(--text); font-family: var(--font-mono); font-weight: 500; }
.dash-warn { color: var(--warning); }
.dash-warn strong { color: var(--warning); }
.dash-danger { color: var(--danger); }
.dash-danger strong { color: var(--danger); }

/* ---- instance summary cards ---- */

.dash-instance-cards { display: flex; flex-direction: column; gap: 10px; }
.dash-instance-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 13px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--panel-2);
  color: var(--text);
  text-decoration: none;
  transition: transform 160ms var(--ease-out), border-color 160ms var(--ease-out), box-shadow 160ms var(--ease-out);
}
.dash-instance-card:hover {
  transform: translateY(-2px);
  border-color: var(--border-strong);
  box-shadow: var(--shadow-md);
  color: var(--text);
}
.dash-instance-card > svg { color: var(--text-faint); flex: none; }
.dash-instance-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.dash-instance-name { font-weight: 600; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dash-instance-group { font-size: 11px; color: var(--text-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dash-instance-users { text-align: right; flex: none; }
.dash-instance-users strong { display: block; font-family: var(--font-display); font-size: 18px; font-weight: 600; line-height: 1.1; }
.dash-instance-users span { font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-faint); }

/* ---------- responsive ---------- */

@media (max-width: 1180px) {
  .grid-2, .detail-grid { grid-template-columns: 1fr; }
}


/* ---------- onboarding progress page ---------- */

.onboarding-side { align-items: center; }

.onboarding-card {
  position: relative;
  overflow: hidden;
  width: 100%;
  max-width: 560px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-top: 3px solid var(--accent);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  padding: 34px 38px 30px;
}

/* Ambient layered background: a soft radial accent glow plus a fine grid built
   from existing tokens (not aurora blobs or glassmorphism). It fades downward
   so the text below stays clean. */
.onboarding-card::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 90% -12%, var(--accent-tint-strong), transparent 52%);
  pointer-events: none;
}

.onboarding-card::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(color-mix(in srgb, var(--border) 60%, transparent) 1px, transparent 1px),
    linear-gradient(90deg, color-mix(in srgb, var(--border) 60%, transparent) 1px, transparent 1px);
  background-size: 30px 30px;
  opacity: 0.3;
  -webkit-mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.5), transparent 62%);
  mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.5), transparent 62%);
  pointer-events: none;
}

.onboarding-card > * { position: relative; z-index: 1; }

.onboarding-head { margin-bottom: 26px; }

.onboarding-eyebrow {
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  font-weight: 600;
  margin-bottom: 8px;
}

.onboarding-heading {
  font-size: clamp(24px, 3vw, 30px);
  line-height: 1.12;
  margin-bottom: 10px;
}

.onboarding-lead {
  color: var(--text-muted);
  font-size: 14px;
  line-height: 1.55;
  margin: 0 0 16px;
  max-width: 46ch;
}

.onboarding-meta { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }

.onboarding-email {
  font-size: 12.5px;
  color: var(--text-faint);
  background: var(--bg-inset);
  border: 1px solid var(--border);
  padding: 3px 8px;
  border-radius: var(--radius-sm);
}

.onboarding-live {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--text-muted);
}

.onboarding-live-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--success); }

.onboarding-live[data-state="live"] .onboarding-live-dot { animation: onboarding-pulse 2s ease-in-out infinite; }

.onboarding-live[data-state="done"] .onboarding-live-dot { background: var(--text-faint); animation: none; }

@keyframes onboarding-pulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--success) 45%, transparent); }
  50% { box-shadow: 0 0 0 5px transparent; }
}

/* Vertical stepper */
.stepper { list-style: none; margin: 0; padding: 4px 0 0; }

.stepper-step {
  position: relative;
  display: grid;
  grid-template-columns: 34px 1fr;
  gap: 16px;
  padding-bottom: 26px;
}

.stepper-step:last-child { padding-bottom: 4px; }

/* Connecting rail between markers */
.stepper-step::before {
  content: "";
  position: absolute;
  left: 16px;
  top: 36px;
  bottom: -4px;
  width: 2px;
  background: var(--border);
  transition: background 300ms ease;
}

.stepper-step:last-child::before { display: none; }

.stepper-step.is-complete::before { background: color-mix(in srgb, var(--success) 55%, transparent); }

.stepper-marker {
  position: relative;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--bg-inset);
  border: 2px solid var(--border-strong);
  color: var(--text-faint);
  z-index: 1;
  transition: background 300ms ease, border-color 300ms ease, color 300ms ease;
}

.stepper-marker .mk-check,
.stepper-marker .mk-alert { display: none; }

.stepper-marker .mk-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.5;
}

/* Complete: success tint + check */
.stepper-step.is-complete .stepper-marker { background: var(--success-tint); border-color: var(--success); color: var(--success); }
.stepper-step.is-complete .mk-check { display: block; }
.stepper-step.is-complete .mk-dot { display: none; }

/* Active: accent + pulsing dot */
.stepper-step.is-active .stepper-marker { background: var(--accent-tint); border-color: var(--accent); color: var(--accent); }
.stepper-step.is-active .mk-dot { opacity: 1; animation: stepper-pulse 1.6s ease-in-out infinite; }
.stepper-step.is-active .stepper-title { color: var(--accent); }

@keyframes stepper-pulse {
  0%, 100% { box-shadow: 0 0 0 0 var(--accent-tint-strong); transform: scale(1); }
  50% { box-shadow: 0 0 0 6px transparent; transform: scale(1.18); }
}

/* Provisioning step gets a rotating "working" arc while active */
.stepper-step[data-step="provisioning"].is-active .stepper-marker::after {
  content: "";
  position: absolute;
  inset: -3px;
  border-radius: 50%;
  border: 2px solid transparent;
  border-top-color: var(--accent);
  animation: stepper-spin 1s linear infinite;
}

@keyframes stepper-spin { to { transform: rotate(360deg); } }

/* Blocked: danger + alert */
.stepper-step.is-blocked .stepper-marker { background: var(--danger-tint); border-color: var(--danger); color: var(--danger); }
.stepper-step.is-blocked .mk-alert { display: block; }
.stepper-step.is-blocked .mk-dot { display: none; }
.stepper-step.is-blocked .stepper-title { color: var(--danger); }

/* Pending: dimmed */
.stepper-step.is-pending { opacity: 0.55; }
.stepper-step.is-pending .stepper-title { color: var(--text-muted); }

.stepper-body { display: flex; flex-direction: column; gap: 3px; padding-top: 4px; }

.stepper-title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 15px;
  color: var(--text);
  transition: color 300ms ease;
}

.stepper-desc { font-size: 13px; color: var(--text-muted); line-height: 1.45; }

.stepper-time { font-family: var(--font-mono); font-size: 11.5px; color: var(--text-faint); margin-top: 2px; }
.stepper-time[hidden] { display: none; }

.onboarding-note { margin-top: 22px; }
.onboarding-note[hidden] { display: none; }

.onboarding-resend {
  margin-top: 22px;
  padding: 16px 18px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--bg-inset);
}
.onboarding-resend[hidden] { display: none; }
.onboarding-resend-lead { margin: 0 0 12px; font-size: 13.5px; color: var(--text-muted); line-height: 1.5; }
.onboarding-resend-actions { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.onboarding-resend-status { font-size: 12.5px; color: var(--text-faint); }
.onboarding-resend-status[hidden] { display: none; }
.onboarding-resend-status[data-state="success"] { color: var(--success); }
.onboarding-resend-status[data-state="error"] { color: var(--danger); }

.onboarding-success {
  display: flex;
  gap: 16px;
  align-items: flex-start;
  margin-top: 24px;
  padding: 18px;
  border: 1px solid color-mix(in srgb, var(--success) 40%, transparent);
  background: var(--success-tint);
  border-radius: var(--radius-lg);
}

.onboarding-success[hidden] { display: none; }
.onboarding-success .result-icon { flex-shrink: 0; margin: 0; }
.onboarding-success-body h2 { font-size: 16px; color: var(--success); margin-bottom: 6px; }
.onboarding-success-body p { margin: 0; font-size: 13.5px; color: var(--text-muted); line-height: 1.55; }

.onboarding-foot { margin-top: 26px; padding-top: 18px; border-top: 1px solid var(--border); }
.onboarding-foot .hint { margin: 0; color: var(--text-faint); font-size: 12.5px; line-height: 1.5; }

/* Tracking CTA on the register result page */
.onboarding-track-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-top: 18px;
  transition: transform 150ms ease, box-shadow 150ms ease;
}

.onboarding-track-link:hover { transform: translateY(-1px); box-shadow: 0 6px 18px var(--accent-tint-strong); }

/* Copy/share tracking-link button (register result + onboarding pages) */
.copy-link-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-top: 10px;
  transition: transform 150ms ease, box-shadow 150ms ease, background 150ms ease, border-color 150ms ease, color 150ms ease;
}
.copy-link-btn[data-copy-state="copied"] {
  background: var(--success-tint);
  border-color: color-mix(in srgb, var(--success) 45%, transparent);
  color: var(--success);
}

@media (max-width: 640px) {
  .onboarding-card { padding: 26px 22px 24px; }
}

/* ---------- motion prefs ---------- */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ---------- print ---------- */

@media print {
  /* paper-friendly palette regardless of the on-screen theme */
  :root {
    color-scheme: light;
    --bg: #ffffff;
    --bg-inset: #ffffff;
    --panel: #ffffff;
    --panel-2: #ffffff;
    --panel-3: #ffffff;
    --border: #c8ccd2;
    --border-strong: #9aa0a8;
    --text: #000000;
    --text-muted: #3f444c;
    --text-faint: #5b6068;
    --shadow-sm: none;
    --shadow-md: none;
  }

  body { background: #ffffff; font-size: 12px; }
  a { color: inherit; text-decoration: none; }

  /* chrome that never belongs on paper */
  .sidebar,
  .topbar,
  .no-print,
  .action-bar,
  .reject-form,
  .danger-zone,
  #detail-feedback,
  .banner,
  .session-toast,
  #notes-panel form { display: none !important; }

  .app-shell { display: block; min-height: 0; }
  .app-content { max-width: none; padding: 0; }

  .page-head { display: block; margin-bottom: 16px; }
  .page-title { font-size: 20px; }

  /* stack the detail columns; keep panels from splitting across pages */
  .detail-grid { display: block; }
  .panel { border-radius: 0; box-shadow: none; margin-top: 14px; break-inside: avoid; }
  .panel + .panel { margin-top: 14px; }
  .panel-body { padding: 12px 0; }

  .detail-fields { gap: 10px 24px; }
  .feed li, .timeline li { break-inside: avoid; }

  .badge { border: 1px solid var(--border-strong); }
}

/* ---------- end-user portal ---------- */

.portal-shell {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.portal-topbar {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 12px 28px;
  background: color-mix(in srgb, var(--bg) 86%, transparent);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--border);
}

.portal-brand {
  display: flex;
  align-items: center;
  gap: 10px;
}

.portal-brand-label {
  font-family: var(--font-display);
  font-weight: 600;
  color: var(--text-muted);
  font-size: 14px;
}

.portal-topbar-actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 14px;
}

.portal-user {
  font-size: 13px;
  color: var(--text-muted);
  font-family: var(--font-mono);
}

.portal-logout-form { margin: 0; }

.portal-main {
  width: 100%;
  max-width: 960px;
  margin: 0 auto;
  padding: 32px 28px 64px;
  flex: 1;
}

.portal-home { display: flex; flex-direction: column; gap: 24px; }

.portal-welcome h1 { margin: 0 0 6px; }

.portal-account { padding: 20px 22px; }

.portal-account-status {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 4px 0 16px;
}

.portal-footer {
  width: 100%;
  max-width: 960px;
  margin: 0 auto;
  padding: 18px 24px 30px;
  color: var(--text-muted);
  font-size: 12.5px;
  text-align: center;
  white-space: pre-line;
}

.portal-account-meta { font-size: 12.5px; color: var(--text-muted); }

.portal-sections {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 16px;
}

.portal-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 18px 20px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.portal-card:hover {
  border-color: var(--border-strong);
  box-shadow: var(--shadow-md);
}

.portal-card-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
}

.portal-card-sub {
  margin: 0;
  font-size: 12.5px;
  color: var(--text-muted);
  flex: 1;
}

/* ---------- portal: nav + pages ---------- */

.portal-brand { text-decoration: none; color: inherit; }

.portal-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  padding: 10px 28px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-inset);
  position: sticky;
  top: 49px;
  z-index: 20;
}

.portal-nav-link {
  padding: 6px 14px;
  border-radius: var(--radius);
  font-size: 13px;
  font-weight: 500;
  color: var(--text-muted);
  text-decoration: none;
  transition: background 0.12s ease, color 0.12s ease;
}

.portal-nav-link:hover { color: var(--text); background: var(--panel-2); }

.portal-nav-link.is-active {
  color: var(--accent-text);
  background: var(--accent);
}

.portal-page { display: flex; flex-direction: column; gap: 22px; }

.portal-head h1 { margin: 0 0 6px; font-size: 26px; }

.portal-head .public-sub { color: var(--text-muted); font-size: 14px; margin: 0; }

.p-grid-2 {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 18px;
  align-items: start;
}

.p-panel { margin: 0; }

.p-muted { color: var(--text-muted); font-size: 13px; margin: 0; }

.p-pad { padding: 18px; }

/* status banner */

.p-status {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 16px 20px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  background: var(--panel);
}

.p-status-icon {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: var(--radius);
  flex: none;
}

.p-status-title { font-family: var(--font-display); font-weight: 600; font-size: 15px; margin-bottom: 2px; }
.p-status-sub { margin: 0; font-size: 13px; color: var(--text-muted); }

.p-status--success { border-color: color-mix(in srgb, var(--success) 40%, transparent); background: var(--success-tint); }
.p-status--success .p-status-icon { background: var(--success-tint); color: var(--success); }
.p-status--danger { border-color: color-mix(in srgb, var(--danger) 45%, transparent); background: var(--danger-tint); }
.p-status--danger .p-status-icon { background: var(--danger-tint); color: var(--danger); }
.p-status--neutral .p-status-icon { background: var(--neutral-tint); color: var(--text-muted); }

/* stat cards */

.p-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 14px;
}

.p-stat {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 18px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  background: var(--panel);
  transition: border-color 0.12s ease, box-shadow 0.12s ease, transform 0.12s ease;
}

.p-stat:hover { border-color: var(--border-strong); box-shadow: var(--shadow-md); transform: translateY(-1px); }

.p-stat-icon {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: var(--radius);
  background: var(--neutral-tint);
  color: var(--text-muted);
  flex: none;
}

.p-stat--accent .p-stat-icon { background: var(--accent-tint); color: var(--accent); }

.p-stat-label { font-size: 12px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.04em; }

.p-stat-value {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 22px;
  line-height: 1.2;
  margin-top: 2px;
  word-break: break-word;
}

.p-stat-sub { font-size: 12px; color: var(--text-faint); margin-top: 2px; }

/* progress bars */

.p-usage-row { margin-bottom: 18px; }
.p-usage-row:last-child { margin-bottom: 0; }

.p-usage-head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 7px; }
.p-usage-label { font-weight: 500; font-size: 13.5px; }
.p-usage-value { font-family: var(--font-mono); font-size: 12.5px; }
.p-usage-of { color: var(--text-faint); }

.p-progress {
  height: 10px;
  border-radius: 999px;
  background: var(--panel-3);
  overflow: hidden;
}

.p-progress-fill {
  height: 100%;
  border-radius: 999px;
  background: var(--accent);
  transition: width 0.4s ease;
}

.p-progress-fill--warning { background: var(--warning); }
.p-progress-fill--danger { background: var(--danger); }
.p-progress--flat .p-progress-fill { background: var(--neutral-tint); }

.p-usage-pct { font-size: 12px; color: var(--text-muted); margin-top: 6px; }
.p-usage-pct--muted { color: var(--text-faint); }
.p-usage-divider { height: 1px; background: var(--border); margin: 20px 0; }

/* bar chart */

.p-barchart {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 48px;
  padding: 8px 0 4px;
}

.p-barchart-col { display: flex; flex-direction: column; align-items: center; gap: 8px; width: 120px; }
.p-barchart-value { font-family: var(--font-mono); font-size: 12.5px; color: var(--text-muted); }

.p-barchart-track {
  width: 64px;
  height: 140px;
  display: flex;
  align-items: flex-end;
  border-radius: var(--radius) var(--radius) 0 0;
  background: var(--panel-3);
  overflow: hidden;
}

.p-barchart-fill { width: 100%; border-radius: var(--radius) var(--radius) 0 0; transition: height 0.4s ease; min-height: 3px; }
.p-barchart-fill--upload { background: var(--accent); }
.p-barchart-fill--download { background: var(--info); }
.p-barchart-label { font-size: 12.5px; color: var(--text-muted); }

/* field lists */

.p-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px 24px; margin: 0; }
.p-field { display: flex; flex-direction: column; gap: 3px; }
.p-field dt { font-size: 12px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.04em; }
.p-field dd { margin: 0; font-size: 14px; word-break: break-word; }
.p-field dd.mono { font-family: var(--font-mono); font-size: 13px; }

/* callout */

.p-callout {
  display: flex;
  gap: 12px;
  margin-top: 18px;
  padding: 14px 16px;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--bg-inset);
}

.p-callout-icon { color: var(--accent); flex: none; padding-top: 1px; }
.p-callout-title { font-weight: 600; font-size: 13.5px; margin-bottom: 3px; }
.p-callout-sub { margin: 0; font-size: 12.5px; color: var(--text-muted); }

/* quick links / help links */

.p-quick-links, .p-help-links { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }

.p-quick-links a, .p-help-links a {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 10px 12px;
  border-radius: var(--radius);
  color: var(--text);
  text-decoration: none;
  font-size: 13.5px;
  transition: background 0.12s ease;
}

.p-quick-links a:hover, .p-help-links a:hover { background: var(--panel-2); }
.p-quick-links svg, .p-help-links svg { color: var(--text-muted); flex: none; }

/* rights list */

.p-rights-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }

.p-right {
  padding: 14px 16px;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--bg-inset);
}

.p-right--invisible { opacity: 0.72; }

.p-right-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.p-right-path { display: inline-flex; align-items: center; gap: 8px; font-weight: 500; }
.p-right-path svg { color: var(--accent); }
.p-right-path code { font-size: 13px; }

.p-right-caps {
  list-style: none;
  margin: 12px 0 0;
  padding: 12px 0 0;
  border-top: 1px solid var(--border);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 8px 16px;
}

.p-cap { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--text-muted); }
.p-cap svg { color: var(--success); flex: none; }

/* reports */

.p-report-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 16px; }
.p-report-actions .btn { gap: 8px; }

.p-check-list { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 8px; font-size: 13px; color: var(--text-muted); }

/* faq */

.p-faq { margin: 0; }
.p-faq dt { font-weight: 600; font-size: 13.5px; margin-top: 14px; }
.p-faq dt:first-child { margin-top: 0; }
.p-faq dd { margin: 4px 0 0; font-size: 13px; color: var(--text-muted); }

/* printable report */

.p-report-doc {
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--panel);
  padding: 28px;
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.p-report-doc-head { display: flex; align-items: center; gap: 16px; padding-bottom: 18px; border-bottom: 1px solid var(--border); }
.p-report-doc-title { font-family: var(--font-display); font-weight: 700; font-size: 18px; }
.p-report-doc-sub { font-size: 12.5px; color: var(--text-muted); }
.p-report-block h2 { font-size: 15px; margin-bottom: 12px; }

.portal-head.p-no-print { flex-direction: row; align-items: center; justify-content: space-between; }

@media print {
  .portal-nav { top: 57px; padding: 8px 16px; }
}

/* ---------- 5.1 portal overhaul: dashboard cards, files, badges, mobile ---------- */

.banner-danger { background: var(--danger-tint); border-color: color-mix(in srgb, var(--danger) 45%, transparent); color: var(--danger); }

/* unread badge (nav + quick cards) */
.portal-nav-badge {
  display: inline-grid;
  place-items: center;
  min-width: 18px;
  height: 18px;
  margin-left: 7px;
  padding: 0 5px;
  border-radius: 9px;
  background: var(--accent);
  color: #fff;
  font-family: var(--font-mono);
  font-size: 11px;
  line-height: 1;
}
.portal-nav-link.is-active .portal-nav-badge { background: rgba(255, 255, 255, 0.25); }

/* home quick-action cards: grid chrome comes from the shared card-grid
   utilities (portal_home.html renders p-quick-cards card-grid card-grid--3). */
.p-quick-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-height: 44px;
  padding: 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--panel);
  text-decoration: none;
  color: var(--text);
  transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
}
.p-quick-card:hover { border-color: var(--border-strong); box-shadow: var(--shadow-md); transform: translateY(-1px); }
.p-quick-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.p-quick-card-icon {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 9px;
  background: var(--accent-tint);
  color: var(--accent);
}
.p-quick-card-title { font-family: var(--font-display); font-weight: 600; font-size: 14px; display: inline-flex; align-items: center; }
.p-quick-card-sub { font-size: 12.5px; color: var(--text-muted); }

/* home recent-uploads mini list */
.p-file-mini-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.p-file-mini {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 6px;
  border-radius: var(--radius);
}
.p-file-mini:hover { background: var(--panel-2); }
.p-file-mini-icon { color: var(--text-muted); flex: none; display: grid; place-items: center; }
.p-file-mini-name { flex: 1; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.p-file-mini-meta { font-size: 11.5px; color: var(--text-faint); flex: none; }

/* connect steps */
.p-connect-steps { list-style: none; margin: 10px 0 0; padding: 0; display: flex; flex-direction: column; gap: 10px; font-size: 13.5px; }
.p-connect-step-num {
  display: inline-grid;
  place-items: center;
  width: 22px;
  height: 22px;
  margin-right: 8px;
  border-radius: 50%;
  background: var(--accent-tint);
  color: var(--accent-text);
  font-family: var(--font-mono);
  font-size: 11.5px;
  font-weight: 600;
}

/* files table */
.p-files-table svg { color: var(--text-muted); vertical-align: -2px; margin-right: 4px; }
.p-files-table .cell-action { white-space: nowrap; }
.p-files-table .btn { gap: 6px; min-height: 36px; }

/* empty state (files list, messages) */
.p-empty-state { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 34px 18px; text-align: center; }
.p-empty-state-icon {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  background: var(--accent-tint);
  color: var(--accent);
}
.p-empty-state-title { font-family: var(--font-display); font-weight: 600; font-size: 14.5px; margin: 4px 0 0; }
.p-empty-state-sub { margin: 0; font-size: 13px; color: var(--text-muted); max-width: 460px; }

/* progressive disclosure accordions (account subsections) */
.p-accordion { margin-top: 14px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg-inset); }
.p-accordion > summary {
  cursor: pointer;
  list-style: none;
  padding: 11px 14px;
  font-weight: 600;
  font-size: 13.5px;
  min-height: 44px;
  display: flex;
  align-items: center;
  gap: 8px;
}
.p-accordion > summary::-webkit-details-marker { display: none; }
.p-accordion > summary::before {
  content: "▸";
  color: var(--text-muted);
  transition: transform 0.15s ease;
}
.p-accordion[open] > summary::before { transform: rotate(90deg); }
.p-accordion > summary:hover { background: var(--panel-2); }
.p-accordion > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: var(--radius); }
.p-accordion > form, .p-accordion > p, .p-accordion > table { padding: 4px 14px 14px; }
.p-accordion > table { width: calc(100% - 28px); }
.p-fields--tight { margin-bottom: 6px; }

/* account anchor targets: clear the sticky portal topbar when jumping */
.portal-page .panel[id] { scroll-margin-top: 120px; }

/* panel header action link */
.panel-link { font-size: 12.5px; color: var(--accent-text); text-decoration: none; }
.panel-link:hover { text-decoration: underline; }
.panel-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }

/* messages friendlier empty state */
.msg--empty { display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 26px 12px; text-align: center; }
.msg-empty-icon { color: var(--text-muted); }
.msg-empty-title { font-weight: 600; font-size: 13.5px; margin: 6px 0 0; color: var(--text); }
.msg-empty-sub { margin: 0; font-size: 12.5px; color: var(--text-muted); max-width: 420px; }

/* mobile-first: cards stack, the files table becomes stacked cards */
@media (max-width: 640px) {
  .portal-main { padding: 18px 14px 40px; }
  .portal-head h1 { font-size: 22px; }
  .p-grid-2 { grid-template-columns: 1fr; }
  .portal-nav { gap: 2px; overflow-x: auto; flex-wrap: nowrap; padding-bottom: 4px; }
  .portal-nav-link { padding: 10px 12px; font-size: 13.5px; white-space: nowrap; }
  .p-quick-cards { grid-template-columns: 1fr; }
  .p-files-table thead { display: none; }
  .p-files-table, .p-files-table tbody, .p-files-table tr, .p-files-table td { display: block; width: 100%; }
  .p-files-table tr {
    padding: 12px 4px;
    border-bottom: 1px solid var(--border-subtle);
  }
  .p-files-table td { border: 0; padding: 3px 4px; }
  .p-files-table td.cell-action { padding-top: 8px; }
  .p-files-table .btn { width: 100%; justify-content: center; min-height: 44px; }
  .p-file-mini-meta { display: none; }
}
/* ---------- 5a. right-side flyout drawer ---------- */

.flyout-scrim {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
  z-index: 55;
  opacity: 0;
  transition: opacity 200ms var(--ease-out);
}
.flyout-scrim.open { opacity: 1; }
.flyout-scrim[hidden] { display: none; }

.flyout {
  position: fixed;
  top: var(--topbar-height);
  right: 0;
  height: calc(100% - var(--topbar-height));
  width: min(440px, 92vw);
  max-width: 92vw;
  background: var(--panel);
  border-left: 1px solid var(--border);
  box-shadow: var(--shadow-drawer);
  display: flex;
  flex-direction: column;
  z-index: 60;
  transform: translateX(100%);
  opacity: 0;
  transition: transform 260ms var(--ease-drawer), opacity 260ms var(--ease-drawer),
    width 260ms var(--ease-drawer), height 260ms var(--ease-drawer);
  will-change: transform;
}
.flyout.open { transform: none; opacity: 1; }
.flyout[hidden] { display: none; }

/* Expanded full view: the drawer grows into a near-full-page overlay panel
   (page dims under the existing scrim) with a two-column layout — sections
   on the left, a rail (activity/audit feeds) on the right. Toggled via
   [data-flyout-expand]/[data-flyout-collapse] in app.js; ESC collapses
   first, then closes. */
.flyout--expanded {
  top: calc(var(--topbar-height) + 10px);
  bottom: 10px;
  left: 16px;
  right: 16px;
  width: auto;
  /* The drawer's 92vw cap must not survive the expansion: with it, a wide
     viewport keeps a dead gutter to the right of the panel. */
  max-width: none;
  height: auto;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
}
.flyout--expanded .flyout-inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(280px, 380px);
  grid-template-rows: auto minmax(0, 1fr);
}
.flyout--expanded .flyout-head { grid-column: 1 / -1; }
.flyout--expanded .flyout-body {
  overflow-y: auto;
  padding-right: 4px;
}
[data-flyout-rail] { display: none; }
.flyout--expanded [data-flyout-rail] {
  display: block;
  overflow-y: auto;
  min-height: 0;
  border-left: 1px solid var(--border);
  padding: 18px;
}
.flyout-rail-slot { min-height: 0; min-width: 0; }
/* Full-view tab row (Overview / Logs …) — shown only when expanded; in the
   collapsed drawer the panels stack instead. */
[data-flyout-tabs] {
  display: flex;
  gap: 2px;
  border-bottom: 1px solid var(--border);
  padding: 0 18px;
}
[data-flyout-tab] {
  border: 0;
  background: transparent;
  color: var(--text-muted);
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  padding: 9px 12px;
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
[data-flyout-tab]:hover { color: var(--text); background: var(--bg-hover); }
[data-flyout-tab].active { color: var(--text); border-bottom-color: var(--accent); }
.flyout-managed {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  color: var(--text-muted);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 2px 9px;
  white-space: nowrap;
}
[data-flyout-back], [data-flyout-copy] { margin-right: 4px; }
.flyout-rail-title {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: 8px;
}
/* The expanded header shows a breadcrumb (kind / name) instead of the drawer's
   badge row, plus a collapse affordance instead of the expand one. */
.onboarding-review-actions { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }
.flyout-breadcrumb {
  display: none;
  align-items: center;
  gap: 8px;
  min-width: 0;
  font-size: 13px;
}
.flyout-breadcrumb .fb-kind {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--text-faint);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.flyout-breadcrumb .fb-sep { color: var(--text-faint); }
.flyout-breadcrumb .fb-name {
  color: var(--text);
  font-weight: 600;
  font-family: var(--font-mono);
  font-size: 12.5px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.flyout--expanded .flyout-breadcrumb { display: flex; }
.flyout--expanded .flyout-head .flyout-badges { display: none; }
.flyout--expanded [data-flyout-expand] { display: none; }
[data-flyout-collapse] { display: none; }
.flyout--expanded [data-flyout-collapse] { display: inline-flex; }
@media (max-width: 980px) {
  .flyout--expanded { left: 8px; right: 8px; }
  .flyout--expanded .flyout-inner { grid-template-columns: 1fr; }
  .flyout--expanded [data-flyout-rail] { border-left: 0; border-top: 1px solid var(--border); }
}

.flyout-resize { position: absolute; left: 0; top: 0; bottom: 0; width: 6px; cursor: ew-resize; z-index: 2; }
.flyout-resize:hover { background: var(--accent-tint); }

.flyout-inner { display: flex; flex-direction: column; min-height: 0; flex: 1; }
.flyout-head {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 10px;
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
  flex: none;
}
.flyout-badges { display: flex; align-items: center; gap: 8px; min-width: 0; flex-wrap: wrap; }
.flyout-actions { display: flex; align-items: center; gap: 4px; flex: none; margin-left: auto; }
/* Expanded-only header chrome: the breadcrumb, copy button, managed-by chip
   and header badges render only in the full view; the collapsed drawer keeps
   its single badge row + actions. */
.flyout-head .flyout-badges,
.flyout-back,
.flyout-head [data-flyout-copy],
.flyout-managed { display: none; }
.flyout--expanded .flyout-head .flyout-badges { display: flex; }
.flyout--expanded .flyout-back:not([hidden]) { display: inline-flex; }
.flyout--expanded .flyout-head [data-flyout-copy]:not([hidden]) { display: inline-flex; }
.flyout--expanded .flyout-managed:not([hidden]) { display: inline-flex; }

.flyout-body { padding: 18px; overflow-y: auto; min-height: 0; flex: 1; }
/* Dense information grid for flyout sections: small uppercase dt over the
   value, auto-fitting 2-3 columns depending on drawer width. */
.kv-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 12px 18px;
  margin: 0;
}
.kv-grid > div { min-width: 0; }
.kv-grid dt {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: 2px;
}
.kv-grid dd { margin: 0; font-size: 13px; word-break: break-word; }
.kv-grid dd.mono { font-family: var(--font-mono); font-size: 12px; font-variant-numeric: tabular-nums; }
.kv-grid dd .badge { vertical-align: middle; }
/* A full-width cell inside a kv-grid (spanning every column). */

/* ---------- Radar-style command palette ----------
   Opening darkens the page (scrim) and drops a command panel DOWNWARD from
   the topbar's global search control: the panel's top edge is flush with
   the searchbar's top edge, its left edge aligns with the searchbar's left
   edge, and its width equals the searchbar's rendered width. Never a
   centered modal, never a full-width bar, clamped 320–720px for readability.
   Grouped sections: Views, Actions, then live resource results.
   JS (app.js positionPalette) anchors the panel to the live searchbar rect
   on open and resize; the CSS left/width are the static fallback. */
.palette-scrim {
  position: fixed;
  inset: 0;
  background: #00000080;
  z-index: 80;
  backdrop-filter: blur(2px);
}
.palette-scrim[hidden] { display: none; }
.palette {
  position: fixed;
  top: 0;
  left: var(--sidebar-width);
  width: min(720px, calc(100vw - var(--sidebar-width) - 40px));
  min-width: 320px;
  max-height: min(70vh, 620px);
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  z-index: 85;
  overflow: hidden;
}
body.sidebar-collapsed .palette { left: var(--sidebar-rail); width: min(720px, calc(100vw - var(--sidebar-rail) - 40px)); min-width: 320px; }
.palette[hidden] { display: none; }
.palette-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
}
.palette-head svg { color: var(--text-muted); flex: none; }
.palette-head input {
  flex: 1;
  border: 0;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 14px;
  outline: none;
}
.palette-head input::placeholder { color: var(--text-faint); }
.palette-body { overflow-y: auto; padding: 8px; min-height: 0; flex: 1; }
.palette-group { margin-bottom: 10px; }
.palette-group:last-child { margin-bottom: 0; }
.palette-group-title {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
  padding: 6px 8px 4px;
}
.palette-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 8px;
  border-radius: calc(var(--radius-sm));
  color: var(--text);
  text-decoration: none;
  font-size: 13px;
  cursor: pointer;
}
.palette-item:hover, .palette-item.active { background: var(--bg-hover); }
.palette-item.active { box-shadow: inset 2px 0 0 var(--accent); }
.palette-item svg { color: var(--text-muted); flex: none; }
.palette-item-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.palette-item-type { font-size: 11px; color: var(--text-faint); flex: none; }

/* ---- narrow palette (sidebar-rail width, ~64px) ----
   The icon rail collapses the sidebar to 64px; the palette follows and
   becomes a compact icon + truncated-label list. Everything decorative or
   redundant hides (type chips, kbd hints, group titles) so the rows keep
   one icon + one truncated line and nothing overflows or clips mid-word. */
body.palette-narrow .palette-head { padding: 8px; gap: 6px; }
body.palette-narrow .palette-head input { font-size: 12px; }
body.palette-narrow .palette-head .kbd-chip { display: none; }
body.palette-narrow .palette-body { padding: 4px; }
body.palette-narrow .palette-group-title { display: none; }
body.palette-narrow .palette-item { gap: 4px; padding: 6px 4px; }
/* Live search rows at rail width: the type badge (R/D/U) identifies the
   group, so the uppercase group labels and the wrapping "see all" links
   hide; the label + hint keep their two-line truncated shape. */
body.palette-narrow .palette .search-live-group-label { display: none; }
body.palette-narrow .palette .search-live-more { display: none; }
body.palette-narrow .palette .search-live-item { gap: 4px; padding: 6px 4px; }
body.palette-narrow .palette .search-live-type { width: 16px; height: 16px; font-size: 9px; border-radius: 4px; }
body.palette-narrow .palette-item-type { display: none; }
/* The kbd hint row is decorative; at rail width it would wrap into three
   cramped lines, so drop it entirely (the Esc key still closes). */
body.palette-narrow .palette-foot { display: none; }
/* Live search rows are already icon + label + hint; the hint wraps to a
   second truncated line so the 64px width stays usable (compact two-line
   rows). */
.palette .search-live-text { flex: 1; }
.palette-foot {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 16px;
  padding: 8px 14px;
  border-top: 1px solid var(--border);
  font-size: 11px;
  color: var(--text-faint);
}
.palette-hint { display: inline-flex; align-items: center; gap: 4px; }
.palette-hint kbd {
  font-family: var(--font-mono);
  font-size: 10px;
  padding: 1px 4px;
  border: 1px solid var(--border);
  border-radius: 3px;
  background: var(--bg-inset);
}
body.palette-open { overflow: hidden; }
@media (max-width: 560px) {
  .palette-foot { flex-wrap: wrap; gap: 10px; }
}
.kv-grid > .kv-wide { grid-column: 1 / -1; }

/* Collapsible flyout sections (accordion). */
.flyout-section { border: 1px solid var(--border); border-radius: var(--radius); margin-bottom: 12px; overflow: hidden; }
.flyout-section:last-child { margin-bottom: 0; }
.flyout-section > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 10px 14px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 13px;
  color: var(--text);
  background: var(--panel-2);
  transition: background 140ms var(--ease-out);
}
.flyout-section > summary::-webkit-details-marker { display: none; }
.flyout-section > summary:hover { background: var(--bg-hover); }
.flyout-section > summary::after {
  content: "";
  width: 7px;
  height: 7px;
  border-right: 1.6px solid var(--text-muted);
  border-bottom: 1.6px solid var(--text-muted);
  transform: rotate(45deg);
  transition: transform 160ms var(--ease-out);
  flex: none;
}
.flyout-section[open] > summary::after { transform: rotate(-135deg); }
.flyout-section .sec-body { padding: 14px; }
.flyout-section .sec-body > :first-child { margin-top: 0; }
.flyout-section .sec-body > :last-child { margin-bottom: 0; }

/* ---------- 5b. kebab row-menu ---------- */

.row-menu { position: relative; display: inline-block; }
.row-menu-list {
  display: none;
  position: absolute;
  right: 0;
  top: calc(100% + 4px);
  min-width: 184px;
  z-index: 50;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 4px;
  box-shadow: var(--shadow-md);
  max-height: 60vh;
  overflow-y: auto;
}
.row-menu.open .row-menu-list { display: block; }
/* Flip upward when there is not enough room below. app.js sets this while it
   hoists the open list to position:fixed (anchored to the toggle's viewport
   rect, so a scrollable .table-wrap can never clip it); the class also works
   on its own as a pure-CSS fallback. */
.row-menu-list--up {
  top: auto;
  bottom: calc(100% + 4px);
}
.row-menu-item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  text-align: left;
  white-space: nowrap;
  padding: 7px 10px;
  border: 0;
  background: transparent;
  color: var(--text);
  border-radius: calc(var(--radius) - 2px);
  font: inherit;
  font-size: 12.5px;
  cursor: pointer;
  transition: background 140ms var(--ease-out), color 140ms var(--ease-out);
}
.row-menu-item:hover { background: var(--bg-hover); }
.row-menu-item--danger { color: var(--danger); }
.row-menu-item--danger:hover { background: var(--danger-tint); }
.row-menu-item--attention { color: var(--warning); font-weight: 600; }
.row-menu-item--attention:hover { background: var(--warning-tint); }
.row-menu-sep { height: 1px; background: var(--border); margin: 4px 6px; }

/* ---------- 5c. list layout: filter rail + search + data-table ---------- */

.list-layout { display: grid; grid-template-columns: 220px 1fr; gap: 18px; align-items: start; }
.list-main { min-width: 0; }

.filter-rail { position: sticky; top: calc(var(--topbar-height) + 12px); }
.filter-group { margin-bottom: 14px; }
.filter-group > .fg-title {
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
  padding: 6px 8px;
  font-weight: 600;
}
.filter-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 6px 8px;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  font-size: 13px;
  cursor: pointer;
  text-decoration: none;
  transition: background 140ms var(--ease-out), color 140ms var(--ease-out);
}
.filter-item:hover { background: var(--bg-hover); color: var(--text); }
.filter-item.active { background: var(--accent-tint); color: var(--text); }
.filter-item .fi-count {
  font-family: var(--font-mono);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  color: var(--text-faint);
  background: var(--bg-hover);
  border-radius: 999px;
  padding: 0 7px;
}
.filter-item.active .fi-count { color: var(--text); }

/* Mobile filter rail: on narrow viewports the desktop filter rail collapses
   into one "Filters" disclosure above the table so the data table sits near
   the top. The page search stays visible above it — it is the primary
   control. Styled at all sizes; the media query only flips `display`. */
.filter-rail-mobile { display: none; margin-bottom: 12px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--panel); }
.filter-rail-mobile > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 9px;
  min-height: 44px;
  padding: 10px 14px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  user-select: none;
}
.filter-rail-mobile > summary::-webkit-details-marker { display: none; }
.filter-rail-mobile > summary::before {
  content: "";
  width: 14px;
  height: 14px;
  flex: none;
  background: var(--text-muted);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 3H2l8 9.46V19l4 2v-8.54L22 3z'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 3H2l8 9.46V19l4 2v-8.54L22 3z'/%3E%3C/svg%3E") center / contain no-repeat;
}
.filter-rail-mobile > summary::after {
  content: "";
  margin-left: auto;
  width: 7px;
  height: 7px;
  flex: none;
  border-right: 1.5px solid var(--text-muted);
  border-bottom: 1.5px solid var(--text-muted);
  transform: rotate(45deg);
  transition: transform 160ms var(--ease-out);
}
.filter-rail-mobile[open] > summary::after { transform: rotate(-135deg); }
.filter-rail-mobile .frm-chips { display: flex; flex-wrap: wrap; gap: 6px; padding: 2px 14px 14px; }
.filter-rail-mobile .filter-item { border: 1px solid var(--border); }

.list-toolbar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 14px; }
.list-tools { display: flex; align-items: center; gap: 8px; margin-left: auto; flex-wrap: wrap; }

.search-bar {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex: 1 1 240px;
  max-width: 420px;
  padding: 7px 12px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text-muted);
  transition: border-color 140ms var(--ease-out), box-shadow 140ms var(--ease-out);
}
.search-bar:focus-within { border-color: var(--accent); box-shadow: var(--glow-accent-sm); }
.search-bar svg { flex: none; }
.search-bar input {
  flex: 1;
  min-width: 0;
  border: 0;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 13px;
  padding: 0;
}
.search-bar input:focus { outline: none; box-shadow: none; }
.search-bar input:focus-visible { outline: none; }
.search-bar input::placeholder { color: var(--text-faint); }

.data-table { width: 100%; border-collapse: collapse; font-size: 13px; }
/* Compact variant (domains list): the table sizes to its content instead of
   stretching edge-to-edge on wide screens; the VFS column stays capped by
   .cell-ellipsis so long paths truncate instead of inflating the width. */
.data-table-compact { width: auto; }
.data-table th {
  text-align: left;
  font-size: 10.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
  font-weight: 600;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
.data-table td { padding: 10px 14px; border-bottom: 1px solid var(--border); vertical-align: middle; }
.data-table tbody tr { transition: background 140ms var(--ease-out); }
.data-table tbody tr:hover { background: var(--panel-2); }
.data-table tbody tr:last-child td { border-bottom: 0; }
/* Whole-row flyout trigger: any table row carrying data-flyout opens the
   drawer on click/Enter (app.js). Interactive children keep their own
   behaviour — the handler ignores clicks that land on them. */
.data-table tbody tr[data-flyout] { cursor: pointer; }
.data-table tbody tr[data-flyout]:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.data-table .cell-main { font-weight: 500; }
.data-table .cell-muted { color: var(--text-muted); }
.data-table .cell-mono { font-family: var(--font-mono); font-size: 12.5px; font-variant-numeric: tabular-nums; }
.data-table .cell-actions { white-space: nowrap; text-align: right; }
.data-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.data-table th.num { text-align: right; }
.data-table .cell-ellipsis { max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Sortable header: a plain link so it works without JS; the active column
   carries an arrow. Server-driven via ?sort=&dir=. */
.sort-link { color: inherit; text-decoration: none; display: inline-flex; align-items: center; gap: 4px; }
.sort-link:hover { color: var(--text); }
.sort-link .sort-arrow { font-size: 9px; opacity: 0.9; }
.sort-link.is-sorted { color: var(--accent-text); }
th.is-sorted { color: var(--text); }

/* ---------- 4. language switch (segmented control) ---------- */

.lang-switch {
  display: inline-flex;
  align-items: center;
  height: var(--topbar-control-height);
  box-sizing: border-box;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--panel);
}
.lang-switch-label { padding: 0 2px 0 8px; font-size: 12px; line-height: 1; color: var(--text-muted); }
.lang-globe {
  flex: none;
  align-self: stretch;
  height: auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 9px;
  background: var(--bg-inset);
  color: var(--text-muted);
}
.lang-globe svg { display: block; }
.lang-opt {
  border: 0;
  background: transparent;
  color: var(--text-muted);
  font: inherit;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  padding: 0 9px;
  align-self: stretch;
  cursor: pointer;
  transition: background 140ms var(--ease-out), color 140ms var(--ease-out);
}
.lang-opt:hover { background: var(--bg-hover); color: var(--text); }
.lang-opt.active { background: var(--accent-tint); color: var(--accent); }

/* ---------- 5e. status dots + count chips ---------- */

.dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; flex: none; }
.dot-success { background: var(--success); }
.dot-warning { background: var(--warning); }
.dot-danger { background: var(--danger); }
.dot-info { background: var(--info); }
.dot-muted { background: var(--text-faint); }
.dot-pulse { animation: dot-pulse-soft 2.4s ease-in-out infinite; }
@keyframes dot-pulse-soft { 0%, 100% { opacity: 1; } 50% { opacity: 0.45; } }

.count-chip { font-variant-numeric: tabular-nums; }

/* ---------- 5d. responsive shell: burger + off-canvas sidebar ---------- */

.topbar-burger { display: none; }
.sidebar-scrim {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
  z-index: 64;
  opacity: 0;
  transition: opacity 200ms var(--ease-out);
}
.sidebar-scrim.open { opacity: 1; }
.sidebar-scrim[hidden] { display: none; }

/* X mark in the brand lockups (sidebar + portal + public). */
.brand-mark { flex: none; border-radius: 6px; }
.brand-lockup { display: flex; align-items: center; gap: 10px; min-width: 0; }

/* Sidebar collapses to an icon rail at ≤1080px. */
@media (max-width: 1080px) {
  .app-shell { grid-template-columns: var(--sidebar-rail) 1fr; }
  body.sidebar-collapsed .app-shell { grid-template-columns: var(--sidebar-rail) 1fr; }
  .sidebar .brand-logo,
  .sidebar .nav-label,
  .sidebar .nav-count { display: none; }
  .sidebar .nav-group-label { display: none; }
  .sidebar .nav-group { margin-top: 8px; }
  .sidebar-brand { align-items: center; justify-content: center; padding: 0 8px; }
  .sidebar .nav-item { justify-content: center; padding: 10px; }
  .sidebar .nav-item.active::before { left: -6px; }
  #collapse-btn { display: none; }
}


/* ============================================================
   Mobile shell (<=980px) — one coherent model:

   - The six-app sidebar becomes an off-canvas drawer over a scrim
     (burger in the topbar, closes on scrim click / Escape / nav tap,
     >=44px tap targets, full grouped nav + drawer-only extras).
   - The topbar is a SINGLE dense row: [burger] [instance] [search] [menu].
     The language switch, theme toggle, API-docs link, shortcuts hint and
     the session timer move into the drawer / user menu instead of
     wrapping the header into 3-4 rows above the content.
   - Exactly ONE visible search control per screen: list surfaces keep
     their page `.search-bar` (it filters the list) and the topbar's
     global search hides (body.page-list); every other page keeps the
     topbar search.
   - The floating session toast becomes a full-width bottom banner so it
     never overlaps cards/rows at 375px.
   - The filter rail + tag filter + export controls collapse into one
     "Filters" disclosure so the data table sits near the top.
   ============================================================ */
@media (max-width: 980px) {
  /* ---- F1: off-canvas nav drawer ---- */
  .app-shell { grid-template-columns: 1fr; }
  body.sidebar-collapsed .app-shell { grid-template-columns: 1fr; }

  .sidebar {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: min(300px, 84vw);
    height: 100vh;
    height: 100dvh;
    z-index: 70;
    transform: translateX(-100%);
    transition: transform 260ms var(--ease-drawer);
  }
  body.sidebar-open .sidebar { transform: none; box-shadow: var(--shadow-drawer); }
  /* The drawer shows the FULL grouped nav, so restore every label the
     collapsed rail hides, and give items a comfortable 44px tap target. */
  .sidebar .nav-label,
  .sidebar .nav-count { display: inline; }
  .sidebar .nav-group-label { display: block; }
  .sidebar-brand { align-items: center; justify-content: flex-start; padding: 0 16px; }
  .sidebar .brand-logo { display: block; width: 76px; height: auto; }
  .sidebar .nav-item { justify-content: flex-start; padding: 11px 12px; min-height: 44px; }
  .sidebar .nav-item.active::before { left: -10px; }
  .sidebar .nav-group { margin-top: 12px; }
  #collapse-btn { display: none; }
  .drawer-extras {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 12px 10px 14px;
    border-top: 1px solid var(--sidebar-border);
  }
  .drawer-search {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 0 12px;
    height: 44px;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius);
    background: var(--bg-inset);
    color: var(--text-faint);
  }
  .drawer-search:focus-within { border-color: var(--accent); background: var(--panel); }
  .drawer-search svg { flex: none; }
  .drawer-search input {
    flex: 1;
    min-width: 0;
    border: 0;
    outline: 0;
    background: transparent;
    color: var(--text);
    font-family: var(--font-body);
    font-size: 13.5px;
    padding: 0;
  }
  .drawer-search input::placeholder { color: var(--text-faint); }
  /* The drawer keeps the search + the labelled API-docs link; language,
     theme and notifications live under the topbar's user card. */
  .drawer-docs {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 10px 12px;
    border-radius: var(--radius-sm);
    color: var(--sidebar-muted);
    font-size: 13px;
    text-decoration: none;
  }
  .drawer-docs:hover { color: #fff; background: var(--bg-hover); }

  /* ---- F3: single-row dense topbar ---- */
  .topbar {
    flex-wrap: nowrap;
    height: var(--topbar-height);
    padding: 0 12px;
    gap: 10px;
  }
  .topbar-burger { display: inline-flex; width: 44px; height: 44px; flex: none; }
  .topbar > .status-dot { display: none; }
  .topbar > .session-timeout { display: none; }
  .topbar-actions { gap: 4px; }
  .topbar-actions > .shortcuts-hint,
  .topbar-actions > a[href="/docs"] { display: none; }
  /* The consolidated user card is the ONLY remaining actions control: it
     collapses to the avatar (+ unread badge); its menu carries the absorbed
     language/theme/notifications/settings controls. */
  .user-btn { padding: 4px 8px 4px 5px; min-height: 44px; }
  .user-btn > .user-btn-name { display: none; }
  .user-btn > .user-chevron { display: none; }

  /* ---- F2: exactly one visible search per screen ----
     List surfaces carry their own page search (the primary control);
     there the topbar's global search hides. Every other page keeps the
     topbar search as its only search affordance. */
  body.page-list .topbar-search { display: none; }
  /* On phones the bar fills its single-row topbar: the desktop 520px cap
     drops so the control keeps growing with the viewport here. */
  .command-search-wrap { flex: 1 1 auto; min-width: 0; max-width: none; }
  .command-search .kbd-chip { display: none; }

  /* The palette drops from the searchbar; the sidebar is off-canvas here,
     so the panel spans the full viewport width. */
  .palette,
  body.sidebar-collapsed .palette { left: 0; width: 100vw; border-radius: 0; }

  /* ---- F4: compact instance selector, full name in the tooltip ---- */
  .instance-selector { padding: 0 8px 0 10px; gap: 6px; min-width: 0; }
  .instance-selector select { max-width: 118px; font-size: 12px; }
  .scope-chip { padding: 0 9px; }
  .scope-chip .mono {
    max-width: 120px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* ---- F5: session toast as a full-width bottom banner ---- */
  .session-toast {
    left: 0;
    right: 0;
    bottom: 0;
    max-width: none;
    border-radius: 0;
    border-left: 0;
    border-right: 0;
    border-bottom: 0;
    padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
  }

  /* ---- F7: filters + tag filter + export collapse into one disclosure ----
     The disclosure (`.filter-rail-mobile`) carries the status/source chips,
     a mobile copy of the tag filter and the export controls; the desktop
     copies (the toolbar tag input + the standalone export form) hide here
     so each control exists exactly once per viewport. */
  .list-layout { grid-template-columns: 1fr; }
  .filter-rail { display: none; }
  .filter-rail-mobile { display: block; }
  .list-toolbar { gap: 10px; }
  .list-toolbar .search-bar { flex: 1 1 100%; max-width: none; }
  .list-tools { margin-left: 0; flex: 1 1 100%; }
  .list-tools > input[name="tag"] { display: none; }
  .list-main > .export-toolbar { display: none; }
  .bulk-bar { flex-wrap: wrap; }

  /* Mobile filter/export forms inside the disclosure. */
  .mobile-filter-form {
    display: flex;
    align-items: flex-end;
    gap: 8px;
    padding: 0 14px 12px;
  }
  .mobile-filter-field { display: flex; flex-direction: column; gap: 4px; flex: 1; min-width: 0; }
  .mobile-filter-field > span { font-size: 11px; font-weight: 600; color: var(--text-muted); }
  .mobile-filter-field > input { width: 100%; }
  .mobile-export-form {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin: 0 14px 14px;
    padding: 12px 0 0;
    border-top: 1px solid var(--border);
    border-bottom: 0;
  }
  .mobile-export-form input[type="date"] { flex: 1 1 130px; min-width: 0; width: auto; }
  .mobile-export-form .export-label { font-size: 12px; color: var(--text-muted); }
  .mobile-export-form .export-sep { color: var(--text-muted); }

  /* ---- layout audit: no horizontal overflow ---- */
  .app-content { padding: 18px 14px 40px; max-width: none; }
  .app-main, .app-content, .app-page, .app-tab-content,
  .panel, .panel-body, .list-main, .table-wrap,
  .grid-2, .detail-grid, .settings-grid { min-width: 0; }
  /* Grid/flex children default to min-width:auto, so a wide unbreakable cell
     (a long email/URL) can push a panel past the viewport — clamp them. */
  .grid-2 > *, .detail-grid > *, .settings-grid > *,
  .stat-tiles > *, .p-stats > * { min-width: 0; }
  .page-title { overflow-wrap: anywhere; }
  .kv div { flex-wrap: wrap; }
  .kv dd { word-break: break-word; }
  .feed li { flex-wrap: wrap; }
  .feed .feed-action { flex: none; }
  .domain-preview-grid { grid-template-columns: 1fr; gap: 2px; }
  .domain-preview-grid dt { white-space: normal; }
  .domain-preview-grid dd { margin-bottom: 8px; }
  .reject-form { flex-wrap: wrap; }
  .reject-form .btn { flex: none; }
  .inline-form > .form-field { flex: 1 1 100%; min-width: 0 !important; }
  .inline-form > .btn { flex: none; align-self: flex-end; }
  .app-page-head { align-items: stretch; }
  .app-page-actions { flex-wrap: wrap; min-width: 0; max-width: 100%; }
  .panel-header { padding: 12px 14px; }
  .panel-body { padding: 14px; }
  .tab { padding: 10px 12px; }
  .pagination { flex-wrap: wrap; }
  .stat-tiles { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 10px; }
  .stat-value { font-size: 1.9rem; }
  .bar-row { grid-template-columns: 88px 1fr 40px; gap: 8px; }
  .data-table .cell-ellipsis { max-width: 150px; }
  .cell-notes { max-width: 150px; }
  .notes-preview { max-width: 110px; }
  .settings-grid { grid-template-columns: 1fr; }
  .settings-layout { grid-template-columns: 1fr; }
  .settings-nav { position: static; flex-direction: row; flex-wrap: wrap; }
  .settings-nav-title { display: none; }
  .detail-grid { grid-template-columns: 1fr; }

  /* Sticky identity column so horizontal table scroll keeps context. */
  .table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .data-table td:first-child,
  .data-table th:first-child { position: sticky; left: 0; background: var(--panel); z-index: 1; }
  .data-table tbody tr:hover td:first-child { background: var(--panel-2); }

  /* Flyout becomes a full-height sheet on phones. */
  .flyout { top: 0; height: 100%; width: 100vw; max-width: 100vw; }

  /* Public pages keep their own stacking (shared with the old 900px block). */
  .public-shell { grid-template-columns: 1fr; }
  /* The form column is a grid item; its default min-width:auto lets a
     wide min-content descendant (the login-card portal tab row) inflate
     the whole page past the viewport on phones. */
  .public-form-side { min-width: 0; }
  /* The brand panel collapses to a compact brand header on small screens:
     logo + eyebrow + title only — the lead and footer drop, so the form
     reaches the viewport fast instead of sitting below a tall hero. */
  .brand-panel {
    padding: 28px 24px 30px;
    min-height: 0;
    gap: 0;
  }
  .brand-panel .brand-eyebrow { font-size: 10px; }
  .brand-panel .brand-title {
    font-size: 22px;
    line-height: 1.15;
    margin: 8px 0 0;
  }
  .brand-panel .brand-lead { display: none; }
  .brand-panel .steps { display: none; }
  .brand-panel .brand-foot { display: none; }
  .public-faq { margin-top: 28px; }
  /* Mobile: the login card follows the compact brand header directly —
     the desktop top-anchor vh padding would push it off-screen. */
  .public-form-side--login { padding-top: 28px; }
}
/* ---------- 9. Dashboard hero (Radar-style, understated) ----------
   The admin dashboard opens with ONE full-width hero panel: identity +
   live status left, three thin ring gauges center, thin utilization bars
   right, then an inline icon-chip row and a compact ghost quick-action
   row. No big-number card grid, no glows; flat panels, 1px borders,
   small-caps labels, tabular numerals. */

.dash-hero {
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--panel);
  padding: 22px 24px 14px;
  margin-bottom: 18px;
}
.dash-hero-top {
  display: grid;
  grid-template-columns: minmax(220px, 1.1fr) minmax(340px, 1.2fr) minmax(240px, 1fr);
  gap: 28px;
  align-items: start;
}
.dash-hero-kicker {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.dash-hero-title {
  margin: 6px 0 2px;
  font-family: var(--font-display);
  font-size: 24px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.15;
}
.dash-hero-sub { color: var(--text-muted); font-size: 13px; }
.dash-hero-live {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
  font-size: 12px;
  color: var(--text-muted);
}
.dash-hero-refresh {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text-faint);
  transition: color 140ms var(--ease-out), border-color 140ms var(--ease-out);
}
.dash-hero-refresh:hover { color: var(--text); border-color: var(--border-strong); }

/* ---- ring gauges (thin SVG donuts) ---- */

.dash-hero-rings {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: flex-start;
  gap: 12px 24px;
}
/* Equal flex basis gives every gauge the same column (equal gaps, same
   baseline); the min-width lets the trio wrap to centered rows on narrow
   viewports instead of squeezing. */
.dash-ring {
  flex: 1 1 0;
  min-width: 96px;
  max-width: 180px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.dash-ring-svg { position: relative; width: 84px; height: 84px; }
.dash-ring-svg svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.dash-ring-track { fill: none; stroke: var(--panel-3); stroke-width: 6; }
.dash-ring-arc {
  fill: none;
  stroke-width: 6;
  stroke-linecap: round;
  transition: stroke-dasharray 400ms var(--ease-out);
}
.dash-ring-arc.tone-success { stroke: var(--success); }
.dash-ring-arc.tone-warning { stroke: var(--warning); }
.dash-ring-arc.tone-danger { stroke: var(--danger); }
.dash-ring-value {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: 20px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.dash-ring-label {
  margin-top: 8px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.dash-ring-sub { font-family: var(--font-mono); font-size: 11.5px; }
.dash-ring-sub.tone-success { color: var(--success); }
.dash-ring-sub.tone-warning { color: var(--warning); }
.dash-ring-sub.tone-danger { color: var(--danger); }

/* ---- utilization bars (thin, per status) ---- */

.dash-hero-util { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.dash-hero-util-title {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: 2px;
}
.dash-util-row { min-width: 0; }
.dash-util-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 4px;
}
.dash-util-label { font-size: 12px; color: var(--text-muted); }
.dash-util-pct { font-size: 11.5px; color: var(--text-faint); font-variant-numeric: tabular-nums; }
.dash-util-track { height: 5px; border-radius: 999px; background: var(--bg-inset); overflow: hidden; }
.dash-util-fill { display: block; height: 100%; border-radius: 999px; }
.dash-util-row-value .dash-util-head { margin-bottom: 0; }
.dash-util-value {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.dash-util-row .dash-util-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---- hero foot: inline icon chips + browse link ---- */

.dash-hero-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}
.dash-hero-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 18px; }
.dash-chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 2px 4px;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  font-size: 12.5px;
  text-decoration: none;
  transition: background 140ms var(--ease-out), color 140ms var(--ease-out);
}
.dash-chip:hover { background: var(--bg-hover); color: var(--text); }
.dash-chip svg { color: var(--text-faint); flex: none; }
.dash-chip strong {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}
.dash-chip-attention {
  padding: 4px 10px;
  border: 1px solid color-mix(in srgb, var(--warning) 45%, transparent);
  background: color-mix(in srgb, var(--warning) 12%, transparent);
  color: var(--warning);
}
.dash-chip-attention svg { color: var(--warning); }
.dash-chip-attention strong { color: var(--warning); }
.dash-chip-attention:hover {
  background: color-mix(in srgb, var(--warning) 20%, transparent);
  color: var(--warning);
}
.dash-hero-browse { white-space: nowrap; color: var(--text-muted); font-size: 13px; text-decoration: none; }
.dash-hero-browse:hover { color: var(--text); }

/* ---- quick actions: compact ghost row (no card chrome) ---- */

.dash-hero-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}
.dash-quick-label {
  margin-right: 6px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-faint);
}

/* ---- active-issues list (needs attention) ---- */

.dash-issues { list-style: none; margin: 0; padding: 0; }
.dash-issues li {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 9px 2px;
  border-bottom: 1px solid var(--border);
}
.dash-issues li:last-child { border-bottom: 0; }
.dash-issues .dot { margin-top: 6px; flex: none; }
.dash-issue-body { flex: 1; min-width: 0; }
.dash-issue-title {
  display: block;
  font-weight: 500;
  font-size: 13px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Card height discipline: dashboard-card feeds never wrap into tall blocks —
   long audit notes / issue hints clamp to one line with an ellipsis. */
.dash-cell .timeline .tl-note {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dash-cell .timeline .tl-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.dash-issue-hint {
  color: var(--text-faint);
  font-size: 12px;
  font-family: var(--font-mono);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dash-issue-age { font-family: var(--font-mono); font-size: 11.5px; color: var(--text-faint); white-space: nowrap; }

/* ---- overview strip: status bar + legend beside the sparkline ---- */

.dash-overview-flex { display: flex; align-items: stretch; gap: 24px; }
.dash-overview-main {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 12px;
}
.dash-overview-main .dash-statusbar { height: 8px; }
.dash-overview-flex .dash-spark-block {
  flex: 0 0 220px;
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}

/* ---- admin grid areas (hero replaces the quick-actions/overview cells) ---- */

.dash-role-admin {
  grid-template-columns: repeat(12, 1fr);
  grid-template-areas:
    "attention attention attention attention attention attention attention activity activity activity activity activity"
    "reminders reminders reminders reminders reminders reminders recent recent recent recent recent recent"
    "overview overview overview overview overview overview overview overview overview overview overview overview"
    "instances instances instances instances instances instances status status status status status status"
    "messaging messaging messaging messaging messaging messaging messaging messaging messaging messaging messaging messaging";
}

@media (max-width: 1180px) {
  .dash-role-admin {
    grid-template-areas:
      "attention attention attention attention attention attention attention attention attention attention attention attention"
      "activity activity activity activity activity activity activity activity activity activity activity activity"
      "reminders reminders reminders reminders reminders reminders reminders reminders reminders reminders reminders reminders"
      "recent recent recent recent recent recent recent recent recent recent recent recent"
      "overview overview overview overview overview overview overview overview overview overview overview overview"
      "instances instances instances instances instances instances instances instances instances instances instances instances"
      "status status status status status status status status status status status status"
      "messaging messaging messaging messaging messaging messaging messaging messaging messaging messaging messaging messaging";
  }
  .dash-hero-top { grid-template-columns: 1fr 1fr; }
  .dash-hero-util { grid-column: 1 / -1; }
}

@media (max-width: 980px) {
  .dash-hero { padding: 18px 16px 10px; }
  .dash-hero-top { grid-template-columns: 1fr; gap: 20px; }
  .dash-hero-rings { justify-content: flex-start; }
  .dash-hero-foot { flex-direction: column; align-items: flex-start; }
  .dash-overview-flex { flex-direction: column; }
  .dash-overview-flex .dash-spark-block { flex: none; }
}

@media (max-width: 640px) {
  .dash-hero-top { gap: 16px; }
  .dash-ring { min-width: 80px; }
  .dash-ring-svg { width: 72px; height: 72px; }
  .dash-ring-value { font-size: 18px; }
  .dash-hero-actions { gap: 6px; }
  .dash-quick-label { font-size: 9.5px; }
}

/* ---------- 10. Observability (Radar-style timeline / logging / metrics / issues) ---------- */

.obs-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 10px; }
.obs-chips-label {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-right: 4px;
}
.obs-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: transparent;
  color: var(--text-muted);
  font-size: 12px;
  text-decoration: none;
  transition: border-color 150ms ease, color 150ms ease, background 150ms ease;
}
.obs-chip:hover { border-color: var(--border-strong); color: var(--text); }
.obs-chip.active { border-color: var(--accent); color: var(--text); background: var(--danger-tint); }
.obs-chip .count-chip { color: var(--text-faint); font-size: 11px; }

/* vertical event stream */
.obs-stream { list-style: none; margin: 6px 0 0; padding: 0; }
.obs-stream li {
  display: grid;
  grid-template-columns: 12px minmax(0, 1fr) auto auto auto;
  align-items: baseline;
  gap: 12px;
  padding: 9px 2px;
  border-bottom: 1px solid var(--border);
}
.obs-stream li:last-child { border-bottom: 0; }
.obs-stream .dot { align-self: center; }
.obs-event-title { font-weight: 500; font-size: 13px; overflow-wrap: anywhere; }
.obs-event-note { color: var(--text-muted); font-size: 12px; overflow-wrap: anywhere; }
.obs-event-entity { color: var(--info); text-decoration: none; }
.obs-event-entity:hover { color: var(--accent); }
.obs-event-actor { color: var(--text-muted); font-size: 12px; }
.obs-event-time { color: var(--text-faint); font-size: 11.5px; white-space: nowrap; }

/* logging */
.obs-log-table td, .obs-log-table th { font-size: 12px; }
.obs-log-table .obs-log-row td { font-family: var(--font-mono); }
.obs-log-table .obs-log-row td.cell-main { font-family: var(--font-sans); }
.obs-log-payload-row td { background: var(--panel-2); padding: 10px 14px; }
.obs-log-payload-label {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: 6px;
}
.obs-log-payload-row pre { margin: 0; max-height: 260px; overflow: auto; }

/* metrics */
.obs-cache-note { color: var(--text-faint); font-size: 11.5px; }
.obs-metric-section { min-width: 0; }
.obs-metric-section--platform { border-style: dashed; }
.obs-metric-section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 10px;
}
.obs-metric-section-title {
  margin: 0;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: -0.01em;
}
.obs-metric-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 6px 0;
  border-bottom: 1px solid var(--border-subtle, #ffffff0a);
}
.obs-metric-row:last-child { border-bottom: 0; }
.obs-metric-label {
  font-size: 12.5px;
  color: var(--text-muted);
  min-width: 0;
}
.obs-metric-def {
  display: block;
  font-size: 11px;
  color: var(--text-faint);
  font-weight: 400;
  letter-spacing: 0;
  margin-top: 1px;
}
.obs-metric-row .obs-metric-value {
  font-size: 16px;
  margin: 0;
  flex-shrink: 0;
}
.obs-metric-spark { margin-top: 8px; color: var(--tile-accent, var(--text-faint)); }
.obs-spark { display: block; width: 100%; height: 26px; }
.obs-scope-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 2px 0 10px;
}
.obs-scope-label {
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.obs-scope-chip {
  font-size: 12px;
  color: var(--text);
  background: var(--bg-hover);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 2px 10px;
}
.obs-window-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin-bottom: 16px;
}
.obs-window-bar .fg-title { padding: 6px 8px 6px 0; }
.obs-window-bar .filter-item { padding: 4px 10px; }

.obs-funnel { margin-top: 22px; display: flex; flex-direction: column; gap: 8px; max-width: 640px; }
.obs-funnel-row { display: grid; grid-template-columns: 110px 1fr 48px; align-items: center; gap: 12px; }
.obs-funnel-label { color: var(--text-muted); font-size: 12.5px; }
.obs-funnel-count { text-align: right; font-variant-numeric: tabular-nums; }

/* issues */
.obs-issues-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
  gap: 14px;
}
.obs-issue {
  border: 1px solid var(--border);
  border-left-width: 3px;
  border-radius: var(--radius);
  background: var(--panel-2);
  padding: 14px 16px;
  min-width: 0;
}
.obs-issue.sev-danger { border-left-color: var(--danger); }
.obs-issue.sev-warning { border-left-color: var(--warning); }
.obs-issue.sev-info { border-left-color: var(--info); }
.obs-issue.sev-success { border-left-color: var(--success); }
.obs-issue-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.obs-issue-title { font-size: 14px; font-weight: 600; margin: 0; flex: 1; min-width: 0; }
.obs-issue-why, .obs-issue-fix { margin: 0 0 6px; font-size: 12.5px; color: var(--text-muted); line-height: 1.5; }
.obs-issue-why strong, .obs-issue-fix strong { color: var(--text); font-weight: 600; }
.obs-issue-items { list-style: none; margin: 8px 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.obs-issue-items a {
  display: inline-block;
  padding: 2px 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--panel);
  color: var(--text-muted);
  font-size: 11.5px;
}
.obs-issue-items a:hover { color: var(--info); border-color: var(--border-strong); }
.obs-issue-viewall { font-size: 12px; color: var(--text-muted); text-decoration: none; }
.obs-issue-viewall:hover { color: var(--text); }

.obs-all-clear {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 42px 20px;
  text-align: center;
}
.obs-all-clear h2 { margin: 0; font-size: 16px; color: var(--success); }
.obs-all-clear p { margin: 0; max-width: 460px; color: var(--text-muted); font-size: 13px; line-height: 1.55; }

/* checks inventory (comprehensive subsystem view above the issue groups) */
.obs-checks-table th, .obs-checks-table td { font-size: 12px; }
.obs-checks-table .obs-check-status-col { width: 22px; padding-right: 0; }
.obs-check .dot { vertical-align: middle; }
.obs-check-title { font-weight: 500; font-size: 12.5px; color: var(--text); text-decoration: none; }
a.obs-check-title:hover { color: var(--info); }
.obs-check-scope { margin-left: 8px; color: var(--text-muted); font-size: 11.5px; }
.obs-check-detail { color: var(--text-muted); }
.obs-check-time { color: var(--text-faint); font-size: 11.5px; white-space: nowrap; }
.obs-checks-note { margin: 10px 0 0; color: var(--text-faint); font-size: 11.5px; }

@media (max-width: 980px) {
  .obs-stream li { grid-template-columns: 12px minmax(0, 1fr); }
  .obs-event-entity, .obs-event-actor, .obs-event-time { grid-column: 2; }
  .obs-funnel-row { grid-template-columns: 90px 1fr 44px; }
}

@media (max-width: 640px) {
  /* Hide less critical columns on narrow screens */
  .obs-log-table th:nth-child(3), /* Kind */
  .obs-log-table td:nth-child(3),
  .obs-log-table th:nth-child(7), /* IP */
  .obs-log-table td:nth-child(7) {
    display: none;
  }
}

@media (max-width: 640px) {
  /* Stack observability toolbar elements vertically on narrow screens */
  .obs-workbench .list-toolbar {
    flex-direction: column;
    align-items: stretch;
  }
  .obs-workbench .list-toolbar .search-bar {
    width: 100%;
  }
  .obs-workbench .list-toolbar > label,
  .obs-workbench .list-toolbar > input[type="date"],
  .obs-workbench .list-toolbar > button,
  .obs-workbench .list-toolbar > a.btn {
    width: 100%;
    margin-left: 0;
  }
  .obs-workbench .list-toolbar > input[type="date"] {
    max-width: none;
  }
}

/* ---------- 11. Radar resources-page list anatomy ----------
   The standard list-page look (registrations / organizations / users and the
   secondary list surfaces): no card chrome around the table, a flat page
   header, a Radar toolbar (search + view controls + live auto-update chip),
   an icon filter rail with count/warning badges, and a dense sortable table
   with status pills, mono identifiers, utilization bars and compact ages.
   Scoped under body.page-list / .radar-* classes so other surfaces are
   untouched. */

/* Flat page header (title left, actions right) — replaces the app shell. */
.radar-page-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-bottom: 14px; }
.radar-page-head .page-title { font-size: 20px; }
.radar-page-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

/* List surfaces drop the card chrome: the table sits directly on the page
   background with hairline separators, like Radar's resources tables. */
body.page-list .panel { background: transparent; border: 0; box-shadow: none; border-radius: 0; }
body.page-list .panel + .panel { margin-top: 24px; }
body.page-list .panel-header { padding: 0 0 10px; border-bottom: 1px solid var(--border); }
body.page-list .panel-body { padding: 0; }
body.page-list .list-layout { gap: 22px; }

/* Filter rail: Radar-style items = icon + label + count badge + warn badge. */
.filter-item .fi-icon { display: inline-flex; flex: none; color: var(--text-faint); }
.filter-item.active .fi-icon { color: var(--accent-text); }
.filter-item .fi-label { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.filter-item .fi-warn {
  font-family: var(--font-mono);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  color: var(--danger);
  background: var(--danger-tint);
  border-radius: 999px;
  padding: 0 7px;
}

/* Radar toolbar: search left, view controls + live chip right. */
.radar-toolbar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 12px; }
.radar-toolbar .search-bar {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex: 1 1 260px;
  max-width: 460px;
  padding: 6px 10px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text-muted);
  transition: border-color 140ms var(--ease-out), box-shadow 140ms var(--ease-out), max-width 200ms var(--ease-out);
}
.radar-toolbar .search-bar:focus-within { border-color: var(--accent); box-shadow: var(--glow-accent-sm); }
.radar-toolbar .search-bar input { flex: 1; min-width: 0; border: 0; background: transparent; color: var(--text); font: inherit; font-size: 13px; padding: 0; }
.radar-toolbar .search-bar input:focus, .radar-toolbar .search-bar input:focus-visible { outline: none; box-shadow: none; }
.radar-toolbar .search-bar input::placeholder { color: var(--text-faint); }
.radar-toolbar .search-bar .radar-search-expand { opacity: 0.65; }
.radar-toolbar .search-bar .radar-search-expand:hover { opacity: 1; }
.radar-toolbar .search-bar.radar-search--wide { max-width: 720px; }
.radar-tools { display: flex; align-items: center; gap: 8px; margin-left: auto; flex-wrap: wrap; }
/* Users surface chrome: instance tabs (directory folded in) + the cache
   meta row ("data as of" stamp, refreshing chip, manual refresh). */
.users-instance-tabs { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; }
.users-instance-tab {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 5px 12px;
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--text-muted);
  background: var(--panel);
  font-size: 12.5px;
  text-decoration: none;
  transition: border-color 140ms var(--ease-out), color 140ms var(--ease-out), background 140ms var(--ease-out);
}
.users-instance-tab:hover { border-color: var(--border-emphasis); color: var(--text); }
.users-instance-tab.active {
  border-color: var(--accent);
  color: var(--text);
  background: color-mix(in srgb, var(--accent) 12%, var(--panel));
}
.users-instance-tab .count-chip { margin-left: 0; }
.users-cache-meta {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 10px;
  font-size: 12px;
}
.users-cache-meta .users-refreshing { display: inline-flex; align-items: center; gap: 6px; }
.users-refresh-form { display: inline-flex; margin-left: auto; }

/* View toggle (table/grid) segmented pair. */
.radar-view-toggle { display: inline-flex; align-items: center; gap: 2px; padding: 2px; background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-sm); }
.radar-view-btn { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 24px; border: 0; border-radius: 4px; background: transparent; color: var(--text-faint); cursor: pointer; transition: background 140ms var(--ease-out), color 140ms var(--ease-out); }
.radar-view-btn:hover { color: var(--text); }
.radar-view-btn.active { background: var(--bg-active); color: var(--text); }

/* Live auto-updating indicator: green dot, pulses on each refresh tick. */
.radar-live { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--success); white-space: nowrap; }
.radar-live-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--success); box-shadow: 0 0 0 0 var(--success-tint); }
.radar-live.is-pulsing .radar-live-dot { animation: radar-live-pulse 900ms var(--ease-out); }
@keyframes radar-live-pulse {
  0% { box-shadow: 0 0 0 0 rgba(63, 178, 127, 0.5); }
  100% { box-shadow: 0 0 0 9px rgba(63, 178, 127, 0); }
}
@media (prefers-reduced-motion: reduce) { .radar-live.is-pulsing .radar-live-dot { animation: none; } }

/* Dense table: ~48px rows, hairline separators, tighter header. */
body.page-list .data-table { font-size: 12.5px; }
body.page-list .data-table th { padding: 8px 12px; font-size: 10px; }
body.page-list .data-table tbody tr[data-flyout] td { padding: 8px 12px; height: 48px; }
body.page-list .data-table tbody tr:not([data-flyout]) td { height: auto; padding-top: 0; }
body.page-list .data-table tbody tr:hover { background: var(--bg-hover); }
body.page-list .data-table .cell-mono { font-size: 12px; }

/* Status pills (Radar): dot + label, toned, no box. */
.pill { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 500; white-space: nowrap; }
.pill-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.pill-success { color: var(--success); } .pill-success .pill-dot { background: var(--success); }
.pill-warning { color: var(--warning); } .pill-warning .pill-dot { background: var(--warning); }
.pill-danger { color: var(--danger); } .pill-danger .pill-dot { background: var(--danger); }
.pill-info { color: var(--info); } .pill-info .pill-dot { background: var(--info); }
.pill-neutral { color: var(--text-muted); } .pill-neutral .pill-dot { background: var(--text-faint); }
.pill-pulse .pill-dot { animation: pill-pulse 1.6s ease-in-out infinite; }
@keyframes pill-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
@media (prefers-reduced-motion: reduce) { .pill-pulse .pill-dot { animation: none; } }

/* Compact inline-flex cell (tags count etc.). Lists never render
   horizontal utilization bars — keep rows dense. */
.util-cell { display: inline-flex; align-items: center; gap: 8px; }

/* Numeric emphasis (restarts-style): amber when non-zero. */
.num-warn { color: var(--warning); font-weight: 600; }

/* Grid view: the dense table reflows into cards. */
body.page-list .radar-list[data-view="grid"] .table-wrap { overflow: visible; }
body.page-list .radar-list[data-view="grid"] .data-table thead { display: none; }
body.page-list .radar-list[data-view="grid"] .data-table,
body.page-list .radar-list[data-view="grid"] .data-table tbody { display: block; }
body.page-list .radar-list[data-view="grid"] .data-table tbody { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 12px; }
body.page-list .radar-list[data-view="grid"] .data-table tr[data-flyout] {
  display: flex; flex-direction: column; gap: 6px;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--panel); padding: 12px 14px;
}
body.page-list .radar-list[data-view="grid"] .data-table tr[data-flyout] td { display: flex; align-items: center; gap: 8px; border: 0; padding: 2px 0; height: auto; }
body.page-list .radar-list[data-view="grid"] .data-table tr[data-flyout] td.cell-main { font-size: 13px; }
body.page-list .radar-list[data-view="grid"] .data-table .reject-row,
body.page-list .radar-list[data-view="grid"] .data-table .domain-edit-row,
body.page-list .radar-list[data-view="grid"] .data-table .domain-verify-row,
body.page-list .radar-list[data-view="grid"] .data-table .domain-preview-row { display: none; }

@media (max-width: 980px) {
  .radar-page-head { margin-bottom: 10px; }
  .radar-toolbar { gap: 8px; }
  .radar-toolbar .search-bar { max-width: none; }
  body.page-list .data-table td { height: auto; }
}

/* Dense-list refinements: keep chips inline and rows ~48-54px on wide and
   1280px viewports (the table must not wrap its inline controls). */
body.page-list .tag-chips { display: inline-flex; flex-wrap: nowrap; gap: 4px; vertical-align: middle; max-width: 140px; overflow: hidden; }
body.page-list .tag-chip { white-space: nowrap; }
body.page-list .cell-notes { max-width: 170px; }
body.page-list .notes-preview { max-width: 96px; }
body.page-list .notes-edit-toggle { margin-left: 2px; padding: 2px 6px; font-size: 11px; }
body.page-list .data-table td.cell-main .cell-muted { font-size: 11.5px; }
body.page-list .util-cell { gap: 6px; }
body.page-list .radar-toolbar .search-bar { flex: 0 1 420px; }
body.page-list .export-toolbar { margin-bottom: 10px; }
@media (max-width: 1440px) {
  body.page-list .data-table td { padding: 8px 10px; }
  body.page-list .data-table th { padding: 8px 10px; }
  body.page-list .cell-notes { max-width: 130px; }
  body.page-list .notes-preview { max-width: 70px; }
  body.page-list .tag-chips { max-width: 110px; }
}

/* Radar dense tables: the inline expand rows (reject / edit / notes / policy /
   verify / preview) collapse to zero height until their toggle opens them, so
   the table reads as one continuous dense list. Scoped to the list panels. */
#registrations-panel tr.reject-row,
#domains-panel tr.domain-edit-row,
#domains-panel tr.domain-verify-row { display: none; }
#registrations-panel tr.reject-row:has(.reject-form.open),
#domains-panel tr.domain-edit-row:has(.reject-form.open),
#domains-panel tr.domain-verify-row.open { display: table-row; }

/* 1280-1440px: trim secondary columns so the row kebab stays visible without
   horizontal scrolling (the trimmed data remains in the rail / flyout). */
@media (max-width: 1440px) {
  #registrations-panel .data-table thead th:nth-child(7),
  #registrations-panel .data-table tr[data-flyout] > td:nth-child(7),
  #registrations-panel .data-table thead th:nth-child(9),
  #registrations-panel .data-table tr[data-flyout] > td:nth-child(9) { display: none; }
  #domains-panel .data-table thead th:nth-child(5),
  #domains-panel .data-table tr[data-flyout] > td:nth-child(5),
  #domains-panel .data-table thead th:nth-child(8),
  #domains-panel .data-table tr[data-flyout] > td:nth-child(8) { display: none; }
}

/* ---------- 12. Messaging (portal ↔ admin threads, chat-style redesign) ---------- */
.msg-layout {
  display: grid;
  grid-template-columns: minmax(280px, 360px) 1fr;
  gap: 16px;
  align-items: stretch;
}
@media (max-width: 980px) {
  .msg-layout { grid-template-columns: 1fr; }
}
.msg-thread-list { display: flex; flex-direction: column; max-height: calc(100vh - 190px); min-height: 420px; overflow: hidden; }
.msg-search { padding: 10px 12px 4px; border-bottom: 1px solid var(--border-subtle); }
.msg-search input { width: 100%; }
.msg-thread-scroll { overflow-y: auto; flex: 1; }
.msg-thread-items { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.msg-thread-item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 9px 12px;
  border-radius: 8px;
  border: 1px solid transparent;
  color: var(--text);
  text-decoration: none;
  transition: background 120ms var(--ease-out);
}
.msg-thread-item:hover { background: var(--bg-hover); }
.msg-thread-item.is-active { background: var(--bg-active); border-color: var(--border-subtle); }
.msg-thread-avatar {
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  font-weight: 700;
  color: var(--text-muted);
  background: var(--panel-2);
  border: 1px solid var(--border-subtle);
}
.msg-thread-avatar-lg { width: 36px; height: 36px; font-size: 14px; }
.msg-thread-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.msg-thread-topline { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.msg-thread-name { font-size: 12.5px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msg-thread-org { font-size: 11px; color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msg-thread-preview { font-size: 12px; color: var(--text-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msg-preview-you { color: var(--text-muted); }
.msg-thread-age { font-size: 10.5px; color: var(--text-faint); flex: 0 0 auto; }
.msg-thread-empty { padding: 12px; color: var(--text-faint); font-size: 13px; }
.msg-thread-item.has-unread .msg-thread-name { color: var(--text); }
.msg-thread-item.has-unread .msg-thread-preview { color: var(--text-muted); font-weight: 500; }
.msg-unread-chip {
  flex: 0 0 auto;
  align-self: center;
  min-width: 18px;
  padding: 1px 6px;
  border-radius: 999px;
  font-size: 10.5px;
  font-weight: 700;
  text-align: center;
  color: var(--info);
  background: var(--info-tint);
}
.msg-thread-item.has-unread .msg-thread-avatar { border-color: color-mix(in srgb, var(--info) 45%, var(--border-subtle)); }
.msg-pagination {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 8px 12px;
  border-top: 1px solid var(--border-subtle);
}
.msg-thread-header { gap: 10px; align-items: center; }
.msg-thread-identity { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.msg-live-chip { margin-left: auto; flex: 0 0 auto; }
.msg-panel-body { display: flex; flex-direction: column; position: relative; }
.msg-list {
  list-style: none;
  margin: 0 0 12px;
  padding: 6px 4px;
  height: 440px;
  max-height: 60vh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.msg { display: flex; max-width: 78%; }
.msg--mine { align-self: flex-end; justify-content: flex-end; }
.msg--theirs { align-self: flex-start; }
/* Legacy side classes (old server renders / tests) keep the same alignment:
   the portal user's messages sit left in the admin view and right in the
   portal view, so the templates drive the real classes; these stay for the
   dashboard-era markup. */
.msg--portal { align-self: flex-start; }
.msg--admin { align-self: flex-end; }
.msg-bubble {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
.msg--mine .msg-bubble { align-items: flex-end; }
.msg-body {
  padding: 8px 12px;
  border-radius: 12px;
  font-size: 13.5px;
  line-height: 1.45;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  max-width: 100%;
}
.msg--theirs .msg-body {
  background: var(--panel-2);
  border: 1px solid var(--border-subtle);
  border-bottom-left-radius: 4px;
}
.msg--mine .msg-body {
  background: color-mix(in srgb, var(--accent) 16%, var(--panel-2));
  border: 1px solid color-mix(in srgb, var(--accent) 35%, var(--border-subtle));
  border-bottom-right-radius: 4px;
}
.msg-meta { display: flex; align-items: center; gap: 8px; font-size: 10.5px; color: var(--text-faint); flex-wrap: wrap; }
.msg--mine .msg-meta { justify-content: flex-end; }
.msg-meta .msg-sender { color: var(--text-muted); font-weight: 600; letter-spacing: 0.02em; }
.msg-day-sep { align-self: center; list-style: none; display: flex; }
.msg-day-sep span {
  font-size: 10.5px;
  color: var(--text-faint);
  background: var(--panel-2);
  border: 1px solid var(--border-subtle);
  border-radius: 999px;
  padding: 2px 10px;
}
.msg-new-pill {
  position: sticky;
  bottom: 8px;
  align-self: center;
  z-index: 2;
  border: 1px solid var(--border-subtle);
  border-radius: 999px;
  background: var(--panel-2);
  color: var(--text);
  font-size: 12px;
  padding: 5px 14px;
  cursor: pointer;
  box-shadow: var(--shadow-sm);
}
.msg-new-pill:hover { background: var(--bg-hover); }
.msg--empty { color: var(--text-faint); font-size: 13px; padding: 8px 4px; max-width: none; }
.msg-composer { display: flex; flex-direction: column; gap: 6px; border-top: 1px solid var(--border-subtle); padding-top: 12px; }
.msg-composer textarea {
  width: 100%;
  resize: none;
  min-height: 44px;
  max-height: 220px;
  overflow-y: auto;
}
.msg-composer-actions { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.msg-composer-hint { flex: 1; min-width: 140px; }
.msg-draft-note { color: var(--text-faint); }
.msg-counter { flex: 0 0 auto; color: var(--text-faint); font-size: 11px; }
.msg-counter.is-warn { color: var(--warning); font-weight: 600; }
.settings-section-subtitle {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-muted);
  margin: 4px 0 8px;
}
.portal-password-form { display: flex; flex-direction: column; gap: 14px; max-width: 460px; }
@media print {
  .msg-composer, .msg-thread-list { display: none; }
}

/* ---------- 13. Scope picker (admin accounts) ---------- */
/* `.banner` is display:flex, which overrides the UA [hidden]{display:none};
   the scope-picker warning toggles hidden in JS, so restore hidden semantics
   inside it (same sharp edge as .session-toast[hidden]). */
.scope-picker-warning[hidden] { display: none; }

.scope-picker {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-inset);
  padding: 12px;
}
.scope-picker-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
}
.scope-picker-count {
  font-size: 12px;
  color: var(--text-muted);
  margin-right: auto;
}
.scope-picker-count strong { color: var(--text); font-weight: 600; }
.scope-picker-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 240px;
  overflow-y: auto;
  padding-right: 4px;
}
.scope-picker-item { margin-right: 0; }
.scope-picker-warning { margin-top: 10px; margin-bottom: 0; }

.account-scope-chips { max-width: 260px; }
.account-scope-chips .tag-chip { overflow: hidden; text-overflow: ellipsis; max-width: 140px; }

.account-create-form {
  display: flex;
  align-items: flex-end;
  gap: 12px;
  flex-wrap: wrap;
}
.account-create-form .form-field { min-width: 180px; }
.account-scope-details { width: 100%; border: 0; }
.account-scope-details[hidden] { display: none; }
.account-scope-details summary { cursor: pointer; font-size: 13px; font-weight: 600; }
.account-scope-details .scope-picker { margin-top: 8px; }
/* ---------- CSP utility classes (auto-generated; replace inline style attrs) ----------
   Enforced Content-Security-Policy forbids inline style attributes. Each unique
   former style="..." value maps to one class. Do not edit by hand. ---------- */
.su-03b6501a { display: inline-flex; align-items: center; gap: 7px; }
.su-045aac89 { margin-bottom: 16px; }
.su-082f6e5d { margin-top: 6px; }
.su-097d766c { --d:190ms; grid-area: activity; }
.su-0af04112 { padding: 18px; }
.su-0b2a28da { display: inline; margin: 0; }
.su-116e7aa6 { padding-left: 0; padding-right: 0; }
.su-17d8c5ec { white-space: pre-wrap; }
.su-1c93056d { margin: 0; flex: 1.6; min-width: 280px; }
.su-1fdc68b9 { --d:60ms; grid-area: domains; }
.su-217a0384 { color: var(--text-faint); font-size: 12.5px; margin-top: 10px; }
.su-27e4afda { margin: 0; flex: 1; min-width: 200px; }
.su-2d847d26 { margin: 0; flex: 0.8; min-width: 180px; }
.su-2d98adf5 { margin-bottom: 10px; }
.su-2e70955c { width: 100%; margin-top: 12px; text-align: center; }
.su-30ccd9bd { width: 100%; padding: 10px; font-size: 14px; }
.su-31526477 { align-self: flex-end; }
.su-342d988c { margin-top: 0.75rem; }
.su-35208e02 { margin: 0 0 14px; }
.su-36ca0aff { margin-top: 8px; }
.su-3728cf3d { --d:330ms; grid-area: recent; }
.su-384c5cb3 { margin: 0; flex: 1; min-width: 220px; }
.su-3907588b { margin-bottom: 14px; }
.su-3a08a48b { margin: 0; flex: 0.5; min-width: 90px; }
.su-3f2f2324 { --d:60ms; grid-area: reminders; }
.su-4379f268 { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; padding: 4px 0 8px; }
.su-4880b78e { margin: 0; flex: 1.4; min-width: 200px; }
.su-48eceef3 { margin: 0; flex: 1; min-width: 140px; }
.su-4feedf8e { margin-bottom: 6px; }
.su-508e5700 { margin: 0 0 10px; }
.su-52fd16b2 { margin: 0; flex: 1; min-width: 160px; }
.su-54a4ec42 { --d:130ms; grid-area: pending; }
.su-54d32d80 { margin-top: 10px; }
.su-5685054f { margin: 0; padding-left: 1.2em; }
.su-57947bfa { --d:470ms; grid-area: instances; }
.su-5a2ddf45 { --d:610ms; grid-area: messaging; }
.su-5cd864ec { margin: 6px 0 0; }
.su-5e342f3c { --d:130ms; grid-area: compliance; }
.su-5eaf8cb5 { color: var(--text-faint); font-size: 12.5px; margin-top: 18px; }
.su-5eee5111 { padding: 18px 18px 0; }
.su-6468396c { width: 100%; padding: 10px; }
.su-693434c7 { display: flex; gap: 8px; }
.su-696b8a28 { flex-wrap: wrap; }
.su-69d66e5b { width: 100%; }
.su-6b82cf24 { display: flex; }
.su-6c63b477 { margin: 4px 0 0; }
.su-6cc9ca22 { margin: 0; flex: 1.4; min-width: 220px; }
.su-6f50c177 { max-width: 140px; }
.su-72d6c38e { margin-bottom: 12px; }
.su-78a38cdd { margin: 0; white-space: pre-wrap; }
.su-7beda6e8 { --d:200ms; grid-area: status; }
.su-81a8278d { margin: 0; flex: 1.2; min-width: 200px; }
.su-825ff003 { flex-direction: column; align-items: flex-start; gap: 8px; }
.su-83682381 { margin: 4px 0 12px; }
.su-8d1f4ab8 { max-width: 200px; }
.su-8eb78c30 { display: flex; align-items: center; gap: 4px; margin-top: 12px; font-size: 11px; color: var(--text-muted); }
.su-91ab1f31 { --d:60ms; grid-area: funnel; }
.su-9293e652 { --d:540ms; grid-area: status; }
.su-97e3f640 { --d:130ms; grid-area: failures; }
.su-98ff738f { padding: 12px 18px; }
.su-99bbdd6a { --d:200ms; grid-area: failures; }
.su-9c9cee20 { margin-top: 12px; }
.su-9eecdd02 { --d:200ms; grid-area: activity; }
.su-a03fcec0 { --d:270ms; grid-area: exports; }
.su-a1e40f7c { color: var(--text-muted); font-size: 13px; }
.su-a39ddebf { margin: 0; flex-basis: 100%; flex-direction: row; align-items: center; gap: 18px; }
.su-a7dc9bf6 { flex: 2; min-width: 320px; }
.su-a9cd8e0e { padding-top: 0; border-bottom: 1px solid var(--border); }
.su-ad0821fa { margin: 12px 0 0; }
.su-af383d3e { max-width: 420px; }
.su-b1230a0e { margin: 0; flex: 1.4; min-width: 260px; }
.su-b26aeceb { margin-top: 14px; }
.su-b57afc0a { margin-bottom: 0.75rem; }
.su-c05fb4d9 { font-size: 11.5px; margin-bottom: 0.25rem; }
.su-c3122899 { margin-top: 0; }
.su-c5935419 { --d:40ms; }
.heatmap { display: grid; grid-template-rows: repeat(7, 13px); grid-auto-flow: column; grid-auto-columns: 13px; gap: 3px; justify-content: start; }
.su-cc6bade1 { --d:120ms; grid-area: attention; }
.su-cdeaae65 { margin: 6px 0; }
.su-ce7fde71 { margin: 0; flex: 1.4; min-width: 180px; }
.su-d1be7e7c { --d:260ms; grid-area: reminders; }
.su-d2f3f473 { white-space: pre-wrap; margin-bottom: 14px; }
.su-d3409764 { margin: 0; flex: 1.4; min-width: 240px; }
.su-d3b40963 { --d:60ms; }
.su-d40474f3 { flex-wrap: wrap; margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--border); }
.su-d4f98a42 { --d:340ms; grid-area: messaging; }
.su-d5b43342 { grid-column: 1 / -1; }
.su-de2395bf { max-width: 160px; }
.su-e1c153d2 { margin: 0; flex: 1; min-width: 240px; }
.su-e3a52ac7 { --d:270ms; grid-area: recent; }
.su-e40c8fc4 { margin: 0 0 12px; }
.su-e527aefa { margin: 0; flex: 1; min-width: 180px; }
.su-e9e0e4af { font-size: 11px; }
.su-eefff2f8 { font-size: 13px; }
.su-f1cc36d6 { color: var(--text-faint); font-size: 12.5px; margin-top: 14px; }
.su-f46470eb { margin: 10px 0 0; }
.su-f5a84850 { --d:400ms; grid-area: overview; }
.su-f608dc7e { border-bottom: 1px solid var(--border); }
.su-f75d63c1 { color: var(--danger); }
.su-fe21d42a { max-width: 120px; }
.su-fe81f59b { color: var(--text-faint); font-size: 12.5px; }
.su-ff227d06 { margin: 0; }
.su-ffbfccfe { margin: 8px 0 0; }
/* CSP companion classes for the data-attr driven dynamic styles
   (app/static/ui-metrics.js applies the values over the CSSOM). */
.p-barchart-fill--muted { opacity: 0.35; }
.stats-heat-cell { width: 13px; height: 13px; border-radius: 3px; background: var(--bg-inset); }

/* The theme toggle icons hide via the `hidden` attribute (CSP-safe: inline
   style="display:none" is not allowed; theme-toggle.js toggles CSSOM
   style.display which wins over the attribute). The UA stylesheet only hides
   [hidden] for block-level boxes, and <svg> is inline — make the attribute
   effective here too. */
svg[hidden] { display: none; }

/* ---------- 12. Notification center (bells, panels, preferences) ---------- */
/* ONE shared component for the admin topbar + the portal topbar. Dark-first
   with light-theme parity via the shared tokens; 44px tap targets; reduced-
   motion safe. */

.notif-bell-wrap {
  position: relative;
  display: inline-flex;
}

.notif-bell {
  position: relative;
  width: 44px;
  height: 44px;
}

.notif-badge {
  position: absolute;
  top: 4px;
  right: 4px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--danger);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  line-height: 16px;
  text-align: center;
  pointer-events: none;
}

.notif-panel {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  width: min(360px, 92vw);
  max-height: min(480px, 70vh);
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: var(--shadow-lg, 0 12px 32px rgb(0 0 0 / 35%));
  z-index: 60;
}

.notif-panel[hidden] {
  display: none;
}

.notif-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 10px 12px;
  border-bottom: 1px solid var(--border-subtle, var(--border));
}

.notif-panel-body {
  overflow-y: auto;
  min-height: 48px;
}

.notif-panel-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 8px 12px;
  border-top: 1px solid var(--border-subtle, var(--border));
}

.notif-day-label {
  padding: 8px 12px 4px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.notif-row {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 9px 12px;
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid var(--border-subtle, var(--border));
}

.notif-row:hover {
  background: var(--bg-hover);
}

.notif-row .dot {
  flex: none;
  margin-top: 5px;
}

.notif-row-main {
  min-width: 0;
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.notif-row-title {
  font-weight: 600;
  font-size: 13px;
}

.notif-row.is-unread .notif-row-title {
  color: var(--text);
}

.notif-row.is-unread {
  background: color-mix(in srgb, var(--accent) 7%, transparent);
}

.notif-row-body {
  font-size: 12.5px;
  color: var(--text-faint);
  overflow-wrap: anywhere;
}

.notif-row-time {
  flex: none;
  font-size: 11px;
  color: var(--text-faint);
}

.notif-empty {
  padding: 24px 16px;
  text-align: center;
}

.notif-empty-title {
  margin: 0;
  font-weight: 600;
}

/* Preferences */
.notif-prefs-form {
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-width: 460px;
}

.notif-pref-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* The portal topbar buttons sit in a flex row — keep the panel aligned. */
.portal-topbar-actions .notif-panel {
  right: 0;
}

@media (max-width: 980px) {
  .notif-panel {
    position: fixed;
    top: 56px;
    right: 8px;
    left: 8px;
    width: auto;
  }
}

@media (prefers-reduced-motion: reduce) {
  .notif-panel,
  .notif-row {
    transition: none;
  }
}

/* ---------- 12. Observability workbench (unified stream, status strip, tiles) ---------- */

/* Status strip: checks-summary chips deep-linking into the filtered stream. */
.obs-status-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
}
.obs-chip.obs-chip-success .dot { box-shadow: 0 0 6px var(--success); }
.obs-chip.obs-chip-warning .dot { box-shadow: 0 0 6px var(--warning); }
.obs-chip.obs-chip-danger .dot { box-shadow: 0 0 6px var(--danger); }

/* Stat tiles: compact Radar tiles, tabular-nums, whole tile is a deep link. */
.obs-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 10px;
  margin-bottom: 14px;
}
.obs-tile {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--panel-2);
  text-decoration: none;
  color: var(--text);
  transition: background 140ms var(--ease-out), border-color 140ms var(--ease-out),
    box-shadow 140ms var(--ease-out);
}
.obs-tile:hover {
  background: var(--bg-hover);
  border-color: var(--border-strong);
  box-shadow: var(--glow-accent-sm);
}
.obs-tile-label {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.obs-tile-value {
  font-size: 22px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}
.obs-tile-sub {
  font-size: 11.5px;
  color: var(--text-muted);
}
.obs-tile .bar-track { height: 4px; margin-top: 4px; }
.obs-tile.tone-success .obs-tile-value { color: var(--success); }
.obs-tile.tone-warning .obs-tile-value { color: var(--warning); }
.obs-tile.tone-danger .obs-tile-value { color: var(--danger); }
.obs-tile.tone-info .obs-tile-value { color: var(--info); }

/* Stream table: the logging page's density carried over. */
.obs-kind-chip {
  display: inline-block;
  padding: 1px 8px;
  border: 1px solid var(--border-subtle);
  border-radius: 999px;
  background: var(--bg-hover);
  color: var(--text-muted);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.obs-workbench .obs-log-table td { padding-top: 7px; padding-bottom: 7px; }
.obs-workbench .obs-log-row { cursor: pointer; }
.obs-workbench .obs-log-row:hover { background: var(--bg-hover); }
.obs-workbench .obs-log-row:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: -2px;
}

@media (max-width: 980px) {
  .obs-tiles { grid-template-columns: repeat(2, 1fr); }
  .obs-status-strip { gap: 6px; }
}

/* ============================================================
   Hallmark de-AI · wave a — shell + dashboard primitives
   Genre: watchful-console · design-system: design.md
   ============================================================

   Normalizes the operator app onto the locked system (design.md):
   opacity-only entrances, quiet surfaces (no accent strips/tops on
   chrome), de-lifted hover states, and a de-uniformed hero. Later
   waves append here (b: lists, c: observability, d: portal,
   e: shared public chrome) under the same stamped header style.
   ============================================================ */

/* Hallmark · genre: watchful-console · macrostructure: workbench/foreman · design-system: design.md · designed-as-app */

/* ---- entrances: opacity only (fade-in-up / scale / slide removed) ---- */
@keyframes dash-rise {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes banner-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes user-menu-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes menu-settings-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes esr-consent-rise {
  from { opacity: 0; }
  to { opacity: 1; }
}
.dash-reveal { animation-duration: 240ms; }

/* ---- hover = state, not spectacle: lift + glow removed ---- */
.btn:hover,
.btn:focus-visible,
.stat-tile:hover,
.dash-domain-card:hover,
.dash-instance-card:hover,
.onboarding-track-link:hover,
.p-stat:hover,
.p-quick-card:hover,
.login-portal-hero:hover,
.login-portal-hero:focus-visible {
  transform: none;
}
.btn-primary:hover,
.btn-primary:focus-visible,
.user-menu.open .user-btn {
  box-shadow: none;
}
.btn-primary:hover { background: var(--accent-hover); }
.btn-primary:focus-visible { box-shadow: 0 0 0 3px var(--focus-ring); }
/* de-emphasize neon status-dot glows on chrome (status rings stay) */
.user-menu.open .user-btn { border-color: var(--border-strong); }

/* ---- stat tiles: quiet ledgers, no colored edge strips ---- */
.stat-tile::before { display: none; }
.stat-tile { overflow: visible; }
.stat-value {
  font-size: 22px;
  font-weight: 600;
  line-height: 1.2;
}
.stat-label {
  margin-top: 4px;
  font-size: 10.5px;
  letter-spacing: 0.1em;
}

/* ---- dialogs: accent tops removed (quiet border + shadow only) ---- */
.consent-dialog,
.shortcuts-dialog {
  border-top: 1px solid var(--border-strong);
}

/* ---- sidebar: single flat surface (drop the vertical shade) ---- */
.sidebar { background: var(--sidebar-bg); }

/* ---- admin hero: ring trio → quiet status ledger ---- */
.dash-hero-rings { justify-content: flex-start; }
.dash-ring {
  align-items: flex-start;
  text-align: left;
}
.dash-ring + .dash-ring {
  border-left: 1px solid var(--border);
  padding-left: 24px;
}
.dash-ring-dot {
  width: 8px;
  height: 8px;
  border-radius: 999px;
  margin-bottom: 10px;
}
.dash-ring-dot.tone-success { background: var(--success); }
.dash-ring-dot.tone-warning { background: var(--warning); }
.dash-ring-dot.tone-danger { background: var(--danger); }
.dash-ring-num {
  font-family: var(--font-display);
  font-size: 26px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}
.dash-ring-label {
  margin-top: 6px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.dash-ring-sub {
  margin-top: 2px;
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--text-faint);
}

/* ---- quick actions: task links, not a uniform chip row ---- */
.dash-hero-actions .btn {
  background: transparent;
  border-color: transparent;
  color: var(--text-muted);
  padding: 3px 8px;
  font-size: 12px;
}
.dash-hero-actions .btn:hover {
  background: var(--bg-hover);
  border-color: var(--border);
  color: var(--text);
}

/* ---- admin bento: asymmetric rows (needs-attention wider than
   activity; reminders narrower than recent; instances vs status) ----
   The asymmetric 12-column areas only read on wide screens; below 1181px
   the earlier <=1180px override collapses every row to full width. This
   block used to sit UNCONDITIONALLY after that override in source order,
   winning the cascade at every viewport and leaving the status/instances
   cells 5/12 of a 320px screen (~114px) — the nowrap "Unreachable" badge
   then blew the document out horizontally. Scoping it to >=1181px
   restores the intended narrow-viewport collapse. */
@media (min-width: 1181px) {
  .dash-role-admin {
    grid-template-columns: repeat(12, 1fr);
    grid-template-areas:
      "attention attention attention attention attention attention attention activity activity activity activity activity"
      "reminders reminders reminders reminders reminders recent recent recent recent recent recent recent"
      "overview overview overview overview overview overview overview overview overview overview overview overview"
      "instances instances instances instances instances instances instances status status status status status"
      "messaging messaging messaging messaging messaging messaging messaging messaging messaging messaging messaging messaging";
  }
}

@media (max-width: 1180px) {
  .dash-ring + .dash-ring {
    border-left: 0;
    padding-left: 0;
  }
}

/* Hallmark · genre: watchful-console · macrostructure: workbench/ledger · design-system: design.md · designed-as-app */

/* ---- list/search focus: ring, not glow ---- */
.search-bar:focus-within,
.radar-toolbar .search-bar:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--focus-ring);
}

/* ---- table eyebrows: one uniform small-caps label ---- */
.data-table th,
.table th {
  font-size: 10.5px;
  letter-spacing: 0.08em;
}

/* ---- list identifiers read as text, not a wall of blue: the primary
   entity name keeps text color and gets the accent only on hover (the
   mono secondary line stays muted). Action buttons in cells are
   untouched (they carry .btn/.pill). ---- */
body.page-list .data-table td a:not(.btn),
#registrations-panel td a:not(.btn),
#domains-panel td a:not(.btn),
#users-panel td a:not(.btn),
.table td a:not(.btn) {
  color: var(--text);
}
body.page-list .data-table td a:not(.btn):hover,
#registrations-panel td a:not(.btn):hover,
#domains-panel td a:not(.btn):hover,
#users-panel td a:not(.btn):hover,
.table td a:not(.btn):hover {
  color: var(--accent);
}

/* ---- pagination + count chips: quiet mono totals ---- */
.pagination .pager a,
.pagination .pager span {
  min-width: 26px;
  height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  color: var(--text-muted);
  font-size: 12px;
}
.pagination .pager a:hover { border-color: var(--border-strong); color: var(--text); }
.count-chip { min-width: 20px; height: 20px; padding: 0 6px; border-radius: 999px; display: inline-flex; align-items: center; justify-content: center; }

/* ---- 1280px budget: hide tags-count + created so STATUS always fits
   without horizontal scroll (both stay in the flyout/detail) ---- */
@media (max-width: 1280px) {
  #registrations-panel .data-table thead th:nth-child(8),
  #registrations-panel .data-table tr[data-flyout] > td:nth-child(8),
  #registrations-panel .data-table thead th:nth-child(11),
  #registrations-panel .data-table tr[data-flyout] > td:nth-child(11) { display: none; }
}

/* ---- row actions stay reachable: sticky-right kebab on every dense
   table (paints over the scrolled row, states match --bg) ---- */
body.page-list .data-table td.cell-actions {
  position: sticky;
  right: 0;
  background: var(--bg);
}
body.page-list .data-table tbody tr:hover td.cell-actions { background: var(--bg-hover); }
/* ---- list layout: rail shrinks to 204px so the table gets the budget.
   Wide screens only — declared unconditionally it sat after the <=980px
   single-column collapse in source order and won the cascade, so phones
   laid the table into the (hidden) rail's 204px track with ~66-88px of
   the viewport wasted. ---- */
@media (min-width: 981px) {
  .list-layout {
    grid-template-columns: 204px 1fr;
  }
}

/* Hallmark · genre: watchful-console · macrostructure: workbench/instrument-panel · design-system: design.md · designed-as-app */

/* ---- observability chips: tone via dots, never glow ---- */
.obs-chip.obs-chip-success .dot,
.obs-chip.obs-chip-warning .dot,
.obs-chip.obs-chip-danger .dot {
  box-shadow: none;
}
.obs-chip.active {
  background: var(--accent-tint);
}

/* ---- obs tiles: a stat ledger, not a row of equal boxed cards ----
   (label eyebrow over a tabular value, hairline separators; the whole
   column is still the deep link) */
.obs-tiles {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 26px;
}
.obs-tile {
  padding: 2px 0;
  border: 0;
  border-radius: 0;
  background: transparent;
}
.obs-tile + .obs-tile {
  border-left: 1px solid var(--border);
  padding-left: 26px;
}
.obs-tile:hover {
  background: transparent;
  border-color: transparent;
  box-shadow: none;
}
.obs-tile:hover .obs-tile-label { color: var(--accent); }
.obs-tile-value {
  font-size: 22px;
  font-weight: 600;
}
.obs-tile .bar-track { margin-top: 2px; }

@media (max-width: 980px) {
  .obs-tiles { gap: 6px 18px; }
  .obs-tile + .obs-tile { border-left: 0; padding-left: 0; }
}

/* ---- issues: tone lives in the head dot, not a 3px severity edge ---- */
.obs-issue { border-left-width: 1px; }

/* Hallmark · genre: watchful-console · macrostructure: workbench/compact-ledger · design-system: design.md · designed-as-app */

/* ---- portal home quick actions: one wrapping task bar (3 or 4 items
   always fill intact rows — the card-grid 3+1 orphan is gone) ---- */
.portal-page .p-quick-cards {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
}
.portal-page .p-quick-card {
  flex: 1 1 210px;
  min-width: 0;
  height: auto;
}

/* ---- connect steps: numeral on solid accent (was accent-tint + white
   text — unreadable) ---- */
.p-connect-step-num {
  background: var(--accent);
  color: var(--accent-text);
}

/* Hallmark · genre: watchful-console · macrostructure: long-document · design-system: design.md · designed-as-app */

/* ---- onboarding card: quiet card, decoration pile removed (accent top
   border, radial corner glow, grid texture) ---- */
.onboarding-card {
  border-top: 1px solid var(--border);
}
.onboarding-card::before,
.onboarding-card::after {
  display: none;
}
.onboarding-card > * { position: static; z-index: auto; }

/* eyebrow tracking normalized to the system value */
.onboarding-eyebrow { letter-spacing: 0.12em; }

/* tracking CTA: border/shadow state only, no lift or glow */
.onboarding-track-link:hover {
  transform: none;
  box-shadow: none;
}

/* stepper active dot: ring pulse without the scale zoom */
@keyframes stepper-pulse {
  0%, 100% { box-shadow: 0 0 0 0 var(--accent-tint-strong); }
  50% { box-shadow: 0 0 0 6px transparent; }
}

/* terms prose: one quiet readable column with real heading hierarchy */
.public-card--prose { max-width: 640px; }
.public-card--prose .terms-body h2 {
  font-size: 15px;
  margin: 24px 0 6px;
}
.public-card--prose .terms-body h2:first-child { margin-top: 0; }

/* ============================================================
   ---------- Hallmark · public expressiveness ----------------
   The login experience redesign (captain's direction): the public +
   portal surfaces move to the expressiveness register allowed by
   design.md ## Variants. Workbench surfaces stay untouched. Every
   rule below is transform/opacity/background-position only, uses the
   system tokens + named easings, and is covered by the global
   prefers-reduced-motion block (durations zeroed -> instant settle).
   ============================================================ */

/* Hallmark · genre: public-expressiveness · macrostructure: long-document (brand panel) · design-system: design.md · designed-as-app */
/* ---- the brand panel comes alive: fine dot grid + a slow drifting
   halo over the fixed red gradient. Pseudo layers sit behind content
   (content is z-index 1). All public split-shell pages share this. ---- */
.brand-panel::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: radial-gradient(rgba(255, 255, 255, 0.13) 1px, transparent 1.4px);
  background-size: 22px 22px;
  opacity: 0.55;
  mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.85), transparent 80%);
  -webkit-mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.85), transparent 80%);
}
.brand-panel::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(640px 380px at 50% -12%, rgba(255, 255, 255, 0.22), transparent 62%);
  animation: esr-brand-halo 21s var(--ease-drawer) infinite alternate;
}
@keyframes esr-brand-halo {
  from { transform: translate3d(4%, -3%, 0); opacity: 0.8; }
  to { transform: translate3d(-3%, 4%, 0); opacity: 1; }
}
/* Brand-panel content: one gentle staggered reveal (rise ≤ 12px). */
.brand-panel > * {
  animation: esr-rise-in 460ms var(--ease-out) both;
}
.brand-panel > :nth-child(1) { animation-delay: 40ms; }
.brand-panel > :nth-child(2) { animation-delay: 110ms; }
.brand-panel > :nth-child(3) { animation-delay: 180ms; }
.brand-panel > :nth-child(4) { animation-delay: 250ms; }
.brand-panel > :nth-child(n+5) { animation-delay: 310ms; }

/* Hallmark · genre: public-expressiveness · macrostructure: long-document (form column) · design-system: design.md · designed-as-app */
/* ---- ambience behind the forms: two slow, low-opacity aurora tints
   drifting inside the column (transform only). Cards have opaque
   backgrounds so the tint shows only around them. ---- */
.public-form-side { position: relative; }
.public-form-side::before,
.public-form-side::after {
  content: "";
  position: absolute;
  z-index: 0;
  pointer-events: none;
  border-radius: 50%;
}
.public-form-side::before {
  width: 520px;
  height: 520px;
  top: 6%;
  right: 8%;
  background: radial-gradient(circle, var(--accent-tint) 0%, transparent 62%);
  animation: esr-aurora-a 34s var(--ease-drawer) infinite alternate;
}
.public-form-side::after {
  width: 460px;
  height: 460px;
  bottom: 5%;
  left: 6%;
  background: radial-gradient(circle, var(--info-tint) 0%, transparent 60%);
  animation: esr-aurora-b 44s var(--ease-drawer) infinite alternate;
}
@keyframes esr-aurora-a {
  from { transform: translate3d(0, 0, 0); }
  to { transform: translate3d(-56px, 36px, 0); }
}
@keyframes esr-aurora-b {
  from { transform: translate3d(0, 0, 0); }
  to { transform: translate3d(48px, -32px, 0); }
}

/* Hallmark · genre: public-expressiveness · macrostructure: workbench/dossier (auth card) · design-system: design.md · designed-as-app */
/* ---- auth cards: richer entrance (rise + 1.5% settle) overriding the
   quiet esr-fade-in from public_base (higher specificity), plus an
   accent hairline that draws in on the branded login cards. The
   operator utility login keeps the entrance but NOT the hairline. ---- */
.public-shell .public-card,
.public-shell .login-card,
.public-form-side .onboarding-card {
  animation: esr-card-in 460ms var(--ease-out) both;
}
@keyframes esr-card-in {
  from { opacity: 0; transform: translateY(12px) scale(0.985); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}
.public-shell:not(.public-shell--utility) .login-card {
  position: relative;
}
.public-shell:not(.public-shell--utility) .login-card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 28px;
  right: 28px;
  height: 2px;
  border-radius: 0 0 2px 2px;
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--accent) 80%, transparent) 50%, transparent);
  transform: scaleX(0);
  opacity: 0;
  animation: esr-hairline-in 760ms var(--ease-out) 300ms both;
}
@keyframes esr-hairline-in {
  from { transform: scaleX(0); opacity: 0; }
  to { transform: scaleX(1); opacity: 1; }
}
/* The login-card -> portal transform gets its own longer entrance. */
.public-shell .login-card--portal {
  animation: esr-portal-card-in 520ms var(--ease-out) both;
}
@keyframes esr-portal-card-in {
  from { opacity: 0; transform: translateY(14px) scale(0.97); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

/* Hallmark · genre: public-expressiveness · macrostructure: workbench/control-room (forms) · design-system: design.md · designed-as-app */
/* ---- form micro-interactions: label tints to brand red on focus,
   the focused input gets the accent ring glow, the whole card edges
   red while a field inside is focused. ---- */
.public-shell .form-field label,
.portal-shell .form-field label {
  display: block;
  transition: color 160ms var(--ease-out);
}
.public-shell .form-field:focus-within label,
.portal-shell .form-field:focus-within label {
  color: var(--accent);
}
.public-shell .form-field input:focus-visible,
.portal-shell .form-field input:focus-visible {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--focus-ring);
}
.public-shell .login-card:focus-within {
  border-color: color-mix(in srgb, var(--accent) 45%, var(--border));
}
/* OTP / 2FA code fields: centered mono digits with wider tracking. */
.public-shell .login-card input[autocomplete="one-time-code"] {
  font-family: var(--font-mono);
  letter-spacing: 0.18em;
  text-align: center;
}

/* ---- primary CTA: sheen sweep on hover + press-scale feedback.
   transform/opacity only; the element's own focus outline is never
   clipped by overflow:hidden. ---- */
.public-shell .btn-primary,
.portal-shell .btn-primary {
  position: relative;
  overflow: hidden;
}
.public-shell .btn-primary::after,
.portal-shell .btn-primary::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(105deg, transparent 42%, rgba(255, 255, 255, 0.3) 50%, transparent 58%);
  transform: translateX(-130%);
  pointer-events: none;
}
.public-shell .btn-primary:hover::after,
.portal-shell .btn-primary:hover::after {
  animation: esr-sheen 640ms var(--ease-out);
}
@keyframes esr-sheen {
  to { transform: translateX(130%); }
}
.public-shell .btn-primary:active,
.portal-shell .btn-primary:active {
  transform: scale(0.98);
}

/* Hallmark · genre: public-expressiveness · macrostructure: workbench/ledger (step panels) · design-system: design.md · designed-as-app */
/* ---- the login card's step panels (login -> register -> OTP) swap
   with a rise crossfade. app.js toggles `hidden`; removing display:none
   restarts the CSS animation on the incoming panel. ---- */
.public-shell .login-card [data-instance-panel]:not([hidden]) {
  animation: esr-panel-swap 320ms var(--ease-out) both;
}
@keyframes esr-panel-swap {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

/* Hallmark · genre: public-expressiveness · macrostructure: workbench/instrument-panel (portal-in-login) · design-system: design.md · designed-as-app */
/* ---- the embedded portal panel: avatar breathes, hero arrow slides,
   portal entrance redefined with a gentle settle. ---- */
.login-portal-avatar {
  animation: esr-avatar-breathe 3.6s var(--ease-drawer) infinite;
}
@keyframes esr-avatar-breathe {
  0%, 100% {
    box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 0%, transparent), 0 0 0 1px color-mix(in srgb, var(--accent) 35%, transparent);
  }
  50% {
    box-shadow: 0 0 0 7px color-mix(in srgb, var(--accent) 0%, transparent), 0 0 0 1px color-mix(in srgb, var(--accent) 62%, transparent);
  }
}
.login-portal-hero-arrow {
  transition: transform 160ms var(--ease-out);
}
.login-portal-hero:hover .login-portal-hero-arrow,
.login-portal-hero:focus-visible .login-portal-hero-arrow {
  transform: translateX(3px);
}
@keyframes esr-portal-in {
  from { opacity: 0; transform: translateY(12px) scale(0.985); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

/* Hallmark · genre: public-expressiveness · macrostructure: workbench/control-room (cookie consent) · design-system: design.md · designed-as-app */
/* ---- consent banner: shield mark + staggered content entrance; the
   opted state turns success-toned and slides away (is-opted toggled by
   cookie-consent.js, which also announces consent.saved live). ---- */
.consent-banner-icon {
  flex: none;
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: var(--radius);
  background: var(--accent-tint);
  color: var(--accent);
}
.consent-banner > * {
  animation: esr-rise-in 380ms var(--ease-out) both;
}
.consent-banner > :nth-child(1) { animation-delay: 40ms; }
.consent-banner > :nth-child(2) { animation-delay: 100ms; }
.consent-banner > :nth-child(3) { animation-delay: 160ms; }
.consent-banner.is-opted {
  border-top: 2px solid var(--success);
  background: color-mix(in srgb, var(--success) 12%, var(--panel));
  animation: esr-consent-opt-out 520ms var(--ease-out) 150ms both;
}
.consent-banner.is-opted .consent-banner-icon {
  background: var(--success-tint);
  color: var(--success);
}
@keyframes esr-consent-opt-out {
  from { opacity: 1; transform: translateY(0); }
  to { opacity: 0; transform: translateY(16px); }
}

/* ---- consent preferences dialog: shield mark in the head, entrance
   + backdrop fade, categories stagger in. ---- */
.consent-dialog-heading {
  display: flex;
  align-items: center;
  gap: 10px;
}
.consent-dialog-mark {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  flex: none;
  border-radius: var(--radius);
  background: var(--accent-tint);
  color: var(--accent);
}
.consent-dialog[open] {
  animation: esr-dialog-in 280ms var(--ease-out) both;
}
@keyframes esr-dialog-in {
  from { opacity: 0; transform: translateY(12px) scale(0.985); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}
.consent-dialog[open]::backdrop {
  animation: esr-dialog-backdrop-in 240ms ease-out both;
}
@keyframes esr-dialog-backdrop-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
.consent-dialog[open] .consent-category {
  animation: esr-pane-in 260ms var(--ease-out) both;
}
.consent-dialog[open] .consent-category:nth-child(2) { animation-delay: 40ms; }
.consent-dialog[open] .consent-category:nth-child(3) { animation-delay: 80ms; }

/* ---- grouped-by-purpose storage list inside each category: a dashed
   divider + a native details row that lists exactly the storage that
   category covers (name / purpose / duration). ---- */
.consent-category-items {
  margin-top: 8px;
  border-top: 1px dashed var(--border);
  padding-top: 8px;
  font-size: 12px;
}
.consent-category-items summary {
  cursor: pointer;
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-weight: 600;
  color: var(--text-faint);
  transition: color 140ms var(--ease-out);
}
.consent-category-items summary::-webkit-details-marker { display: none; }
.consent-category-items summary::before {
  content: "";
  width: 6px;
  height: 6px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg);
  transition: transform 150ms var(--ease-out);
}
.consent-category-items[open] summary::before { transform: rotate(-135deg); }
.consent-category-items summary:hover { color: var(--text); }
.consent-category-items summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.consent-category-items-list {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
}
.consent-item {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 2.2fr) auto;
  gap: 10px 14px;
  padding: 7px 0;
  border-bottom: 1px solid var(--border-subtle);
}
.consent-item:last-child { border-bottom: 0; }
.consent-item-name { font-weight: 600; color: var(--text); }
.consent-item-purpose { color: var(--text-muted); line-height: 1.45; }
.consent-item-duration { color: var(--text-faint); white-space: nowrap; }

/* Hallmark · genre: public-expressiveness · macrostructure: workbench/foreman (portal pages) · design-system: design.md · designed-as-app */
/* ---- portal pages: one gentle staggered entrance per section. Only
   direct children of .portal-page animate, so the embedded login-card
   portal (different tree) keeps its own pane transitions. ---- */
.portal-page > .portal-head { animation: esr-rise-in 380ms var(--ease-out) both; }
.portal-page > .p-status { animation: esr-rise-in 420ms var(--ease-out) 60ms both; }
.portal-page > .p-quick-cards { animation: esr-rise-in 440ms var(--ease-out) 90ms both; }
.portal-page > .p-stats { animation: esr-rise-in 440ms var(--ease-out) 120ms both; }
.portal-page > .panel {
  animation: esr-rise-in 440ms var(--ease-out) both;
}
.portal-page > .panel:nth-of-type(2) { animation-delay: 70ms; }
.portal-page > .panel:nth-of-type(3) { animation-delay: 140ms; }
.portal-page > .panel:nth-of-type(n+4) { animation-delay: 200ms; }

/* ---- quick cards: chevron slides in, the icon well fills brand red
   on hover/focus. ---- */
.p-quick-card {
  position: relative;
  overflow: hidden;
}
.p-quick-card::after {
  content: "";
  position: absolute;
  right: 14px;
  top: 50%;
  width: 8px;
  height: 8px;
  border-right: 2px solid var(--text-faint);
  border-bottom: 2px solid var(--text-faint);
  transform: translate(-4px, -50%) rotate(-45deg);
  opacity: 0;
  transition: opacity 160ms var(--ease-out), border-color 160ms var(--ease-out), transform 160ms var(--ease-out);
}
.p-quick-card:hover::after,
.p-quick-card:focus-visible::after {
  opacity: 1;
  border-color: var(--accent);
  transform: translate(0, -50%) rotate(-45deg);
}
.p-quick-card .p-quick-card-icon {
  transition: background 180ms var(--ease-out), color 180ms var(--ease-out), transform 180ms var(--ease-out);
}
.p-quick-card:hover .p-quick-card-icon,
.p-quick-card:focus-visible .p-quick-card-icon {
  background: var(--accent);
  color: #fff;
  transform: translateY(-1px);
}

/* ---- storage bars fill in from the left on first paint (transform
   scaleX; the inline width from data-fill-w stays authoritative). ---- */
.p-progress-fill {
  transform-origin: left center;
  animation: esr-fill-in 800ms var(--ease-out) both;
}
@keyframes esr-fill-in {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}

/* ---- connect steps: number chips wake to brand red on row hover. ---- */
.p-connect-step-num {
  transition: transform 160ms var(--ease-out), background 160ms var(--ease-out), color 160ms var(--ease-out);
}
.p-connect-steps li:hover .p-connect-step-num {
  background: var(--accent);
  color: #fff;
  transform: scale(1.1);
}

/* Hallmark · genre: public-expressiveness · macrostructure: workbench/dossier (register FAQ) · design-system: design.md · designed-as-app */
.public-faq {
  animation: esr-rise-in 440ms var(--ease-out) 200ms both;
}

/* Hallmark · genre: public-expressiveness · macrostructure: workbench/ledger (files-open handoff) · design-system: design.md · designed-as-app */
/* ---- the "Opening your files" handoff: radar rings radiate from the
   folder mark while a progress line sweeps. All infinite loops are
   collapsed to static by the global reduced-motion block. ---- */
.files-connect {
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 18px;
  padding: 10px 0 8px;
}
.files-connect-visual {
  position: relative;
  width: 76px;
  height: 76px;
}
.files-connect-ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 1.5px solid color-mix(in srgb, var(--accent) 45%, transparent);
  animation: esr-files-ring 2.2s var(--ease-out) infinite;
}
.files-connect-ring--inner {
  inset: 14px;
  animation-delay: 0.55s;
}
@keyframes esr-files-ring {
  0% { transform: scale(0.68); opacity: 0.9; }
  100% { transform: scale(1.4); opacity: 0; }
}
.files-connect-core {
  position: absolute;
  left: 50%;
  top: 50%;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 14px;
  background: var(--accent);
  color: #fff;
  box-shadow: var(--glow-accent-sm);
  animation: esr-files-core 2.4s ease-in-out infinite;
}
@keyframes esr-files-core {
  0%, 100% { transform: translate(-50%, -50%) scale(1); }
  50% { transform: translate(-50%, -50%) scale(1.06); }
}
.files-connect-text {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 14px;
  color: var(--text);
}
.files-connect-label { font-weight: 600; }
.files-connect-dots { display: inline-flex; gap: 4px; }
.files-connect-dots span {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--accent);
  animation: esr-files-dot 1.3s var(--ease-out) infinite;
}
.files-connect-dots span:nth-child(2) { animation-delay: 0.2s; }
.files-connect-dots span:nth-child(3) { animation-delay: 0.4s; }
@keyframes esr-files-dot {
  0%, 100% { opacity: 0.25; transform: translateY(0); }
  50% { opacity: 1; transform: translateY(-2px); }
}
.files-connect-progress {
  width: min(210px, 70vw);
  height: 3px;
  border-radius: 999px;
  background: var(--panel-3);
  overflow: hidden;
}
.files-connect-progress-fill {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--accent), var(--accent-hover));
  transform-origin: left center;
  animation: esr-files-progress 1.7s var(--ease-out) infinite alternate;
}
@keyframes esr-files-progress {
  from { transform: scaleX(0.15); opacity: 0.6; }
  to { transform: scaleX(1); opacity: 1; }
}

/* Hallmark · genre: public-expressiveness · macrostructure: workbench · design-system: design.md · designed-as-app */
/* ---- shared rise keyframe used across the surface groups above. ---- */
@keyframes esr-rise-in {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

@media (max-width: 560px) {
  .consent-item {
    grid-template-columns: 1fr;
    gap: 2px 0;
    padding: 8px 0;
  }
  .consent-banner-icon { display: none; }
}

/* The aurora blobs are oversized by design (absolute, soft radial); on
   narrow screens they would push the layout wider than the viewport —
   drop them (the fixed gradients + brand panel carry the ambience). */
@media (max-width: 640px) {
  .public-form-side::before,
  .public-form-side::after {
    display: none;
  }
}

/* Hallmark · genre: public-expressiveness · macrostructure: workbench/control-room (consent settings) · design-system: design.md · designed-as-app */
/* ---- consent category summary rows in Settings: tone dots make the
   always-on vs optional split legible at a glance. ---- */
.settings-consent-categories li {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 0;
}
.settings-consent-categories li::before {
  content: "";
  flex: none;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--success);
  opacity: 0.75;
}
.settings-consent-categories li.cat-optional::before {
  background: var(--warning);
}

/* ---------- Hallmark org & service-accounts portal (organization surface + robot credentials) ---------- */

/* Hallmark · genre: watchful-console · macrostructure: workbench/ledger (portal shell) · design-system: design.md · designed-as-app */
/* ---- organization identity panel ---- */
.org-identity-head {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}
.org-identity-name {
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -0.02em;
}
.org-dept-chips { display: inline-flex; flex-wrap: wrap; gap: 6px; }
.org-dept-chip {
  display: inline-flex;
  align-items: center;
  padding: 2px 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--panel-2);
  color: var(--text-muted);
  font-size: 12.5px;
}
.org-robots-count { color: var(--text-faint); font-size: 12px; }

/* ---- service accounts list: name/purpose/key-type/status/created rows ---- */
.org-robots {
  list-style: none;
  margin: 0 0 4px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.org-robot-row {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px 18px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--panel);
  color: var(--text);
  text-decoration: none;
  transition: border-color 140ms var(--ease-out), background-color 140ms var(--ease-out);
}
.org-robot-row:hover { background: var(--bg-hover); border-color: var(--border-strong); }
.org-robot-row:active { box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.25); }
.org-robot-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.org-robot-name {
  font-weight: 600;
  font-size: 14px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.org-robot-sub {
  color: var(--text-faint);
  font-size: 12px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.org-robot-meta {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  min-width: 0;
  flex-wrap: wrap;
}
.org-robot-dept { color: var(--text-muted); font-size: 13px; }
.org-robot-created { color: var(--text-faint); font-size: 12px; }
.org-robot-chevron {
  color: var(--text-faint);
  flex: none;
  transition: color 140ms var(--ease-out), transform 140ms var(--ease-out);
}
.org-robot-row:hover .org-robot-chevron {
  color: var(--text-muted);
  transform: translateX(2px);
}
.org-credentials-note {
  margin-top: 10px;
  max-width: 72ch;
  font-size: 12.5px;
}

/* Hallmark · genre: watchful-console · macrostructure: workbench/dossier (portal shell) · design-system: design.md · designed-as-app */
/* ---- robot detail: back link, connection, credentials (D3/D4) ---- */
.portal-head--detail h1 { margin-top: 4px; }
.org-back-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--info);
  text-decoration: none;
}
.org-back-link:hover { text-decoration: underline; }
.ssh-key-wrap { display: flex; flex-direction: column; gap: 8px; }
.ssh-key-block {
  width: 100%;
  box-sizing: border-box;
  padding: 10px 12px;
  background: var(--bg-inset);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  font-size: 12px;
  line-height: 1.55;
  resize: vertical;
}
.ssh-key-wrap .copy-link-btn { align-self: flex-start; }
.robot-password {
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}
.robot-password-head { display: flex; align-items: center; gap: 10px; }
.pass-mask {
  color: var(--text-muted);
  font-size: 13px;
  letter-spacing: 0.14em;
}
.robot-password .p-muted { margin-top: 6px; max-width: 72ch; font-size: 12.5px; }

@media (max-width: 640px) {
  .org-robot-row { grid-template-columns: 1fr auto; }
  .org-robot-meta {
    justify-content: flex-start;
    grid-column: 1 / -1;
    grid-row: 2;
  }
  .org-robot-chevron { grid-column: 2; grid-row: 1; }
}
/* ============================================================
   Mobile layout repair (2026-09-11 captain report: admin pages
   mangled on phones). Every rule below is a narrow-viewport-only
   responsive patch in the house media-query layers; desktop
   (>=1181px) rendering is byte-identical.
   ============================================================ */

/* ---- webhooks / integrations forms: generated su-* utilities carry
   hard min-widths sized for desktop flex rows (e.g. the webhook Events
   fieldset's min-width: 320px), which overflow a 320px viewport. Stack
   every inline-form fieldset full-width on phones instead. ---- */
@media (max-width: 640px) {
  .inline-form > fieldset {
    flex: 1 1 100%;
    min-width: 0;
  }

  /* ---- observability stream: the timestamp cell wrapped onto 3-4 lines
     at 320px, inflating every row; pin it to one line (the column is
     already position: sticky at <=980px, so later columns scroll under
     a readable first column). ---- */
  .obs-log-table th:first-child,
  .obs-log-table td:first-child {
    white-space: nowrap;
  }
}
/* ============================================================
   ---------- Hallmark · login copy de-AI ---------------------
   The transfer mark on the end-user brand panel: two files
   exchanging over counter-flowing arrows — the restrained
   "file transfer at a glance" graphic (captain's direction).
   White brand-panel strokes only; opacity-only loop; covered by
   the global prefers-reduced-motion block. The collapsed cookie
   chip joins the .icon-btn family (restyle applied at its rule).
   ============================================================ */

/* Hallmark · genre: watchful-console · macrostructure: long-document (brand panel) · design-system: design.md · designed-as-app */
.brand-mark {
  display: block;
  width: 96px;
  height: 44px;
  margin: 26px 0 4px;
}
.brand-mark-flow {
  animation: esr-transfer-flow 3.2s var(--ease-drawer) infinite alternate;
}
.brand-mark-flow-b { animation-delay: -1.6s; }
@keyframes esr-transfer-flow {
  from { opacity: 0.5; }
  to { opacity: 1; }
}




/* ==========================================================================
   Hallmark · support system (portal requests + admin Support Center)
   ========================================================================== */
/* Hallmark · genre: watchful-console · macrostructure: workbench/ledger · design-system: design.md · designed-as-app */
/* ---- thread list rows: subject + category + status chips under the user
        identity, instance in mono. One panel, one border, flat. ---- */
.msg-thread-subject {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.msg-thread-item.has-unread .msg-thread-subject { color: var(--text); }
.msg-thread-meta {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  font-size: 11px;
  color: var(--text-muted);
  overflow: hidden;
  white-space: nowrap;
}
.msg-thread-meta .pill {
  font-size: 10.5px;
  gap: 4px;
  padding: 0 2px;
  flex: 0 0 auto;
}
.msg-thread-category {
  flex: 0 0 auto;
  color: var(--text-faint);
  border: 1px solid var(--border-subtle);
  border-radius: 999px;
  padding: 0 8px;
  font-size: 10.5px;
}
.msg-thread-org,
.msg-thread-instance { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msg-thread-instance { color: var(--text-faint); font-size: 10.5px; }

/* Hallmark · genre: watchful-console · macrostructure: workbench/ledger · design-system: design.md · designed-as-app */
/* ---- Support Center filter rail: submit-button pills (native form
        submit, no JS), two selects, and a clear link when filters run. ---- */
.msg-filters {
  padding: 6px 12px 8px;
  border-bottom: 1px solid var(--border-subtle);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.msg-filter-status {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  align-items: center;
}
.msg-filter-pill {
  appearance: none;
  border: 1px solid var(--border-subtle);
  background: transparent;
  color: var(--text-muted);
  font: inherit;
  font-size: 11.5px;
  font-weight: 500;
  border-radius: 999px;
  padding: 3px 10px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
  transition: background 120ms var(--ease-out), border-color 120ms var(--ease-out), color 120ms var(--ease-out);
}
.msg-filter-status { row-gap: 6px; }
.msg-filter-pill:hover { background: var(--bg-hover); border-color: var(--border-strong); color: var(--text); }
.msg-filter-pill:active { box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.2); }
.msg-filter-pill.is-active {
  background: var(--bg-active);
  border-color: var(--border-strong);
  color: var(--text);
}
.msg-filter-count {
  font-size: 10.5px;
  font-variant-numeric: tabular-nums;
  color: var(--text-faint);
  background: var(--panel-2);
  border-radius: 999px;
  min-width: 18px;
  padding: 0 5px;
  text-align: center;
}
.msg-filter-pill.is-active .msg-filter-count { color: var(--text-muted); }
.msg-filter-selects {
  display: flex;
  gap: 6px;
  align-items: center;
  flex-wrap: wrap;
}
.msg-filter-selects select {
  flex: 1 1 110px;
  min-width: 0;
  font-size: 11.5px;
}
.msg-filter-actions {
  display: flex;
  gap: 6px;
  align-items: center;
  margin-left: auto;
}

/* Hallmark · genre: watchful-console · macrostructure: workbench/dossier · design-system: design.md · designed-as-app */
/* ---- conversation header: subject title, lifecycle status pill +
        close/reopen form, then the request's timestamp meta row. ---- */
.msg-thread-title {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.msg-thread-status-wrap {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
  margin-left: auto;
}
.msg-thread-status-wrap .pill { flex: 0 0 auto; }
.msg-thread-status-form { display: inline-flex; }
.msg-thread-status-form .btn-ghost {
  border-color: var(--border-strong);
  background: var(--panel-2);
  color: var(--text);
}
.msg-thread-status-form .btn-ghost:hover { background: var(--bg-hover); border-color: var(--border-strong); }
.msg-thread-status-form .btn { flex: 0 0 auto; }
.msg-thread-meta-row {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  padding: 6px 16px;
  border-bottom: 1px solid var(--border-subtle);
  font-size: 11.5px;
}
.msg-thread-meta-row .hint { display: inline-flex; align-items: baseline; gap: 4px; }
.msg-thread-meta-row .mono { color: var(--text-muted); font-size: 11.5px; }

/* Hallmark · genre: watchful-console · macrostructure: workbench/dossier · design-system: design.md · designed-as-app */
/* ---- the lifecycle hint line under the conversation (both surfaces):
        a quiet status sentence, not a banner. ---- */
.support-status-hint {
  margin: 0;
  padding: 0 16px 4px;
  font-size: 12px;
  color: var(--text-muted);
}

/* Hallmark · genre: public-expressiveness · macrostructure: workbench/dossier (portal request overview) · design-system: design.md · designed-as-app */
/* ---- portal request overview: subject + category + live status pill,
        timestamps as a definition row. Same tokens, quiet register. ---- */
.support-overview {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 18px;
  margin-bottom: 16px;
}
.support-overview-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
}
.support-overview-identity { min-width: 0; }
.support-eyebrow {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--text-faint);
}
.support-subject {
  margin: 4px 0 0;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.support-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 6px;
  flex-wrap: wrap;
}
.support-meta .msg-unread-chip { align-self: auto; }
.support-overview .pill { flex: 0 0 auto; }
.support-overview-meta {
  display: flex;
  gap: 24px;
  flex-wrap: wrap;
  margin: 0;
  border-top: 1px solid var(--border-subtle);
  padding-top: 12px;
}
.support-meta-item {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.support-meta-item dt {
  font-size: 11px;
  color: var(--text-faint);
}
.support-meta-item dd {
  margin: 0;
  font-size: 12px;
  color: var(--text-muted);
}
.support-overview .support-status-hint {
  padding: 0;
  border-top: 1px solid var(--border-subtle);
  padding-top: 10px;
}

/* Hallmark · genre: public-expressiveness · macrostructure: workbench/control-room (portal new request) · design-system: design.md · designed-as-app */
/* ---- the new-request form: one card, real form fields, one primary
        button. No decoration pile; the entrance rides the portal section
        stagger already declared in the expressiveness register. ---- */
.support-new { display: flex; flex-direction: column; gap: 14px; padding: 18px; }
.support-new-head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
}
.support-new-head .support-new-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: var(--radius);
  background: var(--panel-2);
  border: 1px solid var(--border-subtle);
  color: var(--text-muted);
  flex: 0 0 auto;
}
.support-new-head h2 {
  margin: 0;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--text);
}
.support-new .hint { margin: 0; }
.support-form { display: flex; flex-direction: column; gap: 2px; }
.support-form .form-field { margin-bottom: 10px; }
.support-form select {
  width: 100%;
}
.support-form-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: 6px;
}

/* ============================================================
   ---------- Hallmark · end-user portal (captain redesign) ----
   The /portal pages and the login-card portal panel join the
   public expressiveness register: a hero identity row with the
   initial-letter avatar and the account-status pill, the ONE
   red primary action per surface, quiet quick links instead of
   the uniform card grid, underline tabs and flush sections
   inside the login card. Tokens only; the global
   prefers-reduced-motion block zeroes every duration below.
   ============================================================ */

/* Hallmark · genre: watchful-console · macrostructure: long-document (portal pages) · design-system: design.md · designed-as-app */
/* ---- portal home hero: identity + status + the one primary action ---- */
.p-hero {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 22px 24px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--panel);
  animation: p-hero-in 320ms var(--ease-out) both;
}

@keyframes p-hero-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

.p-hero-avatar {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  flex: none;
  border-radius: 50%;
  background: var(--accent-tint);
  color: var(--accent);
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 700;
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 30%, transparent);
}

.p-hero-text { min-width: 0; flex: 1; }

.p-hero-text h1 { margin: 0 0 4px; font-size: 24px; }

.p-hero-sub { margin: 0; color: var(--text-muted); font-size: 13.5px; }

.p-hero-actions {
  display: flex;
  align-items: center;
  gap: 12px;
  flex: none;
}

.p-hero-cta { gap: 8px; }

/* The account-status pill shares the login-card pill language. */
.p-hero-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
  padding: 4px 12px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
}

.p-hero-status .dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.p-hero-status--success { color: var(--success); background: var(--success-tint); }
.p-hero-status--danger { color: var(--danger); background: var(--danger-tint); }
.p-hero-status--neutral { color: var(--text-muted); background: var(--neutral-tint, var(--panel-2)); }

/* ---- quick links: quiet destination chips (no uniform card grid) ---- */
.p-quick-links {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  gap: 8px;
}

.p-quick-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 14px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--panel);
  color: var(--text);
  font-size: 13px;
  font-weight: 500;
  text-decoration: none;
  transition: border-color 140ms var(--ease-out), background-color 140ms var(--ease-out);
}

.p-quick-link svg { color: var(--text-muted); flex: none; }
.p-quick-link:hover { border-color: var(--border-strong); background: var(--bg-hover); }
.p-quick-link:hover svg { color: var(--accent); }
.p-quick-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

@media (max-width: 640px) {
  .p-hero { flex-wrap: wrap; }
  .p-hero-actions {
    width: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
  }
  .p-hero-status { align-self: flex-start; }
  .p-hero-cta { justify-content: center; }
  .p-quick-links { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 4px; }
  .p-quick-link { white-space: nowrap; }
  /* Long usage values ("1.0 GB of Unlimited") wrap instead of clipping. */
  .p-usage-head { flex-wrap: wrap; gap: 2px 10px; }
}

/* Hallmark · genre: watchful-console · macrostructure: long-document (login-card portal) · design-system: design.md · designed-as-app */
/* ---- login-card portal panel: cohesive with the split login ---- */
/* Initial-letter avatar (personal, not a generic shield glyph). */
.login-portal-avatar {
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 700;
}

/* The "Open my files" hero: the card's ONE red action. */
.login-card--portal .login-portal-hero {
  border-color: transparent;
  background: linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--accent) 72%, #000));
  color: #ffffff;
  box-shadow: var(--shadow-sm);
}

.login-card--portal .login-portal-hero:hover,
.login-card--portal .login-portal-hero:focus-visible {
  border-color: transparent;
  color: #ffffff;
  box-shadow: var(--glow-accent-sm, var(--shadow-md));
}

.login-card--portal .login-portal-hero-icon {
  background: rgba(255, 255, 255, 0.16);
  color: #ffffff;
}

.login-card--portal .login-portal-hero-sub { color: rgba(255, 255, 255, 0.78); }

.login-card--portal .login-portal-hero-arrow { color: rgba(255, 255, 255, 0.85); }

/* Underline tabs: active = text + accent underline, no filled pill. */
.login-card--portal .login-portal-tab {
  position: relative;
  margin-bottom: -1px;
  padding: 8px 13px 10px;
  border-bottom: 2px solid transparent;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  background: transparent;
}

.login-card--portal .login-portal-tab:hover {
  background: var(--bg-hover);
  color: var(--text);
}

.login-card--portal .login-portal-tab.is-active {
  background: transparent;
  color: var(--text);
  font-weight: 600;
  border-bottom-color: var(--accent);
}

.login-card--portal .login-portal-tab.is-active .login-portal-tab-badge {
  background: var(--accent);
  color: #ffffff;
}

/* Flush sections inside the card: the card is the surface, so shared
   panels lose their own chrome and separate by hairlines only. */
.login-card--portal .login-portal-pane .panel {
  border: 0;
  background: transparent;
  box-shadow: none;
}

.login-card--portal .login-portal-pane .panel + .panel {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--border-subtle);
}

.login-card--portal .login-portal-pane .panel-header {
  padding: 0 0 8px;
  border-bottom: 0;
}

.login-card--portal .login-portal-pane .panel-body { padding: 0; }

.login-card--portal .login-portal-pane .panel-body.flush { padding: 0; }

