/* Lintel web — mobile-first, accessible, no framework.
 *
 * Design rules baked in:
 *   - Mobile-first: base styles target ≥320px; media queries layer on width.
 *   - WCAG 2.2 AA: ≥44×44 CSS px tap targets, focus-visible rings, contrast ≥4.5:1.
 *   - Respect prefers-color-scheme (dark) and prefers-reduced-motion.
 *   - No webfont network calls — system stack only (avoids FOIT and tracking).
 *   - Container queries kept out of v1 to dodge older mobile browsers.
 */

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

/* The HTML `hidden` attribute must always win. Component classes like
   .btn-primary set an explicit `display`, which has the same specificity
   as the UA `[hidden] { display: none }` rule and — being author CSS —
   overrides it, leaving `hidden` buttons visible (e.g. the passkeys
   "Add" button in an unsupported browser). Force it. */
[hidden] { display: none !important; }

:root {
  color-scheme: light dark;

  /* Spacing — 4px base, fluid up. */
  --sp-1: 0.25rem;
  --sp-2: 0.5rem;
  --sp-3: 0.75rem;
  --sp-4: 1rem;
  --sp-5: 1.25rem;
  --sp-6: 1.5rem;
  --sp-8: 2rem;
  --sp-10: 2.5rem;

  /* Touch targets — WCAG 2.5.5 says ≥44 CSS px. We use 48 to be generous. */
  --touch: 3rem;

  /* Type — clamp() gives fluid sizing without a JS shim. */
  --t-body: clamp(1rem, 0.95rem + 0.25vw, 1.0625rem);
  --t-h1:   clamp(1.5rem, 1.2rem + 1.5vw, 2rem);
  --t-h2:   clamp(1.25rem, 1.1rem + 0.75vw, 1.5rem);
  --t-small: 0.875rem;
  /* Tabular mono — every timer / stat / reference renders in this per the
     "Compliance Instrument" type rule. System stack only (no webfont call). */
  --font-mono: ui-monospace, "SF Mono", "Cascadia Mono", "Roboto Mono", Menlo, Consolas, monospace;

  /* "Compliance Instrument" — cool blueprint neutrals + petrol brand.
     Colour is functional; the semantics carry the time-signal. */
  --bg:        #E8ECF1;
  --surface:   #ffffff;
  --border:    #D3DBE3;
  --text:      #111823;
  --text-muted:#56616F;
  --primary:   #0F3D57;
  --primary-fg:#ffffff;
  --primary-hover: #1C6C90;
  --danger:    #CF3333;
  --success:   #0C8A5E;
  --warning:   #B9760A;
  --focus:     #1C6C90;

  /* Accent — interactive highlight (selected states, "mine" chat tint,
     download links, active onboarding step). Distinct from --primary so a
     selection reads as a highlight, not a brand block. Shares the petrol
     focus hue so contrast is already proven. */
  --accent:    #1C6C90;
  /* Raised surface — cards sitting on a plain surface page (onboarding runs
     on a white body, so its cards need a step of elevation to read). */
  --surface-elev: #F1F5F9;
  /* Status token families — theme-aware so success/warning tints track the
     colour scheme instead of being frozen light-mode hex. */
  --ok:        #0C8A5E;
  --ok-bg:     #DCF3EA;
  --ok-text:   #075E3D;
  --warn:      #B9760A;
  --warn-bg:   #F8ECD4;
  --warn-text: #79510A;

  --radius: 11px;
  --shadow-card: 0 1px 2px rgba(16,28,40,.05), 0 6px 20px -14px rgba(16,28,40,.16);
  /* Centred masthead mark: a lintel (doorway beam) on two jambs with a plumb-bob. */
  --lintel-mark: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2040%2034'%3E%3Crect%20x='1'%20y='2.5'%20width='38'%20height='6.6'%20rx='2.2'/%3E%3Crect%20x='5.5'%20y='10.6'%20width='5.6'%20height='21'%20rx='1.7'/%3E%3Crect%20x='28.9'%20y='10.6'%20width='5.6'%20height='21'%20rx='1.7'/%3E%3Crect%20x='19.2'%20y='9'%20width='1.6'%20height='15'%20rx='.8'/%3E%3Ccircle%20cx='20'%20cy='26'%20r='2.7'/%3E%3C/svg%3E");
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg:        #090D14;
    --surface:   #121924;
    --border:    #232E3B;
    --text:      #E9EDF2;
    --text-muted:#93A0B1;
    --primary:   #2E7CA6;
    --primary-fg:#04121B;
    --primary-hover:#4FA6CE;
    --danger:    #FF6B6B;
    --success:   #3ED690;
    --warning:   #F0B44A;
    --focus:     #4FA6CE;
    --accent:    #4FA6CE;
    --surface-elev: #1B2635;
    --ok:        #3ED690;
    --ok-bg:     #10352A;
    --ok-text:   #83EBC0;
    --warn:      #F0B44A;
    --warn-bg:   #3B2D12;
    --warn-text: #F6D191;
    --shadow-card: 0 1px 2px rgba(0,0,0,.4), 0 10px 28px -16px rgba(0,0,0,.7);
  }
}

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
}

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

body {
  margin: 0;
  padding: 0;
  min-height: 100vh;
  min-height: 100svh;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto,
               "Helvetica Neue", Arial, sans-serif;
  font-size: var(--t-body);
  line-height: 1.5;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Skip link — keyboard users land on main content directly. */
.skip-link {
  position: absolute;
  inset-inline-start: var(--sp-2);
  inset-block-start: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  background: var(--primary);
  color: var(--primary-fg);
  border-radius: 8px;
  text-decoration: none;
  transform: translateY(-200%);
  transition: transform .15s ease;
  z-index: 100;
}
.skip-link:focus { transform: none; }

/* Header — sticky on mobile so brand stays anchored. */
.site-header {
  position: sticky;
  top: 0;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  padding: var(--sp-3) var(--sp-4);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-3);
  z-index: 10;
}
.site-header .brand {
  font-weight: 700;
  font-size: 1.0625rem;
  letter-spacing: -0.01em;
  color: var(--text);
  text-decoration: none;
}
.site-header .brand { display: inline-flex; align-items: center; }
.site-header .brand-mark {
  display: inline-block;
  width: 1.85rem; height: 1.6rem;
  background: var(--primary);
  -webkit-mask: var(--lintel-mark) center / contain no-repeat;
          mask: var(--lintel-mark) center / contain no-repeat;
  margin-inline-end: var(--sp-2);
  vertical-align: middle;
}

main { padding: var(--sp-6) var(--sp-4) var(--sp-10); }

.shell {
  max-width: 28rem;     /* ~448px — comfortable single column on phone */
  margin: 0 auto;
}

@media (min-width: 768px) {
  main { padding-block: var(--sp-10); }
}

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--sp-6);
  box-shadow: var(--shadow-card);
}

h1 { font-size: var(--t-h1); margin: 0 0 var(--sp-2); letter-spacing: -0.02em; }
h2 { font-size: var(--t-h2); margin: 0 0 var(--sp-2); letter-spacing: -0.01em; }
.lead { color: var(--text-muted); margin: 0 0 var(--sp-5); }

label {
  display: block;
  font-weight: 600;
  margin-block-end: var(--sp-2);
}
.hint {
  font-size: var(--t-small);
  color: var(--text-muted);
  margin-block-start: var(--sp-1);
}

input[type="email"],
input[type="text"],
input[type="password"] {
  width: 100%;
  min-height: var(--touch);
  padding: 0 var(--sp-4);
  font-size: var(--t-body);
  color: var(--text);
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: 10px;
  appearance: none;
  -webkit-appearance: none;
  transition: border-color .15s ease, box-shadow .15s ease;
}
input:focus-visible {
  outline: none;
  border-color: var(--focus);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--focus) 25%, transparent);
}

button, .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  width: 100%;
  min-height: var(--touch);
  padding: 0 var(--sp-5);
  font: inherit;
  font-weight: 600;
  color: var(--primary-fg);
  background: var(--primary);
  border: 0;
  border-radius: 10px;
  cursor: pointer;
  text-decoration: none;
  touch-action: manipulation;
  transition: background-color .15s ease, transform .05s ease;
}
button:hover, .btn:hover { background: var(--primary-hover); }
button:active, .btn:active { transform: translateY(1px); }
button:focus-visible, .btn:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
}
button[disabled], .btn[disabled] {
  opacity: .55;
  cursor: not-allowed;
}
button[aria-busy="true"] { opacity: .85; }

/* link-button — a button styled as inline text. Used where the
   element is semantically a button (an action, not navigation)
   but the visual treatment must read as inline link copy.
   Replaces the <a href=""> + onclick="..." anti-pattern flagged
   by §10.9 + accessibility (assistive tech reads "empty link"
   on href=""). */
button.link-button {
  display: inline;
  width: auto;
  min-height: 0;
  padding: 0;
  font-weight: inherit;
  color: var(--primary);
  background: transparent;
  border: 0;
  border-radius: 0;
  text-decoration: underline;
  cursor: pointer;
}
button.link-button:hover {
  background: transparent;
  text-decoration: none;
}
button.link-button:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
  border-radius: 2px;
}

.btn-secondary {
  color: var(--text);
  background: transparent;
  border: 1.5px solid var(--border);
}
.btn-secondary:hover { background: color-mix(in srgb, var(--text) 5%, transparent); }

.field { margin-block-end: var(--sp-5); }
.actions { display: flex; flex-direction: column; gap: var(--sp-3); margin-top: var(--sp-2); }

/* Status messages — assertive role required for HTMX swaps. */
.notice {
  margin-block-start: var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  border-radius: 10px;
  border: 1px solid var(--border);
  background: color-mix(in srgb, var(--success) 10%, var(--surface));
  color: var(--text);
}
.notice.error {
  background: color-mix(in srgb, var(--danger) 10%, var(--surface));
  border-color: color-mix(in srgb, var(--danger) 35%, var(--border));
}
.notice.warning {
  background: color-mix(in srgb, var(--warn, #f59e0b) 10%, var(--surface));
  border-color: color-mix(in srgb, var(--warn, #f59e0b) 35%, var(--border));
}
.notice .title { font-weight: 600; margin: 0 0 var(--sp-1); }
.notice .body  { margin: 0; color: var(--text-muted); }
.notice .hint  { font-size: 0.875rem; color: var(--text-muted); margin: var(--sp-1) 0 0; padding-inline-start: var(--sp-4); }
.field-hint    { font-size: 0.8125rem; color: var(--text-muted); margin: var(--sp-1) 0 0; }

/* Photo grid on issue detail. Mobile-first: 2 columns; >= 480px gets 3; */
/* >= 720px gets 4. Square thumbnails via aspect-ratio with object-fit. */
.photo-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-3);
  list-style: none;
  margin: 0;
  padding: 0;
}
@media (min-width: 480px) { .photo-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 720px) { .photo-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.photo-tile { display: flex; flex-direction: column; gap: var(--sp-2); }
.photo-tile a { display: block; line-height: 0; border-radius: 8px; overflow: hidden; border: 1px solid var(--border); }
.photo-tile img { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; display: block; }
.photo-meta { display: flex; justify-content: space-between; align-items: baseline; gap: var(--sp-2); font-size: 0.8125rem; }
.photo-filename { color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.photo-download { color: var(--accent); text-decoration: none; flex-shrink: 0; }
.photo-download:hover { text-decoration: underline; }

/* Message timeline (§5.27 in-app chat) -------------------------------- */
.thread-messages {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  max-height: min(60vh, 480px);
  overflow-y: auto;
}
.message {
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: var(--sp-2) var(--sp-3);
  background: var(--surface);
  max-width: 85%;
}
.message-mine {
  align-self: flex-end;
  background: color-mix(in srgb, var(--accent) 8%, var(--surface));
  border-color: color-mix(in srgb, var(--accent) 25%, var(--border));
}
.message-theirs {
  align-self: flex-start;
}
.message-head {
  display: flex;
  align-items: baseline;
  gap: var(--sp-2);
  font-size: 0.8125rem;
  color: var(--text-muted);
  margin-bottom: var(--sp-1);
}
.message-sender { font-weight: 600; color: var(--text); }
.message-time { font-variant-numeric: tabular-nums; }
.message-safety {
  margin-left: auto;
  color: var(--danger);
  font-weight: 600;
  font-size: 0.75rem;
}
.message-body {
  margin: 0;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.message-composer {
  display: flex;
  gap: var(--sp-2);
  align-items: flex-end;
}
.message-composer textarea {
  flex: 1;
  min-height: 2.5rem;
  resize: vertical;
  font-family: inherit;
}
.message-composer button {
  flex-shrink: 0;
}

/* Complaint response list (§4.10) ------------------------------------- */
.response-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}
.response-row {
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: var(--sp-3);
  background: var(--surface);
}
.response-head {
  display: flex;
  align-items: baseline;
  gap: var(--sp-2);
  font-size: 0.8125rem;
  color: var(--text-muted);
  margin-bottom: var(--sp-2);
  flex-wrap: wrap;
}
.response-stage { font-weight: 600; color: var(--text); }
.response-author { margin-left: auto; font-style: italic; }
.response-time { font-variant-numeric: tabular-nums; }
.response-body {
  margin: 0;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

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

/* Tabular-figure utility — aligns digits in compliance tables / numeric cells. */
.tnum { font-variant-numeric: tabular-nums; }

/* Reduce-motion-friendly spinner used by HTMX while a request is in flight. */
.spinner {
  display: inline-block;
  width: 1rem; height: 1rem;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.htmx-request .spinner { display: inline-block; }
.htmx-request button[type="submit"] { pointer-events: none; }

/* Footer — small, muted, mobile-friendly stacking. */
.site-footer {
  margin-top: var(--sp-10);
  padding: var(--sp-6) var(--sp-4);
  border-top: 1px solid var(--border);
  color: var(--text-muted);
  font-size: var(--t-small);
  text-align: center;
}
.site-footer a { color: inherit; }

/* When the device is in landscape and short (e.g. a phone in landscape), drop
 * the sticky header so the form keeps as much vertical room as possible. */
@media (max-height: 480px) and (orientation: landscape) {
  .site-header { position: static; }
  main { padding-block: var(--sp-4); }
}

/* ============================================================================
 * Admin shell — WP-admin-like sidebar + top bar + content surface.
 * Mobile: sidebar collapses behind a burger button (CSS-only via :checked).
 * ============================================================================ */

:root {
  --side-w: 15.5rem;
  --side-bg: #0f172a;          /* slate-900 */
  --side-bg-2: #1e293b;        /* slate-800 — divider tone */
  --side-fg: #f1f5f9;           /* slate-100 */
  --side-fg-muted: #94a3b8;     /* slate-400 */
  --side-fg-subtle: #8b98a9;    /* WCAG 2.2 AA: ≥4.5:1 on --side-bg/--side-bg-2 (slate-500 #64748b failed at 3.1–3.8:1) */
  --side-active: #6366f1;       /* indigo-500 */
  --side-active-soft: color-mix(in srgb, #6366f1 14%, transparent);
  --side-hover: color-mix(in srgb, #f1f5f9 6%, transparent);
  --side-border: color-mix(in srgb, #f1f5f9 9%, transparent);
  --topbar-h: 3.5rem;
}
@media (prefers-color-scheme: dark) {
  :root {
    --side-bg: #020617;        /* slate-950 in dark mode */
    --side-bg-2: #0f172a;
  }
}

/* Reset body padding when admin shell renders — main is laid out by the
 * shell itself, not by .shell auto-margins. */
body.page-app { background: var(--bg); }
body.page-app main { padding: 0; }

.app {
  display: grid;
  grid-template-columns: var(--side-w) minmax(0, 1fr);
  grid-template-rows: 100vh;
  grid-template-rows: 100dvh;
  min-height: 100vh;
  min-height: 100dvh;
}

/* ---------- Sidebar -----------------------------------------------------
 * Type scale: 12px (labels) / 13px (foot) / 14px (nav, name).
 * Anything outside this scale is a defect — the sidebar reads as
 * professional only when the vertical rhythm is consistent.
 * ------------------------------------------------------------------------ */

.app-side {
  background: var(--side-bg);
  color: var(--side-fg);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100dvh;
  overflow-y: auto;
  border-right: 1px solid var(--side-border);
}

/* Brand --------------------------------------------------------- */
.app-side .side-brand {
  display: flex; align-items: center; gap: 0.625rem;
  padding: 1.125rem 1.25rem;
  font-weight: 600; font-size: 0.9375rem; letter-spacing: -0.01em;
  color: var(--side-fg);
  text-decoration: none;
  border-bottom: 1px solid var(--side-border);
  min-height: var(--topbar-h);
}
.app-side .side-brand .brand-mark {
  width: 1.75rem; height: 1.75rem;
  border-radius: 7px;
  background: linear-gradient(135deg, #6366f1 0%, #818cf8 100%);
  display: inline-flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 0.875rem; line-height: 1;
  color: #fff;
  box-shadow: 0 1px 2px rgba(0,0,0,.25), inset 0 1px 0 rgba(255,255,255,.18);
  flex-shrink: 0;
}
.app-side .side-brand .brand-name {
  font-weight: 600;
}

/* Org chip ------------------------------------------------------ */
.app-side .side-org {
  padding: 0.875rem 1.25rem;
  border-bottom: 1px solid var(--side-border);
}
.app-side .side-org-label {
  display: block;
  font-size: 0.6875rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--side-fg-subtle);
  margin-bottom: 0.375rem;
}
.app-side .side-org-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 0.5rem;
  min-width: 0;
}
.app-side .side-org-value {
  color: var(--side-fg);
  font-weight: 600;
  font-size: 0.8125rem;
  letter-spacing: -0.005em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  min-width: 0;
}

/* Nav ----------------------------------------------------------- */
.side-nav {
  list-style: none; padding: 0.625rem 0.625rem; margin: 0;
  display: block;
  flex: 1 1 auto;
  overflow-y: auto;
}
.side-nav ul { list-style: none; padding: 0; margin: 0; }
.side-nav .nav-section-label {
  padding: 0.875rem 0.625rem 0.375rem;
  font-size: 0.6875rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--side-fg-subtle);
}
.side-nav a {
  display: flex; align-items: center; gap: 0.625rem;
  padding: 0.5rem 0.625rem;
  border-radius: 6px;
  color: var(--side-fg-muted);
  text-decoration: none;
  font-size: 0.875rem;
  font-weight: 500;
  line-height: 1.25rem;
  min-height: 2rem;
  position: relative;
  transition: color .12s ease, background-color .12s ease;
}
.side-nav a:hover {
  background: var(--side-hover);
  color: var(--side-fg);
}
.side-nav a:focus-visible {
  outline: 2px solid var(--side-active);
  outline-offset: 2px;
}
.side-nav a[aria-current="page"] {
  background: var(--side-active-soft);
  color: #fff;
  font-weight: 600;
  box-shadow: inset 2px 0 0 var(--side-active);
}
.side-nav .nav-icon {
  display: inline-flex; width: 1.125rem; height: 1.125rem;
  align-items: center; justify-content: center;
  flex-shrink: 0;
  color: currentColor;
}
.side-nav .nav-icon svg { width: 100%; height: 100%; }

/* Foot — vertical stack: PWA → Settings → user card -------------- */
.side-foot {
  margin-top: auto;
  padding: 0.625rem 0.625rem 0.875rem;
  border-top: 1px solid var(--side-border);
  display: flex; flex-direction: column; gap: 0.125rem;
}
.side-foot-link {
  display: flex; align-items: center; gap: 0.625rem;
  padding: 0.5rem 0.625rem;
  border-radius: 6px;
  color: var(--side-fg-muted);
  background: none;
  border: 0;
  text-decoration: none;
  font-size: 0.8125rem;
  font-weight: 500;
  line-height: 1.25rem;
  width: 100%;
  text-align: left;
  cursor: pointer;
  font-family: inherit;
  transition: color .12s ease, background-color .12s ease;
}
.side-foot-link svg {
  width: 1rem; height: 1rem; flex-shrink: 0;
}
.side-foot-link:hover {
  background: var(--side-hover);
  color: var(--side-fg);
}
.side-foot-link:focus-visible {
  outline: 2px solid var(--side-active);
  outline-offset: 2px;
}
.side-foot-link[aria-current="page"] {
  color: #fff;
  background: var(--side-active-soft);
}
.side-foot-link[hidden] { display: none; }
.side-foot-link[disabled] {
  opacity: 0.6;
  cursor: default;
}
.side-foot-link[disabled]:hover {
  background: none;
  color: var(--side-fg-muted);
}

.side-pwa {
  display: flex; flex-direction: column; gap: 0.125rem;
  margin-bottom: 0.125rem;
}
/* When both PWA buttons end up hidden (Safari without
 * service-worker / PushManager, Firefox without
 * beforeinstallprompt, headless browsers, etc.) collapse
 * the wrapper so the foot stack doesn't carry a stray gap. */
.side-pwa:not(:has(.side-foot-link:not([hidden]))) {
  display: none;
}

/* User card with inline sign-out icon ---------------------------- */
.side-user {
  display: flex; align-items: center; gap: 0.625rem;
  padding: 0.625rem 0.625rem;
  margin-top: 0.5rem;
  border-radius: 8px;
  border: 1px solid var(--side-border);
  background: var(--side-bg-2);
  min-width: 0;
}
.side-user .avatar {
  width: 2rem; height: 2rem; border-radius: 50%;
  background: linear-gradient(135deg, #6366f1 0%, #818cf8 100%);
  color: #fff;
  display: inline-flex; align-items: center; justify-content: center;
  font-weight: 600; font-size: 0.75rem; line-height: 1;
  flex-shrink: 0;
  box-shadow: 0 1px 2px rgba(0,0,0,.2);
}
.side-user .who { min-width: 0; flex: 1 1 auto; line-height: 1.2; }
.side-user .who .name {
  display: block;
  font-size: 0.8125rem; font-weight: 600; color: var(--side-fg);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.side-user .who .email {
  display: block;
  font-size: 0.6875rem; color: var(--side-fg-subtle);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  margin-top: 1px;
}
.side-signout-form { margin: 0; flex-shrink: 0; }
.side-signout-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2rem; height: 2rem;
  padding: 0;
  background: none; border: 0;
  border-radius: 6px;
  color: var(--side-fg-muted);
  cursor: pointer;
  transition: color .12s ease, background-color .12s ease;
}
.side-signout-btn svg { width: 1rem; height: 1rem; }
.side-signout-btn:hover {
  background: color-mix(in srgb, #ef4444 25%, transparent);
  color: #fee2e2;
}
.side-signout-btn:focus-visible {
  outline: 2px solid var(--side-active);
  outline-offset: 2px;
}

/* ---------- Top bar + content -------------------------------------------- */

.app-main {
  display: flex; flex-direction: column;
  min-height: 100vh; min-height: 100dvh;
  min-width: 0;
}
.topbar {
  position: sticky; top: 0; z-index: 5;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  height: var(--topbar-h);
  padding: 0 var(--sp-5);
  display: flex; align-items: center; gap: var(--sp-4);
}
.topbar .page-title {
  font-size: 1.0625rem; font-weight: 600; margin: 0; letter-spacing: -0.01em;
}
.topbar .topbar-right {
  margin-inline-start: auto; display: flex; align-items: center; gap: var(--sp-2);
}
.topbar .pill {
  padding: 4px 10px; border-radius: 999px;
  font-size: 0.75rem; font-weight: 600;
  background: color-mix(in srgb, var(--success) 16%, transparent);
  color: var(--success);
}

.app-content {
  padding: var(--sp-6) var(--sp-5);
  flex: 1;
  /* Scroll content internally so the fixed-height shell (and the sticky
   * sidebar) stay put instead of the whole page scrolling. min-height:0 is
   * required for a flex child to shrink below its content and scroll. */
  overflow-y: auto;
  min-height: 0;
}
.app-content > * + * { margin-block-start: var(--sp-6); }

@media (min-width: 1024px) {
  .app-content { padding: var(--sp-8) var(--sp-8); }
}

/* ---------- Mobile collapsible sidebar ----------------------------------- */

.menu-toggle { display: none; }
.menu-button {
  display: none;
  background: transparent;
  border: 0;
  color: var(--text);
  width: var(--touch); height: var(--touch);
  min-height: var(--touch);
  padding: 0;
  border-radius: 8px;
  cursor: pointer;
  align-items: center; justify-content: center;
  flex: 0 0 auto;
}
.menu-button:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.menu-button svg { width: 24px; height: 24px; }

@media (max-width: 839px) {
  .app { grid-template-columns: 1fr; }
  .app-side {
    position: fixed; inset: 0 30% 0 0;
    width: 70vw; max-width: 20rem;
    transform: translateX(-100%);
    transition: transform .2s ease;
    z-index: 50;
    box-shadow: 0 0 40px rgba(0,0,0,.35);
  }
  .menu-toggle:checked ~ .app .app-side { transform: translateX(0); }
  .menu-toggle:checked ~ .app::before {
    content: ""; position: fixed; inset: 0; background: rgba(0,0,0,.4); z-index: 40;
  }
  .menu-button { display: inline-flex; }
  .app-content { padding: var(--sp-5) var(--sp-4); }

  /* Touch-target sizing inside the slide-out sidebar.
   * Apple HIG + WCAG 2.5.5 both want ≥ 44 × 44px. Desktop
   * uses tighter 32px rows; mobile bumps to 44px so the
   * tenant PWA install + tap-to-navigate UX is comfortable. */
  .side-nav a,
  .side-foot-link {
    min-height: 2.75rem;     /* 44px */
    font-size: 0.9375rem;     /* 15px reads better on small displays */
    padding: 0.625rem 0.75rem;
  }
  .side-signout-btn {
    width: 2.75rem; height: 2.75rem;
  }
  .side-user {
    padding: 0.75rem;
  }
}

/* ---------- Cards / panels ----------------------------------------------- */

.panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  overflow: hidden;
}
.panel-head {
  padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--border);
  display: flex; align-items: center; gap: var(--sp-3);
}
.panel-head h2 {
  margin: 0; font-size: 1rem; font-weight: 600;
}
.panel-head .panel-sub {
  margin-inline-start: auto;
  font-size: var(--t-small); color: var(--text-muted);
}
.panel-body { padding: var(--sp-5); }

/* ---------- Stat tiles --------------------------------------------------- */

.stat-grid {
  display: grid; gap: var(--sp-4);
  grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
}
.stat-tile {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--sp-5);
  box-shadow: var(--shadow-card);
}
.stat-tile .stat-label {
  font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text-muted);
  margin: 0 0 var(--sp-2);
}
.stat-tile .stat-value {
  font-size: 1.875rem; font-weight: 700; line-height: 1;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  margin: 0;
  overflow-wrap: anywhere;
}

/* ---------- Composer (submit form) --------------------------------------- */

.composer .field { margin-block-end: var(--sp-4); }

textarea {
  width: 100%;
  min-height: calc(var(--touch) * 2);
  padding: var(--sp-3) var(--sp-4);
  font: inherit;
  color: var(--text);
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: 10px;
  resize: vertical;
}
textarea:focus-visible {
  outline: none;
  border-color: var(--focus);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--focus) 25%, transparent);
}

select {
  width: 100%;
  min-height: var(--touch);
  padding: 0 var(--sp-10) 0 var(--sp-4);
  font: inherit;
  color: var(--text);
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: 10px;
  appearance: none;
  -webkit-appearance: none;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--text-muted) 50%),
    linear-gradient(135deg, var(--text-muted) 50%, transparent 50%);
  background-position: right var(--sp-4) center, right calc(var(--sp-4) + 6px) center;
  background-size: 6px 6px;
  background-repeat: no-repeat;
}
select:focus-visible {
  outline: none;
  border-color: var(--focus);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--focus) 25%, transparent);
}

/* Composer actions sit horizontally on tablet+ but keep button at min touch
 * size on phone. */
.composer .actions { flex-direction: row; justify-content: flex-end; }
.composer .actions button { width: auto; min-width: 12rem; }
@media (max-width: 559px) {
  .composer .actions { flex-direction: column; }
  .composer .actions button { width: 100%; }
}

/* ---------- Empty state -------------------------------------------------- */

.empty-state {
  border: 1.5px dashed var(--border);
  border-radius: var(--radius);
  padding: var(--sp-8) var(--sp-5);
  text-align: center;
  color: var(--text-muted);
  background: color-mix(in srgb, var(--surface) 60%, transparent);
}
.empty-state .empty-title {
  font-weight: 600; color: var(--text); margin: 0 0 var(--sp-2);
}
.empty-state .empty-body { margin: 0; }

/* ---------- Issue list (table-ish on desktop, cards on phone) ----------- */

.issue-list {
  list-style: none; padding: 0; margin: 0;
  display: grid; gap: var(--sp-2);
}
.issue-row {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--sp-4);
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-2);
  transition: border-color .12s ease, box-shadow .12s ease;
}
.issue-row:hover { border-color: color-mix(in srgb, var(--primary) 25%, var(--border)); box-shadow: var(--shadow-card); }
.issue-meta {
  display: flex; gap: var(--sp-3); align-items: center;
  font-size: var(--t-small);
}
.issue-ref { color: var(--text-muted); font-variant-numeric: tabular-nums; }
.issue-state {
  display: inline-flex; align-items: center;
  padding: 2px var(--sp-2);
  border-radius: 999px;
  font-weight: 600;
  font-size: 0.75rem;
  background: color-mix(in srgb, var(--text) 8%, transparent);
  color: var(--text);
  white-space: nowrap;
}
.issue-state.state-submitted    { background: color-mix(in srgb, var(--primary) 18%, transparent); color: var(--primary); }
.issue-state.state-triaged      { background: color-mix(in srgb, var(--success) 18%, transparent); color: var(--success); }
.issue-state.state-acknowledged { background: color-mix(in srgb, var(--success) 18%, transparent); color: var(--success); }
.issue-state.state-escalated-hazard,
.issue-state.state-safety-interrupt { background: color-mix(in srgb, var(--danger) 18%, transparent); color: var(--danger); }

.issue-title { font-weight: 600; min-width: 0; overflow-wrap: anywhere; }
.issue-tail {
  display: flex; gap: var(--sp-3);
  font-size: var(--t-small);
  color: var(--text-muted);
}
.issue-tail .issue-time { margin-inline-start: auto; font-variant-numeric: tabular-nums; }

@media (min-width: 768px) {
  .issue-row { grid-template-columns: minmax(0, 1fr) auto; align-items: start; }
  .issue-meta { grid-row: 1; grid-column: 2; justify-self: end; }
  .issue-title { grid-row: 1; grid-column: 1; }
  .issue-tail { grid-row: 2; grid-column: 1 / span 2; }
}

/* ---------- Notice variants on dashboard --------------------------------- */

.composer .notice { margin-block-start: var(--sp-4); }

/* ---------- Role pill / topbar new-issue button -------------------------- */

.role-pill {
  display: inline-flex; align-items: center;
  padding: 2px 0.5rem;
  border-radius: 999px;
  font-size: 0.625rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  line-height: 1rem;
  background: color-mix(in srgb, var(--side-active) 28%, transparent);
  color: var(--side-fg);
  border: 1px solid color-mix(in srgb, var(--side-active) 35%, transparent);
  flex-shrink: 0;
  white-space: nowrap;
}
.role-pill[data-role="council_admin"], .role-pill[data-role="council_officer"] {
  background: color-mix(in srgb, #06b6d4 22%, transparent);
  border-color: color-mix(in srgb, #06b6d4 38%, transparent);
}
.role-pill[data-role="tenant"] {
  background: color-mix(in srgb, #15803d 22%, transparent);
  border-color: color-mix(in srgb, #15803d 40%, transparent);
}
.role-pill[data-role="contractor"] {
  background: color-mix(in srgb, #ea580c 22%, transparent);
  border-color: color-mix(in srgb, #ea580c 40%, transparent);
}

.btn-pill {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-4);
  background: var(--primary);
  color: var(--primary-fg);
  font-weight: 600;
  font-size: 0.875rem;
  border-radius: 999px;
  text-decoration: none;
  min-height: 0;
  transition: background-color .12s ease;
}
.btn-pill:hover { background: var(--primary-hover); }
.btn-pill:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }

/* ---------- Composer disclosure (collapsed by default) ------------------- */

details.composer-disclose {
  padding: 0;
  overflow: hidden;
}
details.composer-disclose > summary {
  list-style: none;
  cursor: pointer;
  user-select: none;
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5);
  background: linear-gradient(to right,
    color-mix(in srgb, var(--primary) 8%, var(--surface)),
    var(--surface) 70%);
  font-weight: 600;
  color: var(--text);
  border-bottom: 1px solid transparent;
  transition: border-color .12s ease;
}
details.composer-disclose > summary::-webkit-details-marker { display: none; }
details.composer-disclose > summary::marker { content: ""; }
details.composer-disclose[open] > summary {
  border-bottom-color: var(--border);
}
.composer-summary-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2rem; height: 2rem;
  border-radius: 999px;
  background: var(--primary);
  color: var(--primary-fg);
}
.composer-summary-icon svg { width: 16px; height: 16px; }
.composer-summary-hint {
  margin-inline-start: auto;
  font-weight: 400;
  font-size: var(--t-small);
  color: var(--text-muted);
}
@media (max-width: 559px) {
  .composer-summary-hint { display: none; }
}

/* ---------- Filter bar --------------------------------------------------- */

.filter-bar {
  display: flex; gap: var(--sp-2);
  overflow-x: auto;
  scrollbar-width: thin;
  padding-bottom: var(--sp-1);
  margin-block: var(--sp-4);
  /* Anti-clip so focus rings on edge pills aren't sliced. */
  padding-inline: 2px;
}
.filter-pill {
  flex-shrink: 0;
  padding: var(--sp-2) var(--sp-4);
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 999px;
  font-size: 0.875rem;
  font-weight: 500;
  cursor: pointer;
  width: auto; min-height: 0;
  transition: background-color .12s ease, border-color .12s ease, color .12s ease;
}
.filter-pill:hover { border-color: color-mix(in srgb, var(--primary) 35%, var(--border)); }
.filter-pill:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.filter-pill.is-active {
  background: var(--primary);
  color: var(--primary-fg);
  border-color: var(--primary);
}

/* ---------- Stat tile clickable affordance ------------------------------ */

.stat-tile.is-clickable {
  display: block;
  width: 100%;
  text-align: start;
  cursor: pointer;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  min-height: 0;
  transition: border-color .12s ease, transform .08s ease, box-shadow .12s ease;
}
.stat-tile.is-clickable:hover {
  border-color: color-mix(in srgb, var(--primary) 35%, var(--border));
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(0,0,0,.08);
}
.stat-tile.is-clickable:focus-visible {
  outline: 3px solid var(--focus); outline-offset: 2px;
}
.stat-tile.is-clickable.is-active {
  border-color: var(--primary);
  box-shadow: inset 0 0 0 1px var(--primary);
}

/* Active status lens chip on the portfolio rollup. */
.active-filter {
  display: flex;
  align-items: center;
  gap: .75rem;
  margin: .25rem 0 1rem;
  font-size: .9375rem;
  color: var(--text-muted);
}
.active-filter strong { color: var(--text); }
.active-filter-clear { color: var(--primary); text-decoration: underline; }
.stat-tile.is-clickable .stat-label,
.stat-tile.is-clickable .stat-value {
  display: block; margin: 0;
}
.stat-tile .stat-value.muted { color: var(--text-muted); font-weight: 600; font-size: 1.0625rem; }
.stat-tile .stat-value.danger { color: var(--danger); }

/* ---------- Issue list: clickable rows ---------------------------------- */

.issue-list a.issue-link {
  text-decoration: none;
  color: inherit;
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-2);
}
.issue-row.issue-link:hover .issue-title {
  color: var(--primary);
}

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

.breadcrumb {
  font-size: var(--t-small);
  color: var(--text-muted);
  display: flex; gap: var(--sp-2);
  margin-block-end: var(--sp-3);
}
.breadcrumb a { color: var(--text-muted); text-decoration: none; }
.breadcrumb a:hover { color: var(--primary); }
.breadcrumb [aria-current="page"] { color: var(--text); font-weight: 600; }

.issue-detail-heading {
  display: flex; flex-direction: column; gap: var(--sp-1);
  margin: 0;
}
.issue-ref-large {
  font-size: var(--t-small);
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  font-weight: 500;
}
.issue-detail-title {
  font-size: 1.125rem;
  font-weight: 600;
  color: var(--text);
}
.issue-facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
  gap: var(--sp-4);
  margin: 0 0 var(--sp-4);
}
.issue-facts > div { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.issue-facts dt {
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
}
.issue-facts dd { margin: 0; font-weight: 500; overflow-wrap: anywhere; }
.issue-description h3 {
  font-size: 0.875rem; font-weight: 600;
  margin: 0 0 var(--sp-2);
  color: var(--text-muted);
  text-transform: uppercase; letter-spacing: 0.06em;
}
.issue-description p { margin: 0; line-height: 1.6; }

.action-bar { display: flex; gap: var(--sp-3); flex-wrap: wrap; }
.action-bar .inline-action { margin: 0; }
.btn-secondary {
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--surface);
  color: var(--text);
  border: 1.5px solid var(--border);
  padding: var(--sp-2) var(--sp-4);
  border-radius: 10px;
  font-weight: 600;
  width: auto; min-height: var(--touch);
  cursor: pointer;
}
.btn-secondary:hover { border-color: var(--primary); color: var(--primary); }

.timeline {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: var(--sp-3);
}
.timeline li {
  display: grid; grid-template-columns: minmax(0, 8rem) minmax(0, 1fr);
  gap: var(--sp-3);
  padding-bottom: var(--sp-3);
  border-bottom: 1px dashed var(--border);
}
.timeline li:last-child { border-bottom: 0; }
.timeline time { color: var(--text-muted); font-size: var(--t-small); overflow-wrap: anywhere; }
.timeline-action { font-weight: 600; overflow-wrap: anywhere; }
.timeline-desc { display: block; color: var(--text-muted); font-size: var(--t-small); min-width: 0; overflow-wrap: anywhere; }

/* ---------- Analytics row + chart panels -------------------------------- */

.analytics-row {
  display: grid;
  gap: var(--sp-4);
  grid-template-columns: 1fr;
}
@media (min-width: 900px) {
  .analytics-row { grid-template-columns: 1fr 1fr; }
  .analytics-row > .chart-panel-wide { grid-column: 1 / span 2; }
}
@media (min-width: 1280px) {
  .analytics-row { grid-template-columns: 1fr 1fr 1fr; }
  .analytics-row > .chart-panel-wide { grid-column: 1 / span 3; }
}

/* Each panel is its own query container so .chart-body reacts to the panel's
   own width, not the viewport. At mid widths (e.g. 1280px laptop) the
   analytics row packs 2-3 panels side-by-side, leaving each panel too narrow
   for the side-by-side chart+legend layout; a viewport media query cannot see
   that. The container query below only splits into two columns once the panel
   itself is wide enough to leave the legend track a usable width (~11rem at
   the 26rem threshold), otherwise .chart-body stays stacked (chart on top,
   full-width legend below) so legend labels never wrap one char per line. */
.chart-panel { overflow: hidden; container: chart-panel / inline-size; }
.chart-body {
  display: grid; gap: var(--sp-4);
  grid-template-columns: minmax(0, 1fr);
}
@container chart-panel (min-width: 26rem) {
  .chart-body { grid-template-columns: minmax(8rem, 14rem) minmax(0, 1fr); align-items: center; }
  .chart-body-histogram { grid-template-columns: minmax(0, 1fr); }
}
.chart-canvas-wrap {
  position: relative;
  width: 100%;
  aspect-ratio: 1;
  min-height: 12rem;
  max-height: 16rem;
}
.chart-canvas-wide { aspect-ratio: 16 / 5; max-height: 18rem; }
.chart-canvas { width: 100% !important; height: 100% !important; }

.chart-legend {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: var(--sp-2);
  font-size: 0.875rem;
}
.chart-legend li {
  display: grid;
  grid-template-columns: 1rem minmax(0, 1fr) auto auto;
  gap: var(--sp-2);
  align-items: start;
}
.legend-swatch {
  display: inline-block; width: 0.875rem; height: 0.875rem;
  border-radius: 4px;
  margin-block-start: 0.15em; /* optical align with first text line now rows are top-aligned */
}
/* The flexible label track must be allowed to shrink below its content's
   min-content width, otherwise a long category name forces the grid wider
   than its column and the value/percentage get clipped (the pie-legend bug). */
.legend-label { color: var(--text); min-width: 0; overflow-wrap: anywhere; }
.legend-value {
  color: var(--text);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}
.legend-pct {
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  font-size: var(--t-small);
}

/* ---------- Page-entry animation -------------------------------------- */

@keyframes panelFadeUp {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.app-content > .panel,
.app-content > .stat-grid > *,
.app-content > .analytics-row > *,
.app-content > details.composer-disclose {
  animation: panelFadeUp .35s ease-out both;
}
.app-content > .stat-grid > *:nth-child(1) { animation-delay: 0ms; }
.app-content > .stat-grid > *:nth-child(2) { animation-delay: 60ms; }
.app-content > .stat-grid > *:nth-child(3) { animation-delay: 120ms; }
.app-content > .analytics-row > *:nth-child(1) { animation-delay: 80ms; }
.app-content > .analytics-row > *:nth-child(2) { animation-delay: 140ms; }
.app-content > .analytics-row > *:nth-child(3) { animation-delay: 200ms; }

@media (prefers-reduced-motion: reduce) {
  .app-content > .panel,
  .app-content > .stat-grid > *,
  .app-content > .analytics-row > *,
  .app-content > details.composer-disclose {
    animation: none !important;
  }
}

/* Hover lift on chart panels — subtle, mirrors stat-tile feel. */
.chart-panel { transition: box-shadow .18s ease, transform .18s ease; }
.chart-panel:hover {
  box-shadow: 0 8px 24px -6px rgba(0,0,0,.12), 0 1px 2px rgba(0,0,0,.04);
}

/* ---------- Composer multi-field grid ---------------------------------- */

.field-grid {
  display: grid;
  gap: var(--sp-4);
  grid-template-columns: 1fr;
}
@media (min-width: 640px) {
  .field-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 960px) {
  .field-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
.required-mark {
  color: var(--danger);
  font-weight: 700;
  margin-inline-start: 2px;
}

/* ---------- Legal pages ----------------------------------------------- */

body.page-legal main.legal-shell {
  max-width: 44rem; margin: 0 auto;
  padding: var(--sp-8) var(--sp-5);
}
body.page-legal h1 { font-size: var(--t-h1); margin: 0 0 var(--sp-2); }
body.page-legal h2 { font-size: 1.0625rem; margin: var(--sp-6) 0 var(--sp-2); }
body.page-legal section { margin-block-end: var(--sp-6); }
body.page-legal p, body.page-legal li { line-height: 1.6; }
body.page-legal ul { padding-inline-start: var(--sp-5); }

/* ---------- Abbreviation tooltips (WCAG 2.2 AA H28) ------------------- */
/*
 * <abbr class="abbr-glossary"> renders with a dotted underline as a
 * visual affordance that hovering / focusing yields more info. The
 * native title attribute is the accessible name (announced by every
 * screen reader); tabindex=0 on the markup makes the element
 * keyboard-focusable so non-pointer users can read the tooltip too.
 * cursor: help is the standardised UI signal for "tooltip available";
 * touch devices show on long-press; keyboard users focus to read.
 */
.abbr-glossary {
  text-decoration: underline dotted;
  text-underline-offset: 0.18em;
  cursor: help;
  border-radius: 2px;
}
.abbr-glossary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  background-color: color-mix(in oklab, var(--accent) 12%, transparent);
}

/* ---------- §16.1 Onboarding wizard ---------------------------------- */
/* Distinct from page-app — no sidebar; centred narrow column for focus. */

body.page-onboarding {
  background: var(--surface);
}
body.page-onboarding .site-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--sp-3) var(--sp-5);
  border-block-end: 1px solid var(--border);
}
body.page-onboarding .header-signout button {
  font-size: 0.875rem;
}
.onboarding-shell {
  max-width: 38rem;
  margin: 0 auto;
  padding: var(--sp-6) var(--sp-5) var(--sp-8);
}
.onboarding-progress {
  margin-block-end: var(--sp-6);
}
.onboarding-progress .progress-steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--sp-2);
}
/* Four equal columns overflow at 320px once step labels are more than one word.
   Reflow to a 2×2 grid on the narrowest screens. */
@media (max-width: 400px) {
  .onboarding-progress .progress-steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.onboarding-progress .step-label { overflow-wrap: anywhere; }
.onboarding-progress .step {
  display: flex;
  flex-direction: column;
  gap: 4px;
  align-items: center;
  padding: var(--sp-2);
  border-radius: 8px;
  background: var(--surface-elev);
  border: 1px solid var(--border);
  font-size: 0.75rem;
  text-align: center;
}
.onboarding-progress .step-number {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 50%;
  border: 1px solid var(--border);
  font-weight: 600;
  background: var(--surface);
}
.onboarding-progress .step-active {
  border-color: var(--accent);
  background: color-mix(in oklab, var(--accent) 8%, transparent);
}
.onboarding-progress .step-active .step-number {
  background: var(--accent);
  color: var(--surface);
  border-color: var(--accent);
}
.onboarding-progress .step-done .step-number {
  background: var(--ok, #10b981);
  color: var(--surface);
  border-color: var(--ok, #10b981);
}
.onboarding-progress .step-future {
  opacity: 0.5;
}

.onboarding-panel { margin-block-start: 0; }

/* Language picker — grid of cards */
.language-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
  gap: var(--sp-3);
  border: 0;
  margin: 0 0 var(--sp-4);
  padding: 0;
}
.language-card {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--sp-3);
  border: 1.5px solid var(--border);
  border-radius: 8px;
  cursor: pointer;
  background: var(--surface-elev);
  transition: border-color 100ms, background-color 100ms;
}
.language-card input[type="radio"] {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.language-card:has(input:checked),
.language-card-selected {
  border-color: var(--accent);
  background: color-mix(in oklab, var(--accent) 6%, transparent);
}
.language-card:focus-within {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.lang-native {
  font-size: 1.125rem;
  font-weight: 600;
  min-width: 0;
  overflow-wrap: anywhere;
}
.lang-label {
  font-size: 0.85rem;
  color: var(--text-muted);
  min-width: 0;
  overflow-wrap: anywhere;
}

/* Role summary — definition list with strong type styling */
.role-summary,
.contact-summary {
  display: grid;
  gap: var(--sp-2);
  padding: var(--sp-3);
  background: var(--surface-elev);
  border-radius: 8px;
  margin: 0 0 var(--sp-4);
}
.role-summary > div,
.contact-summary > div {
  display: grid;
  grid-template-columns: 9rem 1fr;
  gap: var(--sp-2);
}
.role-summary dt,
.contact-summary dt {
  font-weight: 600;
  color: var(--text-muted);
  font-size: 0.875rem;
}
.role-summary dd,
.contact-summary dd {
  margin: 0;
  min-width: 0;
  overflow-wrap: anywhere;
}
/* Mirror .detail-list: stack to a single column on narrow screens so the
   9rem label track never squeezes a long email/value into an unreadable
   sliver. */
@media (max-width: 559px) {
  .role-summary > div,
  .contact-summary > div { grid-template-columns: 1fr; gap: var(--sp-1); }
}

/* Channel verification badges */
.badge-ok,
.badge-warn {
  display: inline-block;
  font-size: 0.75rem;
  padding: 2px 8px;
  border-radius: 999px;
  margin-inline-start: var(--sp-1);
}
.badge-ok { background: var(--ok-bg, #d1fae5); color: var(--ok-text, #065f46); }
.badge-warn { background: var(--warn-bg, #fef3c7); color: var(--warn-text, #92400e); }

/* Quiet-hours pair */
.quiet-hours-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-3);
}
.quiet-hours-grid label {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

/* Prominent checkbox — for the critical-bypass option */
.checkbox-prominent {
  display: flex;
  gap: var(--sp-2);
  padding: var(--sp-3);
  border: 1.5px solid var(--border);
  border-radius: 8px;
  margin: var(--sp-4) 0;
  background: var(--surface-elev);
}
.checkbox-prominent input[type="checkbox"] {
  margin-top: 4px;
}

/* Vulnerability category grid */
.vuln-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: var(--sp-2);
  border: 0;
  padding: 0;
  margin: 0 0 var(--sp-4);
}
.vuln-grid legend {
  margin-block-end: var(--sp-2);
  font-weight: 600;
}

/* Split-action footer (declare + skip) */
.actions-split {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-2);
}

/* Visually-hidden text — screen-reader-only labels */
.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;
}

/* RTL layout — Arabic / Urdu / Hebrew. The wizard is symmetric so
 * flipping direction works without per-component overrides. */
body.page-onboarding[dir="rtl"] .onboarding-progress .step,
body.page-onboarding[dir="rtl"] .role-summary,
body.page-onboarding[dir="rtl"] .contact-summary {
  text-align: right;
}

/* §7.4 hazards panel — read-only display on the issue-detail page.
 * Each tile's left border and badge colour signal urgency at a glance:
 * breached/overdue draws on --danger; imminent / soon use a warmer
 * token derived from --danger; paused uses --text-muted; ok uses
 * --success. Same monochrome palette as the rest of the app — no
 * new theme tokens. */
.hazard-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}
.hazard-tile {
  border: 1px solid var(--border);
  border-left: 4px solid var(--text-muted);
  border-radius: var(--radius);
  padding: var(--sp-3);
  background: var(--surface);
}
.hazard-tile.hazard-state-breached,
.hazard-tile.hazard-state-closed-breached {
  border-left-color: var(--danger);
}
.hazard-tile.hazard-state-paused-no-access,
.hazard-tile.hazard-state-paused-refused-access {
  border-left-color: var(--text-muted);
  background: color-mix(in srgb, var(--text-muted) 4%, var(--surface));
}
.hazard-tile.hazard-state-resolved,
.hazard-tile.hazard-state-closed-resolved {
  border-left-color: var(--success);
}

.hazard-tile-head {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  align-items: center;
  margin-bottom: var(--sp-2);
}
.hazard-ref {
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 0.85rem;
  color: var(--text-muted);
}
.hazard-category {
  margin: 0;
  font-size: 1rem;
  font-weight: 600;
  flex: 1 1 auto;
}
.hazard-severity-badge,
.hazard-state-pill {
  display: inline-block;
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 600;
  white-space: nowrap;
}
.hazard-severity-badge.severity-cat_1 {
  background: color-mix(in srgb, var(--danger) 18%, transparent);
  color: var(--danger);
}
.hazard-severity-badge.severity-cat_2 {
  background: color-mix(in srgb, var(--primary) 18%, transparent);
  color: var(--primary);
}
.hazard-state-pill {
  background: color-mix(in srgb, var(--text-muted) 14%, transparent);
  color: var(--text-muted);
}
.hazard-state-pill.state-breached,
.hazard-state-pill.state-closed-breached {
  background: color-mix(in srgb, var(--danger) 18%, transparent);
  color: var(--danger);
}
.hazard-state-pill.state-resolved,
.hazard-state-pill.state-closed-resolved {
  background: color-mix(in srgb, var(--success) 18%, transparent);
  color: var(--success);
}

.hazard-flag {
  margin: var(--sp-2) 0 0;
  padding: var(--sp-2);
  border-radius: 8px;
  font-size: 0.9rem;
  background: color-mix(in srgb, var(--text-muted) 8%, transparent);
}
.hazard-flag-emergency {
  background: color-mix(in srgb, var(--danger) 12%, transparent);
  color: var(--danger);
}
.hazard-flag-vulnerable {
  background: color-mix(in srgb, var(--primary) 10%, transparent);
}
.hazard-flag-paused {
  background: color-mix(in srgb, var(--text-muted) 12%, transparent);
}
.hazard-flag-breached {
  background: color-mix(in srgb, var(--danger) 14%, transparent);
  color: var(--danger);
  font-weight: 500;
}
/* Reasonable-period nations (Wales/Scotland/NI) past their target — caution
   amber, NEVER breach-red (there is no statutory hard deadline to breach). */
.hazard-flag-advisory {
  background: color-mix(in srgb, var(--warning) 14%, transparent);
  color: var(--warning);
  font-weight: 500;
}
/* Unknown regime past target — muted; never asserts a statutory breach. */
.hazard-flag-unresolved {
  background: color-mix(in srgb, var(--text-muted) 12%, transparent);
  color: var(--text-muted);
  font-weight: 500;
}

.hazard-facts {
  margin: var(--sp-3) 0 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--sp-3);
}
.hazard-facts > div { margin: 0; min-width: 0; }
.hazard-facts dt {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  margin-bottom: 0.15rem;
}
.hazard-facts dd { margin: 0; font-size: 0.95rem; overflow-wrap: anywhere; }

.hazard-countdown {
  display: inline-block;
  margin-left: var(--sp-2);
  padding: 0.05rem 0.45rem;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 600;
}
.hazard-countdown.urgency-ok       { background: color-mix(in srgb, var(--success) 14%, transparent); color: var(--success); }
.hazard-countdown.urgency-soon     { background: color-mix(in srgb, var(--primary) 14%, transparent); color: var(--primary); }
.hazard-countdown.urgency-imminent { background: color-mix(in srgb, var(--danger)  14%, transparent); color: var(--danger); font-weight: 700; }
.hazard-countdown.urgency-overdue  { background: color-mix(in srgb, var(--danger)  22%, transparent); color: var(--danger); font-weight: 700; }
.hazard-countdown.urgency-breached { background: var(--danger); color: var(--primary-fg); }
.hazard-countdown.urgency-paused   { background: color-mix(in srgb, var(--text-muted) 16%, transparent); color: var(--text-muted); }
.hazard-countdown.urgency-resolved { background: color-mix(in srgb, var(--success) 14%, transparent); color: var(--success); }

/* Hazards list surface (/dashboard/hazards) — reuses .panel/.filter-pill/.empty-state. */
.hazard-row { border-top: 1px solid var(--border); }
.hazard-list > .hazard-row:first-child { border-top: none; }
.hazard-row-link {
  display: grid;
  grid-template-columns: auto 1fr auto auto auto;
  gap: var(--sp-3);
  align-items: center;
  padding: var(--sp-3) var(--sp-2);
  min-height: var(--touch);
  text-decoration: none;
  color: var(--text);
  transition: background .15s;
}
.hazard-row-link:hover { background: var(--bg); }
.hazard-cat { font-weight: 600; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hazard-state { color: var(--text-muted); font-size: var(--t-small); }
.hazard-deadline { color: var(--text-muted); font-size: var(--t-small); white-space: nowrap; font-variant-numeric: tabular-nums; }
/* Used both as a short severity chip (Cat 1 / Breached) and to label longer
   compliance sentences. Short labels never wrap (they fit their auto track);
   long ones must wrap rather than overflow the viewport on narrow screens. */
.sev-badge { font-size: .72rem; font-weight: 700; padding: 2px 8px; border-radius: 6px; overflow-wrap: anywhere; }
.sev-breach { background: color-mix(in srgb, var(--danger) 14%, transparent); color: var(--danger); }
.sev-caution { background: color-mix(in srgb, var(--warning) 16%, transparent); color: var(--warning); }
.sev-neutral { background: var(--bg); color: var(--text-muted); }
.empty-sub { color: var(--text-muted); }
@media (max-width: 640px) {
  .hazard-row-link { grid-template-columns: auto 1fr auto; }
  .hazard-state { display: none; }
}

/* Jurisdiction-aware hazard deadline rendering (§7.5) — reasonable-period
   nations (Wales/Scotland/NI) never render breach-red; unresolved is flagged. */
.urgency-advisory { color: var(--warning); }
.urgency-unresolved { color: var(--text-muted); }
.hazard-regime { display: block; font-size: var(--t-small); color: var(--text-muted); margin-top: var(--sp-1); }
.hazard-regime.urgency-unresolved { color: var(--warning); font-weight: 600; }

/* ---------- Corporate / BTR exposure surface (§ Segment C) ---------------- */
/* Reuses --surface / --border / --text tokens; no accent rails, no gradient
   washes, no coloured status chips. Numbers are tabular (the "instrument"
   read). Time-signal colour is reserved for genuinely time-critical data
   (open-hazard counts), never applied to a reasonable-period regime. */

.exposure-registered {
  margin: 0 0 var(--sp-4);
  color: var(--text-muted);
  font-size: var(--t-small);
  line-height: 1.5;
}
.exposure-registered strong { color: var(--text); font-weight: 600; }
.exposure-unresolved-note { color: var(--warning); }

.exposure-split { list-style: none; margin: 0; padding: 0; }
.exposure-bucket {
  display: flex; align-items: center; gap: var(--sp-4);
  padding: var(--sp-4) 0;
  border-block-start: 1px solid var(--border);
}
.exposure-bucket:first-child { border-block-start: none; }
.exposure-bucket-label { display: flex; flex-direction: column; gap: 2px; }
.exposure-bucket-title { font-weight: 600; }
.exposure-bucket-detail { font-size: var(--t-small); color: var(--text-muted); }
.exposure-bucket-count {
  margin-inline-start: auto;
  font-size: 1.5rem; font-weight: 700; line-height: 1;
  font-variant-numeric: tabular-nums;
}
/* The unresolved bucket is the one that demands action — flag it, but never
   colour a reasonable-period regime as if it were a hard deadline. */
.exposure-bucket[data-tone="unresolved"] .exposure-bucket-count { color: var(--warning); }

/* Generic data table (canonical definition — this is the ONLY .data-table /
   .table-scroll ruleset; do not re-declare below). Horizontal scroll on narrow
   viewports so the page body never scrolls sideways. Long-text columns (names,
   citations, locations) wrap; numeric / date / reference columns stay on one
   line via .num / .nowrap / .mono / .tnum. text-align:start (not left) keeps it
   correct under RTL. */
.table-scroll { overflow-x: auto; margin-block: var(--sp-4); }
.data-table {
  width: 100%; border-collapse: collapse;
  font-size: 0.9375rem;
}
.data-table th, .data-table td {
  text-align: start; padding: var(--sp-3) var(--sp-4);
  border-block-end: 1px solid var(--border);
  overflow-wrap: anywhere;
}
.data-table thead th {
  font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text-muted); font-weight: 600;
}
.data-table td.num, .data-table th.num { text-align: end; white-space: nowrap; }
.data-table td.nowrap, .data-table th.nowrap { white-space: nowrap; }
.data-table .mono { font-variant-numeric: tabular-nums; white-space: nowrap; }
.data-table .tnum { white-space: nowrap; }
.data-table tbody tr:last-child td { border-block-end: none; }

/* ---------- §7.4 Instrument hero — live statutory timer -------------------
   The landlord dashboard's flagship element. Petrol-blue instrument panel;
   tabular-mono countdown; functional time-signal colour (never decorative).
   No AI signatures: no pill chips, no pulsing dots, no gradient wash. */
.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

.instrument-hero {
  margin-block-end: var(--sp-6);
}
.instrument-hero-live,
.instrument-hero-clear {
  display: block;
  background: var(--surface);
  border: 1px solid var(--border);
  border-inline-start: 4px solid var(--border);
  border-radius: var(--radius);
  padding: var(--sp-6);
  box-shadow: var(--shadow-card);
}
.instrument-hero-live {
  color: inherit;
  text-decoration: none;
}
.instrument-hero-live:hover {
  border-color: var(--primary);
  border-inline-start-color: var(--primary);
}
.instrument-hero-live:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
}
.hero-line {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--sp-3); flex-wrap: wrap;
}
.hero-eyebrow {
  font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--text-muted); font-weight: 600;
}
.hero-ref { font-family: var(--font-mono); font-size: 0.8125rem; color: var(--text-muted); }
.hero-title {
  font-size: var(--t-h2); font-weight: 700; letter-spacing: -0.01em;
  margin: var(--sp-2) 0 var(--sp-4);
}
.hero-clock {
  display: flex; align-items: baseline; gap: var(--sp-4); flex-wrap: wrap;
}
.hero-countdown {
  font-size: clamp(1.75rem, 1.3rem + 2vw, 2.75rem);
  font-weight: 700; line-height: 1; letter-spacing: -0.02em;
}
.hero-deadline-abs { font-size: var(--t-small); color: var(--text-muted); }
.hero-regime { font-size: var(--t-small); color: var(--text-muted); margin: var(--sp-3) 0 0; }
.hero-regime-unresolved { color: var(--warning); font-weight: 600; }
.hero-facts {
  display: flex; gap: var(--sp-6); flex-wrap: wrap;
  margin: var(--sp-4) 0 0; padding-block-start: var(--sp-4);
  border-block-start: 1px solid var(--border);
}
.hero-facts dt {
  font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text-muted); margin: 0 0 var(--sp-1);
}
.hero-facts dd { margin: 0; font-weight: 600; }

/* Time-signal colour on the countdown + the hero's start-border. England's
   statutory hard deadline is the only regime that reddens on breach; the
   reasonable-period nations use the caution tone; unresolved is warned. */
.instrument-hero-live.urgency-ok        { border-inline-start-color: var(--success); }
.instrument-hero-live.urgency-ok        .hero-countdown { color: var(--success); }
.instrument-hero-live.urgency-soon      { border-inline-start-color: var(--primary); }
.instrument-hero-live.urgency-soon      .hero-countdown { color: var(--primary); }
.instrument-hero-live.urgency-imminent  { border-inline-start-color: var(--warning); }
.instrument-hero-live.urgency-imminent  .hero-countdown { color: var(--warning); }
.instrument-hero-live.urgency-overdue   { border-inline-start-color: var(--danger); }
.instrument-hero-live.urgency-overdue   .hero-countdown { color: var(--danger); }
.instrument-hero-live.urgency-breached  { border-inline-start-color: var(--danger); }
.instrument-hero-live.urgency-breached  .hero-countdown { color: var(--danger); }
.instrument-hero-live.urgency-advisory  { border-inline-start-color: var(--warning); }
.instrument-hero-live.urgency-advisory  .hero-countdown { color: var(--warning); }
.instrument-hero-live.urgency-paused    { border-inline-start-color: var(--text-muted); }
.instrument-hero-live.urgency-paused    .hero-countdown { color: var(--text-muted); }
.instrument-hero-live.urgency-unresolved { border-inline-start-color: var(--warning); }
.instrument-hero-live.urgency-unresolved .hero-countdown { color: var(--text-muted); }

.hero-clear-headline { font-size: var(--t-h2); font-weight: 700; margin: var(--sp-1) 0 var(--sp-2); }
.hero-clear-body { color: var(--text-muted); margin: 0 0 var(--sp-3); max-width: 46ch; }
.hero-clear-link { font-weight: 600; }

/* ---------- §5.25 availability publish composer + withdraw ---------------- */
.composer > summary.composer-summary {
  list-style: none; cursor: pointer; user-select: none;
  font-weight: 600; color: var(--text);
  padding: var(--sp-1) 0;
}
.composer > summary.composer-summary::-webkit-details-marker { display: none; }
.composer > summary.composer-summary::marker { content: ""; }
.composer > summary.composer-summary::before {
  content: "+"; display: inline-block; width: 1.2em;
  font-family: var(--font-mono); color: var(--primary); font-weight: 700;
}
.composer[open] > summary.composer-summary::before { content: "\2212"; } /* minus */

.checkbox-row {
  display: flex; align-items: center; gap: var(--sp-2);
  min-height: var(--touch); font-weight: 400;
}
.checkbox-row input { width: auto; min-height: 0; }
fieldset.field { border: 1px solid var(--border); border-radius: 10px; padding: var(--sp-3) var(--sp-4); }
fieldset.field legend { font-size: 0.8125rem; font-weight: 600; padding: 0 var(--sp-2); }

.withdraw-form { margin-block-start: var(--sp-2); }
.btn-danger {
  color: var(--danger);
  border-color: color-mix(in srgb, var(--danger) 35%, var(--border));
}
.btn-danger:hover {
  background: color-mix(in srgb, var(--danger) 8%, transparent);
  border-color: var(--danger);
}

/* ---------- §3.7 multi-property bulk compliance export ------------------- */
.bulk-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-4); flex-wrap: wrap;
  margin-block-end: var(--sp-4); padding-block-end: var(--sp-3);
  border-block-end: 1px solid var(--border);
}
.bulk-hint { color: var(--text-muted); font-size: var(--t-small); margin: 0; }
.bulk-bar button { width: auto; }
.bulk-row { display: flex; align-items: stretch; gap: var(--sp-2); }
.bulk-check {
  display: flex; align-items: center; justify-content: center;
  min-width: var(--touch); padding: 0 var(--sp-2);
}
.bulk-check input { width: auto; min-height: 0; }
.bulk-row .issue-row { flex: 1; }

/* (Preview summary table now uses the canonical .data-table / .table-scroll
   ruleset defined above — the duplicate declaration was removed per §6.4.) */

/* "registered" marker — plain small-caps text, deliberately NOT a filled chip. */
.registered-tag {
  margin-inline-start: var(--sp-2);
  font-size: 0.625rem; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text-muted);
}

/* Portfolio schemes list — real <a> row-links (keyboard-native), styled as a
   table via grid so each row can be a single focusable element. */
.portfolio-list { display: flex; flex-direction: column; }
.portfolio-row {
  display: grid;
  grid-template-columns: minmax(0, 2.4fr) minmax(0, 1.4fr) minmax(0, 1.6fr) auto;
  gap: var(--sp-4); align-items: center;
  padding: var(--sp-3) var(--sp-4);
  border-block-end: 1px solid var(--border);
  color: var(--text); text-decoration: none;
}
.portfolio-row:last-child { border-block-end: none; }
.portfolio-head {
  font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text-muted); font-weight: 600;
}
a.portfolio-row:hover {
  background: color-mix(in srgb, var(--primary) 6%, transparent);
}
a.portfolio-row:focus-visible {
  outline: 2px solid var(--focus); outline-offset: -2px;
}
.portfolio-address { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.portfolio-address-line {
  font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.portfolio-type { font-size: var(--t-small); color: var(--text-muted); }
.portfolio-building, .portfolio-nation {
  color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.portfolio-hazards {
  text-align: end; font-size: 1.125rem; font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.portfolio-hazards[data-tone="live"] { color: var(--warning); }
.portfolio-hazards[data-tone="clear"] { color: var(--text-muted); }

@media (max-width: 720px) {
  .portfolio-row { grid-template-columns: minmax(0, 1fr) auto; }
  .portfolio-building, .portfolio-head span:nth-child(2), .portfolio-head span:nth-child(3) { display: none; }
  .portfolio-nation { display: none; }
}

/* ==========================================================================
   Compliance-Instrument strip (W4) — namespaced .lnt-* progressive-
   enhancement components. All colour comes from the existing :root tokens
   (no new hardcoded values); every visual is layered over server-rendered
   real data by /static/lintel.js and degrades gracefully without it.
   Kept additive at the end of the file so parallel dashboard work merges
   cleanly.
   ========================================================================== */

.lnt-strip {
  display: grid;
  gap: var(--sp-4);
  grid-template-columns: 1fr;
  margin-block-end: var(--sp-6);
}
@media (min-width: 48rem) {
  /* Gauge takes intrinsic width; the trend fills the rest. */
  .lnt-strip { grid-template-columns: minmax(15rem, 22rem) 1fr; }
}

.lnt-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  padding: var(--sp-5);
  display: flex;
  gap: var(--sp-4);
  min-width: 0;
}

/* Whole-card click affordance (the real <a> inside stays the keyboard
   target — see lintel.js clickable). Only shows the pointer once JS has
   confirmed a destination exists. */
.lnt-clickable-ready { cursor: pointer; }
.lnt-card { transition: box-shadow .18s ease, transform .18s ease; }
.lnt-clickable-ready:hover {
  box-shadow: 0 8px 24px -6px color-mix(in srgb, var(--primary) 22%, transparent),
              0 1px 2px rgba(0,0,0,.04);
  transform: translateY(-1px);
}
/* Focus ring lands on the inner link; mirror it onto the card so the
   whole affordance reads as focused for sighted keyboard users. */
.lnt-card:focus-within {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

/* ---- Gauge (ring) ------------------------------------------------------ */
.lnt-gauge { align-items: center; }
.lnt-gauge-ring {
  position: relative;
  inline-size: 6.5rem;
  block-size: 6.5rem;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
}
.lnt-ring-svg {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
}
.lnt-gauge-value {
  position: relative;
  font-size: 1.75rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}
.lnt-gauge-body { display: flex; flex-direction: column; justify-content: center; gap: var(--sp-1); min-width: 0; }
.lnt-gauge-label {
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  margin: 0;
}
.lnt-gauge-headline { font-size: 1.0625rem; font-weight: 650; color: var(--text); margin: 0; }
.lnt-gauge-sub { font-size: var(--t-small); color: var(--text-muted); margin: 0; }
.lnt-gauge-link {
  font-size: var(--t-small);
  color: var(--primary);
  text-decoration: none;
  font-weight: 600;
  margin-top: var(--sp-1);
  align-self: flex-start;
}
.lnt-gauge-link:hover { text-decoration: underline; }

/* ---- Trend (sparkline) ------------------------------------------------- */
.lnt-trend { flex-direction: column; gap: var(--sp-3); }
.lnt-trend-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-3);
}
.lnt-trend-label {
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  margin: 0;
}
.lnt-trend-value {
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}
.lnt-trend-spark {
  display: block;
  inline-size: 100%;
  block-size: 3rem;
}
.lnt-sparkline-svg {
  display: block;
  inline-size: 100%;
  block-size: 100%;
}
.lnt-trend-sub { font-size: var(--t-small); color: var(--text-muted); margin: 0; }

/* The strip participates in the same staggered entrance as the stat grid
   and honours reduced motion (the global reduce rule already zeroes
   animation-duration, but the entrance is opt-in here for parity). */
.app-content > .lnt-strip { animation: panelFadeUp .35s ease-out both; animation-delay: 40ms; }
@media (prefers-reduced-motion: reduce) {
  .app-content > .lnt-strip { animation: none !important; }
  .lnt-clickable-ready:hover { transform: none; }
}

/* ---------------------------------------------------------------------------
   Compliance register (ADR-0003 F1 Slice-7). RAG badges reuse the .sev-badge
   base; .sev-ok is the green (compliant / in-date / meets-minimum) variant.
   The rest is jurisdiction-line framing + the per-type / BS / MEES lists.
   Monochrome-with-status palette, consistent with the rest of the app; theme
   tokens (--success/--warning/--danger/--text-muted) carry light + dark.
--------------------------------------------------------------------------- */
.sev-ok { background: color-mix(in srgb, var(--success) 16%, transparent); color: var(--success); }

.notice.notice-ok {
  background: color-mix(in srgb, var(--success) 10%, var(--surface));
  border-color: color-mix(in srgb, var(--success) 35%, var(--border));
}

.filter-bar-label {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--text-muted);
  align-self: center;
  margin-inline-end: var(--sp-2);
}

.compliance-nation {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  margin: var(--sp-2) 0 0;
  font-size: 0.9375rem;
}
.compliance-nation-badge {
  font-weight: 700;
  padding: 2px 10px;
  border-radius: 6px;
  background: color-mix(in srgb, var(--primary) 12%, transparent);
  color: var(--primary);
}
.compliance-nation-sep { color: var(--text-muted); }
.compliance-nation-regime { color: var(--text-muted); }
.compliance-nation-unresolved {
  color: var(--warning);
  font-weight: 500;
}

.compliance-list { list-style: none; margin: 0; padding: 0; }
.compliance-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-3);
  padding: var(--sp-3) 0;
  border-block-end: 1px solid var(--border);
}
.compliance-row:last-child { border-block-end: none; }
.compliance-row-col { flex-direction: column; align-items: flex-start; }
.compliance-row-line {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-3);
  width: 100%;
}
.compliance-row-name { font-weight: 600; }
.compliance-row-code {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  color: var(--text-muted);
}
.compliance-row-meta { color: var(--text-muted); font-size: 0.875rem; }
.compliance-row-citation { flex-basis: 100%; color: var(--text-muted); font-size: 0.8125rem; margin: 0; }
.compliance-row-upcoming { margin: var(--sp-1) 0 0; font-size: 0.875rem; color: var(--text-muted); }

.stacked-form { margin-block-start: var(--sp-3); }
.form-actions { margin-block-start: var(--sp-4); display: flex; gap: var(--sp-3); }

.inline-form { display: inline-flex; gap: var(--sp-2); align-items: center; flex-wrap: wrap; }
.inline-input {
  padding: 4px 8px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text);
  font-size: 0.875rem;
  max-width: 16rem;
}
.btn-sm { padding: 4px 10px; font-size: 0.8125rem; }

/* ===========================================================================
 * Page-level alert banners  (.banner / .banner-error / .banner-success)
 * Used by compliance portfolio (EPC sync), TSM, consumer-standards, EPC/UPRN
 * review, contractors. Shares the visual language of .notice but is a full-
 * width in-flow banner rather than a form-scoped notice. Honest §10.9 error /
 * success states depend on these being legible.
 * ========================================================================= */
.banner {
  margin-block: var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  border-radius: 10px;
  border: 1px solid var(--border);
  background: color-mix(in srgb, var(--primary) 8%, var(--surface));
  color: var(--text);
}
.banner p { margin: 0; }
.banner p + p { margin-block-start: var(--sp-2); }
.banner-error {
  background: color-mix(in srgb, var(--danger) 10%, var(--surface));
  border-color: color-mix(in srgb, var(--danger) 35%, var(--border));
}
.banner-success {
  background: color-mix(in srgb, var(--success) 10%, var(--surface));
  border-color: color-mix(in srgb, var(--success) 35%, var(--border));
}
/* EPC/UPRN-sync degraded banner (compliance portfolio, review pages) maps onto
 * the warning palette so a "banner banner-warning" render is never unstyled. */
.banner-warning {
  background: color-mix(in srgb, var(--warning) 12%, var(--surface));
  border-color: color-mix(in srgb, var(--warning) 35%, var(--border));
}

/* Amber "partial / attention" badge — the sev-badge family was missing this
 * one variant (consumer-standards "partial", TSM caveats). */
.sev-warn { background: color-mix(in srgb, var(--warning) 16%, transparent); color: var(--warning); }

/* Horizontal wrap-row of status badges (readiness rollups). */
.summary-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  margin-block: var(--sp-3);
}

/* ---------------------------------------------------------------------------
 * Consumer-Standards readiness — per-outcome evidence rows.
 * A row that has an evidence target (a.outcome-row.outcome-link) is fully
 * clickable with a hover affordance, matching the .issue-row pattern; a row
 * that is an honest gap (no target) stays a static <li> (§10.9 — never a dead
 * link, never a link to a 404).
 * ------------------------------------------------------------------------- */
.outcome-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-3); }
.outcome-row {
  display: block;
  padding: var(--sp-4);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
}
a.outcome-row {
  text-decoration: none;
  color: inherit;
  transition: border-color .12s ease, transform .08s ease, box-shadow .12s ease;
}
a.outcome-row:hover {
  border-color: color-mix(in srgb, var(--primary) 35%, var(--border));
  transform: translateY(-1px);
  box-shadow: var(--shadow-card);
}
a.outcome-row:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.outcome-head { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
.outcome-name { font-weight: 600; }
.outcome-desc { color: var(--text-muted); margin: var(--sp-2) 0 0; }
.outcome-detail { margin: var(--sp-2) 0 0; }
.outcome-link {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  margin-block-start: var(--sp-2);
  font-weight: 600;
  color: var(--primary);
}
a.outcome-row .outcome-link { text-decoration: underline; text-underline-offset: 2px; }
a.outcome-row:hover .outcome-link { color: var(--primary-hover); }

/* ---------------------------------------------------------------------------
 * TSM survey card + definition list + hint list.
 * ------------------------------------------------------------------------- */
.panel-card {
  padding: var(--sp-5);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow-card);
  margin-block: var(--sp-4);
}
.panel-card h3 { margin: 0 0 var(--sp-3); }
.detail-list {
  display: grid;
  grid-template-columns: minmax(9rem, auto) 1fr;
  gap: var(--sp-2) var(--sp-4);
  margin: 0;
}
.detail-list dt { color: var(--text-muted); font-weight: 500; min-width: 0; overflow-wrap: anywhere; }
.detail-list dd { margin: 0; font-weight: 500; min-width: 0; overflow-wrap: anywhere; }
@media (max-width: 559px) {
  .detail-list { grid-template-columns: 1fr; gap: var(--sp-1); }
  .detail-list dd { margin-block-end: var(--sp-2); }
}
.hint-list { margin: var(--sp-2) 0 0; padding-inline-start: var(--sp-5); color: var(--text-muted); }
.hint-list li + li { margin-block-start: var(--sp-1); }

/* ===========================================================================
 * Cookie consent banner  (§6.10 / PECR)
 * Pinned bottom-right card (bottom bar on mobile). z-index sits above page
 * content + topbar (z 5) but below the mobile slide-out nav (z 50) and its
 * backdrop (z 40) so an open sidebar dims it and the burger is never blocked.
 * On desktop it clears the left sidebar by pinning to the right edge.
 * ========================================================================= */
.cookie-banner {
  position: fixed;
  z-index: 30;
  inset-block-end: var(--sp-4);
  inset-inline-end: var(--sp-4);
  inset-inline-start: auto;
  max-width: min(30rem, calc(100vw - 2 * var(--sp-4)));
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  padding: var(--sp-4);
}
.cookie-banner-body {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-4);
  flex-wrap: wrap;
}
.cookie-banner-text {
  margin: 0;
  flex: 1 1 16rem;
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--text-muted);
}
.cookie-banner-link { color: var(--primary); font-weight: 600; }
.cookie-banner-button {
  flex: 0 0 auto;
  align-self: center;
  padding: var(--sp-2) var(--sp-5);
  min-height: var(--touch);
}
@media (max-width: 559px) {
  .cookie-banner {
    inset-inline: var(--sp-3);
    inset-block-end: var(--sp-3);
    max-width: none;
  }
  .cookie-banner-button { width: 100%; }
}
/* ========================================================================= *
 * Secondary pages — Compliance Instrument component library
 *
 * The authenticated settings surfaces (My data, Passkeys, Billing, Team,
 * Staff access) and the public reading surfaces (Trust portal, Changelog)
 * were authored with semantic class names but never got their component
 * CSS — they inherited the shell (panel / breadcrumb / empty-state) but
 * their lists, badges, callouts and tables fell back to browser defaults.
 * This block brings them onto the same tokens, pills and card treatments
 * the primary pages already use. Nothing new is invented — every value is
 * an existing design token.
 * ========================================================================= */

/* ---------- Reading utilities ------------------------------------------- */

.body-copy {
  color: var(--text-muted);
  max-width: 68ch;
  margin: 0 0 var(--sp-3);
}
.body-copy:last-child { margin-bottom: 0; }

/* Second and subsequent body lines inside a .notice get vertical rhythm
   (the base .notice .body sets margin:0 so a lone paragraph hugs). */
.notice .body + .body { margin-block-start: var(--sp-2); }

/* Inline links in reading copy take the brand primary, not UA blue.
   Excludes .btn: a button link inside reading copy keeps its own
   --primary-fg label colour, otherwise --primary text on a --primary
   navy button renders an invisible label (the empty-state button bug). */
.body-copy a:not(.btn), .empty-state a:not(.btn), .callout a:not(.btn), .lede a:not(.btn) {
  color: var(--primary); text-decoration: underline;
}
.body-copy a:not(.btn):hover, .empty-state a:not(.btn):hover, .callout a:not(.btn):hover, .lede a:not(.btn):hover { text-decoration: none; }

/* Standalone muted / inline pill utilities used in the staff-access table. */
.muted { color: var(--text-muted); }
.pill {
  display: inline-flex; align-items: center;
  padding: 2px var(--sp-2);
  border-radius: 999px;
  font-size: 0.6875rem; font-weight: 600;
  letter-spacing: 0.02em;
  background: color-mix(in srgb, var(--text) 8%, transparent);
  color: var(--text);
  white-space: nowrap;
}
.pill.warn {
  background: color-mix(in srgb, var(--warning) 16%, transparent);
  color: var(--warning);
}

/* Horizontal-scroll table wrapper (alias of .table-scroll for the
   staff-access page) — the page body never scrolls sideways. */
.table-wrap { overflow-x: auto; margin-block: var(--sp-2); }

/* ---------- Badge system ------------------------------------------------ *
 * Pill badges shared by the changelog, passkey list and SAR history. Base
 * pill + tonal variants derived from the semantic colour tokens. */
.badge {
  display: inline-flex; align-items: center;
  padding: 2px var(--sp-2);
  border-radius: 999px;
  font-size: 0.6875rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.05em;
  line-height: 1.4;
  background: color-mix(in srgb, var(--text) 8%, transparent);
  color: var(--text-muted);
  white-space: nowrap;
}
.badge-success { background: color-mix(in srgb, var(--success) 16%, transparent); color: var(--success); }
.badge-info    { background: color-mix(in srgb, var(--primary) 16%, transparent); color: var(--primary); }
.badge-warning { background: color-mix(in srgb, var(--warning) 18%, transparent); color: var(--warning); }
.badge-error   { background: color-mix(in srgb, var(--danger) 16%, transparent);  color: var(--danger); }
.badge-muted   { background: color-mix(in srgb, var(--text) 8%, transparent);     color: var(--text-muted); }

/* ---------- Form primitives (settings surfaces) ------------------------- */

.form-row { margin-block-end: var(--sp-4); }
.form-row:last-child { margin-block-end: 0; }
.form-label { display: block; font-weight: 600; margin-block-end: var(--sp-2); }
.form-hint  { display: block; font-size: var(--t-small); color: var(--text-muted); margin-block-start: var(--sp-1); }
.error-hint { display: block; font-size: var(--t-small); color: var(--danger); margin-block-start: var(--sp-1); }
.error-hint:empty { display: none; }

/* Inline status banners for HTMX / round-trip feedback. */
.form-row.status-success,
.form-row.status-error {
  padding: var(--sp-3) var(--sp-4);
  border-radius: 10px;
  border: 1px solid var(--border);
  margin-block: var(--sp-4);
}
.form-row.status-success {
  background: color-mix(in srgb, var(--success) 10%, var(--surface));
  border-color: color-mix(in srgb, var(--success) 35%, var(--border));
}
.form-row.status-error {
  background: color-mix(in srgb, var(--danger) 10%, var(--surface));
  border-color: color-mix(in srgb, var(--danger) 35%, var(--border));
}
.form-row.status-success:empty,
.form-row.status-error:empty { display: none; }

/* Radio option rows (SAR access/erasure choice). Each is a full-width
   tap target with the control aligned to the top of the copy. */
.radio-row {
  display: flex; align-items: flex-start; gap: var(--sp-3);
  padding: var(--sp-4);
  border: 1.5px solid var(--border);
  border-radius: 10px;
  margin-block-end: var(--sp-3);
  cursor: pointer;
  transition: border-color .12s ease, background-color .12s ease;
}
.radio-row:last-child { margin-block-end: 0; }
.radio-row:hover { border-color: color-mix(in srgb, var(--primary) 30%, var(--border)); }
.radio-row:focus-within { border-color: var(--focus); box-shadow: 0 0 0 3px color-mix(in srgb, var(--focus) 20%, transparent); }
.radio-row:has(input:checked) { border-color: var(--primary); background: color-mix(in srgb, var(--primary) 5%, transparent); }
.radio-row input[type="radio"] { margin-top: 0.2rem; width: 1.1rem; height: 1.1rem; flex-shrink: 0; }
.radio-row > span { display: flex; flex-direction: column; gap: 2px; }
.radio-row strong { font-weight: 600; }
.radio-row .form-hint { margin-block-start: 0; }

/* ---------- Callout (legal / precedence notices) ------------------------ */

.callout {
  padding: var(--sp-4) var(--sp-5);
  border: 1px solid var(--border);
  border-inline-start: 3px solid var(--text-muted);
  border-radius: 10px;
  background: color-mix(in srgb, var(--text) 3%, var(--surface));
}
.callout > :last-child { margin-bottom: 0; }
.callout-warning {
  border-inline-start-color: var(--warning);
  background: color-mix(in srgb, var(--warning) 8%, var(--surface));
  border-color: color-mix(in srgb, var(--warning) 30%, var(--border));
}
.callout-title { margin: 0 0 var(--sp-2); font-size: 1rem; font-weight: 700; }
.precedence-list { margin: var(--sp-3) 0; padding-inline-start: var(--sp-5); display: grid; gap: var(--sp-2); }
.precedence-list li { padding-inline-start: var(--sp-1); }

/* ---------- Link / disabled buttons ------------------------------------- */

.btn-link {
  display: inline-flex; align-items: center; gap: var(--sp-1);
  width: auto; min-height: 0; padding: 0;
  background: transparent; color: var(--primary);
  font-weight: 600; text-decoration: none;
}
.btn-link:hover { background: transparent; text-decoration: underline; }
.btn-link:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: 4px; }
.btn-disabled {
  background: transparent;
  color: var(--text-muted);
  border: 1.5px solid var(--border);
  cursor: not-allowed;
}
.btn-disabled:hover { background: transparent; }

/* ---------- Settings link list ------------------------------------------ */

.settings-link-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-2); }
.settings-link-list li {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-2) var(--sp-3);
  padding: var(--sp-3) 0;
  border-block-end: 1px solid var(--border);
}
.settings-link-list li:last-child { border-block-end: none; }
.settings-link-list a { font-weight: 600; text-decoration: none; color: var(--primary); }
.settings-link-list a:hover { text-decoration: underline; }
.settings-link-meta { color: var(--text-muted); font-size: var(--t-small); }

/* ---------- Shared record lists (passkeys / SAR / payment / invites) ----- *
 * All four are "a surface card per record, main column + trailing actions".
 * Grouped so one treatment drives them; family-specific bits follow. */
.passkey-list,
.sar-list,
.payment-method-list,
.invite-list {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: var(--sp-3);
}
.passkey-row,
.sar-row,
.payment-method-row,
.invite-row {
  display: flex; flex-wrap: wrap; align-items: flex-start;
  justify-content: space-between; gap: var(--sp-3) var(--sp-4);
  padding: var(--sp-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
}
.passkey-row-main,
.sar-row-main { display: flex; flex-direction: column; gap: var(--sp-1); min-width: 0; flex: 1 1 16rem; }
.passkey-row-actions,
.sar-row-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }

.passkey-name,
.sar-title { margin: 0; font-size: 1rem; font-weight: 600; }
.passkey-meta,
.sar-meta {
  margin: 0; font-size: var(--t-small); color: var(--text-muted);
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-1) var(--sp-2);
}
.passkey-meta-sep,
.sar-meta-sep { color: var(--border); }
.passkey-badges,
.sar-badges { display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-2); margin-top: var(--sp-1); }

/* SAR download groups + pending note. */
.sar-download-group { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }
.sar-download-label { font-size: var(--t-small); color: var(--text-muted); font-weight: 600; }
.sar-pending-note { font-size: var(--t-small); color: var(--text-muted); max-width: 24ch; text-align: end; }
/* Compact secondary buttons inside record rows so they don't span full width. */
.passkey-row-actions .btn-secondary,
.sar-download-group .btn-secondary {
  width: auto; min-height: 2.25rem; padding: 0 var(--sp-4); font-size: var(--t-small);
}

/* ---------- Payment method rows (billing) ------------------------------- */

.payment-method-meta { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
.payment-method-status {
  display: inline-flex; align-items: center;
  padding: 2px var(--sp-2); border-radius: 999px;
  font-size: 0.6875rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.05em;
  background: color-mix(in srgb, var(--text) 8%, transparent); color: var(--text-muted);
}
.payment-method-status.status-active  { background: color-mix(in srgb, var(--success) 16%, transparent); color: var(--success); }
.payment-method-status.status-pending { background: color-mix(in srgb, var(--warning) 18%, transparent); color: var(--warning); }
.payment-method-status.status-failed  { background: color-mix(in srgb, var(--danger) 16%, transparent);  color: var(--danger); }
.payment-method-status.status-removed { background: color-mix(in srgb, var(--text) 8%, transparent);      color: var(--text-muted); }
.payment-method-brand { font-size: var(--t-small); color: var(--text-muted); font-weight: 600; }
.payment-method-title { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-2) var(--sp-3); margin-top: var(--sp-1); }
.payment-method-card { font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: 0.04em; }
.payment-method-pending { color: var(--text-muted); font-weight: 500; letter-spacing: normal; }
.payment-method-exp { font-size: var(--t-small); color: var(--text-muted); font-variant-numeric: tabular-nums; }
.payment-method-error { flex-basis: 100%; font-size: var(--t-small); color: var(--danger); }
.payment-method-tail { flex-basis: 100%; }
.payment-method-added { font-size: var(--t-small); color: var(--text-muted); }
.payment-method-row.payment-method-removed { opacity: 0.6; }

/* Stripe Elements mount point + the add-card form disclosure body. */
.stripe-card-element {
  padding: var(--sp-3) var(--sp-4);
  border: 1.5px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
  margin-block: var(--sp-3);
}
.card-form { margin-block-start: var(--sp-4); }
.composer-body { display: flex; flex-direction: column; gap: var(--sp-3); padding-top: var(--sp-3); }

/* ---------- Invite rows (team) ------------------------------------------ */

.invite-meta { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 14rem; }
.invite-email { font-weight: 600; overflow-wrap: anywhere; }
.invite-role { font-size: var(--t-small); color: var(--text-muted); }
.invite-tail { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-3); }
.invite-time { font-size: var(--t-small); color: var(--text-muted); font-variant-numeric: tabular-nums; }
.invite-issue-form { display: grid; gap: 0; }

/* ---------- Public reading surfaces: shell + changelog ------------------ */

.trust-shell {
  max-width: 54rem;
  margin: 0 auto;
  display: flex; flex-direction: column; gap: var(--sp-6);
}
.trust-shell > .hero,
.trust-shell > section { margin: 0; }

.hero { margin: 0 0 var(--sp-2); }
.lede { color: var(--text-muted); font-size: 1.0625rem; max-width: 62ch; margin: var(--sp-2) 0 0; }
.meta { font-size: var(--t-small); color: var(--text-muted); margin: var(--sp-1) 0 0; }

.changelog-list { display: flex; flex-direction: column; gap: var(--sp-4); }
.changelog-entry {
  padding: var(--sp-5);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
}
.changelog-entry-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-3); margin-block-end: var(--sp-2); }
.changelog-entry-date { margin-inline-start: auto; font-size: var(--t-small); color: var(--text-muted); font-variant-numeric: tabular-nums; }
.changelog-entry-title { margin: 0 0 var(--sp-2); font-size: 1.0625rem; font-weight: 600; letter-spacing: -0.01em; }
.changelog-entry-summary { margin: 0; color: var(--text-muted); max-width: 68ch; }
.changelog-entry-foot { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4); margin-block-start: var(--sp-3); }
.changelog-entry-foot .meta { margin: 0; }

/* ---------- Trust portal ------------------------------------------------ */

.trust-staleness {
  padding: var(--sp-4) var(--sp-5);
  border: 1px solid color-mix(in srgb, var(--warning) 35%, var(--border));
  border-inline-start: 3px solid var(--warning);
  border-radius: 10px;
  background: color-mix(in srgb, var(--warning) 8%, var(--surface));
}
.trust-staleness-ok { color: var(--text-muted); font-size: var(--t-small); margin: 0; }

.trust-commitments { display: grid; gap: var(--sp-2); padding-inline-start: var(--sp-5); }

.trust-table { width: 100%; border-collapse: collapse; font-size: 0.9375rem; }
.trust-table th, .trust-table td {
  text-align: left; padding: var(--sp-3) var(--sp-4);
  border-block-end: 1px solid var(--border); vertical-align: top;
}
.trust-table thead th {
  font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text-muted); font-weight: 600;
}
.trust-table tbody tr:last-child td { border-block-end: none; }
/* Certification status pill — tokens per internal/trust status enum. */
.trust-status {
  display: inline-flex; align-items: center;
  padding: 2px var(--sp-2); border-radius: 999px;
  font-size: 0.6875rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.05em;
  background: color-mix(in srgb, var(--text) 8%, transparent); color: var(--text-muted);
}
.trust-status-achieved { background: color-mix(in srgb, var(--success) 16%, transparent); color: var(--success); }
.trust-status-renewing { background: color-mix(in srgb, var(--success) 12%, transparent); color: var(--success); }
.trust-status-in_progress { background: color-mix(in srgb, var(--warning) 18%, transparent); color: var(--warning); }
.trust-status-planned { background: color-mix(in srgb, var(--text) 8%, transparent); color: var(--text-muted); }
.trust-data-cats { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--sp-1); }
.trust-data-cats li {
  font-size: 0.75rem; color: var(--text-muted);
  padding: 1px var(--sp-2); border: 1px solid var(--border); border-radius: 6px;
}
.trust-dpa-signed { color: var(--success); font-weight: 600; }
/* DPA status text can be a long unbroken phrase; let it wrap rather than
   push the sub-processor table past the viewport edge (narrow-width hscroll). */
.trust-dpa-pending { color: var(--warning); font-weight: 600; overflow-wrap: anywhere; word-break: break-word; }

/* The cosign recipe is a long shell command with an unbreakable URL regexp;
   wrap it (rather than overflow the page) so /trust has no horizontal scroll
   at 360/768. white-space:pre-wrap preserves the command's line structure. */
.trust-shell pre { white-space: pre-wrap; overflow-wrap: anywhere; word-break: break-word; }
.trust-shell pre code { overflow-wrap: anywhere; word-break: break-word; }

.trust-activity {
  padding: var(--sp-4) var(--sp-5);
  border: 1px solid var(--border);
  border-radius: 10px;
  background: color-mix(in srgb, var(--text) 2%, var(--surface));
  margin-block-end: var(--sp-3);
}
.trust-activity:last-child { margin-block-end: 0; }
.trust-activity h3 { margin: 0 0 var(--sp-1); font-size: 1rem; }
.trust-meta, .trust-rights {
  display: grid; gap: var(--sp-1) var(--sp-3); margin: var(--sp-2) 0 0;
  grid-template-columns: minmax(9rem, max-content) 1fr;
}
.trust-meta dt, .trust-rights dt { font-weight: 600; color: var(--text-muted); font-size: 0.875rem; min-width: 0; overflow-wrap: anywhere; }
.trust-meta dd, .trust-rights dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
.trust-hrp { display: grid; gap: var(--sp-3); list-style: none; margin: 0; padding: 0; }
.trust-hrp > li { padding-block-end: var(--sp-3); border-block-end: 1px solid var(--border); }
.trust-hrp > li:last-child { border-block-end: none; padding-block-end: 0; }
.trust-footer { color: var(--text-muted); font-size: var(--t-small); border-block-start: 1px solid var(--border); padding-block-start: var(--sp-4); }

@media (max-width: 559px) {
  .trust-meta, .trust-rights { grid-template-columns: 1fr; gap: 0; }
  .trust-meta dt, .trust-rights dt { margin-block-start: var(--sp-2); }
}

/* ---- FIX-C global error toast region ---------------------------------- */
/* Fixed bottom-right stack of curated HTMX error messages surfaced by
   lintel.js. Colours/tokens only — no hardcoded palette. Honours reduced
   motion (no slide-in animation when requested). */
.lnt-toast-region {
  position: fixed;
  inset-block-end: var(--sp-4);
  inset-inline-end: var(--sp-4);
  z-index: 1000;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  max-width: min(28rem, calc(100vw - 2 * var(--sp-4)));
  pointer-events: none; /* region is inert; individual toasts re-enable */
}
.lnt-toast {
  pointer-events: auto;
  position: relative;
  padding: var(--sp-3) calc(var(--sp-4) + var(--sp-4)) var(--sp-3) var(--sp-4);
  border-radius: 10px;
  border: 1px solid color-mix(in srgb, var(--danger) 35%, var(--border));
  background: color-mix(in srgb, var(--danger) 12%, var(--surface));
  color: var(--text);
  box-shadow: var(--shadow-card);
}
.lnt-toast-msg { margin: 0; font-size: 0.9375rem; }
.lnt-toast-ref {
  margin: var(--sp-1) 0 0;
  font-size: 0.75rem;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  word-break: break-all;
}
.lnt-toast-close {
  position: absolute;
  inset-block-start: var(--sp-2);
  inset-inline-end: var(--sp-2);
  width: 1.75rem;
  height: 1.75rem;
  padding: 0;
  line-height: 1;
  font-size: 1.25rem;
  background: transparent;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  border-radius: 6px;
}
.lnt-toast-close:hover { color: var(--text); }
.lnt-toast-close:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }

/* §12.5 historical-certificate import surface. The list / detail / error pages
   build hand-rolled body HTML in the handlers (a <section class="import"> with
   base headings, a form, verdict tables and status lists) and render it inside
   the styled admin shell. This block gives that section the same panel-like
   surface, readable width and vertical rhythm as the rest of the dashboard —
   plus a table that borders like .data-table and error copy in the danger hue —
   without re-templating the content markup. */
.import {
  max-width: 68rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--sp-5) var(--sp-6);
}
.import > * + * { margin-block-start: var(--sp-4); }
.import h1 { margin: 0; }
.import h2 { margin: 0; font-size: 1.125rem; }
.import p { margin: 0; color: var(--text-muted); }
.import p.error {
  color: var(--danger);
  font-weight: 600;
}
.import p.empty { color: var(--text-muted); }
.import ul.counts {
  margin: 0;
  padding-inline-start: var(--sp-5);
  color: var(--text-muted);
}
.import table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9375rem;
}
.import th,
.import td {
  text-align: start;
  padding: var(--sp-3) var(--sp-4);
  border-block-end: 1px solid var(--border);
  overflow-wrap: anywhere;
}
.import thead th {
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  font-weight: 600;
}
.import tbody tr:last-child td { border-block-end: none; }
