/* Slate / Heron — Linear-styled redesign tokens
   ===============================================
   Sits on top of the repo's tokens.css but overrides the canvas palette
   to a Linear-faithful warm near-black. Hairlines, soft tall shadows,
   inset top highlights, dim/bright/muted text steps. */

:root {
  /* Type — same family stack as repo, tightened for Linear compactness */
  --aq-ff-sans: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --aq-ff-display: 'Inter Tight', Inter, system-ui, sans-serif;
  /* No monospace anywhere in the product UI (decision 2026-05-09).
     The token is kept so existing var(--aq-ff-mono) call sites resolve,
     but it now points at the sans stack. Any surface that needs aligned
     numerals should add `font-variant-numeric: tabular-nums` directly. */
  --aq-ff-mono: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;

  /* Density (overridden by Tweaks: compact / comfortable) */
  --aq-fs-body: 13px;
  --aq-fs-micro: 11.5px;
  --aq-fs-h1: 28px;
  --aq-fs-h2: 18px;
  --aq-fs-stat: 30px;
  --aq-row-h: 30px;
  --aq-section-gap: 40px;
  --aq-card-pad: 18px;

  /* Linear-style layered greys.
     Surfaces are gradients, not flat colors — a slight top-to-bottom
     lift across each panel makes the UI feel atmospheric without any
     visible "glow". Each layer has its own gradient stops. */
  /* Canvas neutralised 2026-06-12: the old greys were blue-leaning
     (#131519 had B+6 over R) while the brand layer (--slate-*) and the
     marketing site are strict neutrals. B now sits ~+3 over R/G — a
     whisper of coolness, no longer a cast. */
  --aq-page:      #0b0b0d;
  --aq-bg:        #141418;
  --aq-bg-2:      var(--aq-page);
  /* Surface tokens — cards now sit very close to the panel tone so
     they almost disappear into the canvas. Hairline border + faint
     top-edge highlight do all the differentiation work. */
  --aq-surface:   #141418;
  --aq-surface-2: #19191d;
  --aq-surface-3: #202025;

  /* Linear-style atmosphere — light source from top-left, dialled
     way down so the corner doesn't pool. */
  --aq-page-grad:    radial-gradient(ellipse 80% 60% at 30% 0%, #111114 0%, #0b0b0d 70%);
  /* Main panel — Oli flagged top-left as still too bright. Brightest
     corner stop dropped from #1f2127 → #1a1c20 (about 4 luma points)
     and the lit zone shrunk from 25% → 18% so the corner highlight
     reads as a subtle wash rather than a spotlight. Hexes re-pinned
     2026-06-12 to the neutralised grey ramp (same luma, less blue). */
  --aq-main-grad:    radial-gradient(ellipse 140% 120% at 0% 0%, #1b1b1f 0%, #18181c 18%, #151518 55%, #101013 100%);
  /* Cards now sit at panel-tone or just below — Oli wants them to
     read as part of the canvas, not as raised tiles. Panel mid-tone
     is ~#151518; card range is #161619 → #141417 → #111114. The
     hairline border + --aq-edge-top hint do the lifting; the fill
     stays nearly flush with the panel. */
  --aq-surface-grad: linear-gradient(180deg, #161619 0%, #141417 35%, #111114 100%);
  /* Hero glow — subtle wash. Alpha down from 0.030 → 0.014 (now
     barely sub-perceptual at peak), falloff pulled in from 75% → 65%.
     Just enough to suggest atmosphere; not a corner spotlight. */
  --aq-hero-glow:    radial-gradient(ellipse 120% 100% at 0% 0%, rgba(255,255,255,0.014) 0%, rgba(255,255,255,0.006) 35%, transparent 65%);

  /* Hairlines — two tiers (2026-06-12): --aq-line contains (card and
     panel outlines, input borders); --aq-line-soft separates WITHIN a
     surface (list rows, table rows, internal seams). One opacity doing
     both jobs made dense areas read as grids. */
  --aq-line:        rgba(255, 255, 255, 0.10);
  --aq-line-soft:   rgba(255, 255, 255, 0.055);
  --aq-line-strong: rgba(255, 255, 255, 0.12);
  --aq-line-bright: rgba(255, 255, 255, 0.14);

  /* Inset top highlight — 0.06 → 0.04 (too bright as trim), then
     0.04 → 0.05 (2026-06-12): resting cards lost their drop shadows in
     the elevation-grammar pass, so this edge now carries more of the
     material definition and earns a touch more presence. */
  --aq-edge-top: inset 0 1px 0 rgba(255, 255, 255, 0.05);

  /* Type — Linear's body text is a faded off-white, not pure white.
     Stepped through 4 cool neutrals. */
  /* Type — softer, more blended; never pure white. */
  /* Type ramp re-spread 2026-06-12. Two rules: (1) the data is the
     brightest thing on the page — headlines/KPI numerals sit at the
     top step, brighter than any button; (2) faint is decoration only
     (separators, disabled, placeholder), never information. The first
     contrast fix lifted faint to #6e7178 which collapsed the dim/faint
     gap to ~12 luma points; this restores four distinct steps. */
  --aq-text:       #e6e8ec;   /* headlines + KPI numerals */
  --aq-text-muted: #aeb1b9;   /* body */
  --aq-text-dim:   #8a8d95;   /* secondary — ~5.4:1 on card surface */
  --aq-text-faint: #686b73;   /* decoration only */

  /* Status — desaturated, low-chroma */
  --aq-warn:    oklch(0.78 0.14 75);    /* amber */
  --aq-danger:  oklch(0.70 0.16 25);    /* red */
  --aq-success: oklch(0.78 0.13 160);   /* green */

  /* Semantic status variants — single source of truth for tinted fills
     and borders. Use these instead of ad-hoc color-mix()/rgba at call
     sites so they retheme with light mode. */
  --aq-danger-soft:  oklch(0.70 0.16 25 / 0.13);
  --aq-danger-line:  oklch(0.70 0.16 25 / 0.32);
  --aq-warn-soft:    oklch(0.78 0.14 75 / 0.12);
  --aq-warn-line:    oklch(0.78 0.14 75 / 0.30);
  --aq-success-soft: oklch(0.78 0.13 160 / 0.12);
  --aq-success-line: oklch(0.78 0.13 160 / 0.30);

  /* Accent — overridden by Tweaks. Default = slate blue (replaced the
     indigo/AI-purple accent May 2026, Oli). The [data-accent="slateblue"]
     block mirrors these; this :root default is the fallback for any
     surface without a data-accent ancestor. */
  --aq-accent:        oklch(0.62 0.13 245);
  --aq-accent-soft:   oklch(0.62 0.13 245 / 0.16);
  --aq-accent-line:   oklch(0.62 0.13 245 / 0.34);
  --aq-accent-glow:   oklch(0.62 0.13 245 / 0.20);
  --aq-accent-ink:    rgba(255, 255, 255, 0.96);

  /* Soft tall shadows — softened to about 60% of the previous alpha
     because the cards now sit close to the panel tone, so a heavy
     drop-shadow under them looks disconnected. The hairline border
     + --aq-edge-top still carry the elevation cue. */
  --aq-shadow-1: 0 1px 2px rgba(0, 0, 0, 0.18), 0 3px 10px rgba(0, 0, 0, 0.10);
  --aq-shadow-2: 0 1px 3px rgba(0, 0, 0, 0.18), 0 8px 24px rgba(0, 0, 0, 0.18);
  --aq-shadow-hero: 0 1px 0 rgba(255, 255, 255, 0.04) inset,
                    0 18px 48px -20px rgba(0, 0, 0, 0.32),
                    0 1px 2px rgba(0, 0, 0, 0.22);

  /* Radii */
  --aq-r-sm: 6px;
  --aq-r-md: 9px;
  --aq-r-lg: 12px;

  /* Motion */
  --aq-d-1: 120ms;
  --aq-d-2: 220ms;
  --aq-ease: cubic-bezier(0.22, 0.7, 0.3, 1);
}

/* Density variants */
[data-density="comfortable"] {
  --aq-fs-body: 14px;
  --aq-row-h: 34px;
  --aq-section-gap: 48px;
  --aq-card-pad: 22px;
}

/* Atmosphere variants */
[data-atmosphere="flat"] .aq-atmosphere { display: none; }
[data-atmosphere="medium"] .aq-atmosphere { opacity: 0.7; }
[data-atmosphere="high"]   .aq-atmosphere { opacity: 1.1; }

/* Accent variants */
[data-accent="indigo"] {
  --aq-accent:      oklch(0.66 0.16 270);
  --aq-accent-soft: oklch(0.66 0.16 270 / 0.14);
  --aq-accent-line: oklch(0.66 0.16 270 / 0.32);
  --aq-accent-glow: oklch(0.66 0.16 270 / 0.18);
}
[data-accent="aqua"] {
  --aq-accent:      oklch(0.74 0.12 200);
  --aq-accent-soft: oklch(0.74 0.12 200 / 0.14);
  --aq-accent-line: oklch(0.74 0.12 200 / 0.32);
  --aq-accent-glow: oklch(0.74 0.12 200 / 0.20);
}
[data-accent="coral"] {
  --aq-accent:      oklch(0.72 0.16 35);
  --aq-accent-soft: oklch(0.72 0.16 35 / 0.14);
  --aq-accent-line: oklch(0.72 0.16 35 / 0.32);
  --aq-accent-glow: oklch(0.72 0.16 35 / 0.20);
}
[data-accent="pearl"] {
  --aq-accent:      rgba(255, 255, 255, 0.95);
  --aq-accent-soft: rgba(255, 255, 255, 0.08);
  --aq-accent-line: rgba(255, 255, 255, 0.22);
  /* Glow dialled 0.10 → 0.04 (2026-06-12): coloured accents read as a
     tint in the atmosphere wash, but pure white at 0.10 rendered as a
     ~7% grey fog in the top-right — the strongest light on the whole
     canvas, opposite the main panel's top-left light source. Pearl's
     wash should be a whisper, not a second sun. */
  --aq-accent-glow: rgba(255, 255, 255, 0.04);
  --aq-accent-ink: oklch(0.18 0.008 60);
}
/* Slate blue — the calmer, less-saturated action colour chosen to
   replace the indigo/AI-purple accent across the CMS (May 2026, Oli).
   Lower chroma + a touch bluer hue reads as "the action" without the
   purple pop. White ink stays legible on the fill. Set as the app
   default via data-accent on <body> in index.html. */
[data-accent="slateblue"] {
  --aq-accent:      oklch(0.62 0.13 245);
  --aq-accent-soft: oklch(0.62 0.13 245 / 0.16);
  --aq-accent-line: oklch(0.62 0.13 245 / 0.34);
  --aq-accent-glow: oklch(0.62 0.13 245 / 0.20);
  --aq-accent-ink:  rgba(255, 255, 255, 0.96);
}

/* ── Base scaffolding ───────────────────────────────────────────── */

* { box-sizing: border-box; }

/* App-style anchor reset (2026-06-12): no global reset existed, so any
   link without explicit component styling rendered with the browser's
   default underline + colour — visibly raw against the rest of the UI.
   Intent is expressed per component (colour shift or underline on
   hover), never by default. */
a { color: inherit; text-decoration: none; }

.aq-app {
  position: relative;
  display: flex;
  width: 100%;
  height: 100%;
  background: var(--aq-page-grad), var(--aq-page);
  color: var(--aq-text-muted);
  font-family: var(--aq-ff-sans);
  font-size: var(--aq-fs-body);
  line-height: 1.5;
  letter-spacing: -0.005em;
  overflow: hidden;
  font-feature-settings: "ss01", "cv01", "cv11";
  padding: 8px 8px 8px 0;
  gap: 4px;
}

/* Film grain — barely-perceptible noise over the whole app. The long,
   ultra-subtle dark gradients are exactly where cheap panels show
   banding stripes; 2% noise breaks the bands and makes the atmosphere
   read as physical. SVG feTurbulence, no asset, no repaint cost. */
.aq-app::after {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 9998;
  opacity: 0.02;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}
body[data-theme="light"] .aq-app::after { opacity: 0.028; }

/* Atmosphere — subtle background washes layered behind everything.
   Both stops pulled down to match the dialled-back sidebar + main
   panel: accent-glow upper-right is now barely perceptible, and the
   lower-left ambient wash is half its previous strength. */
.aq-atmosphere {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(ellipse 60% 40% at 70% 0%, var(--aq-accent-glow) 0%, transparent 60%),
    radial-gradient(ellipse 80% 50% at 20% 100%, rgba(255,255,255,0.012) 0%, transparent 55%);
  z-index: 0;
}

/* ── Sidebar ────────────────────────────────────────────────────── */

.aq-sidebar {
  position: relative;
  z-index: 2;
  width: 232px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  /* Sidebar wash dialled down to match the new main-panel hero glow.
     Old values pooled brightly in the top-left at 0.08 alpha — far
     brighter than the panel beside it. New peak 0.022, mid-stop
     0.010, falloff pushed further (50% → 80%) so the corner reads
     as ambient lift not a hot spot. */
  background:
    radial-gradient(ellipse 140% 90% at 0% 0%, rgba(255,255,255,0.022) 0%, rgba(255,255,255,0.010) 40%, transparent 80%),
    transparent;
  border: 0;
}

/* Main content — uniform hairline border on all sides. The SVG
   fractalNoise dither was originally layered here to hide 8-bit
   colour banding on dark gradients, but reads as visible grain on
   modern displays (especially in light mode against the cream
   wash). Stripped down to a plain gradient. */
.aq-main {
  background: var(--aq-main-grad);
  border: 1px solid var(--aq-line);
  border-radius: 10px;
  overflow: hidden;
  position: relative;
}
/* Top-edge inner highlight — sits *inside* the border so the border
   thickness stays uniform; provides the light-catch on the top edge. */
.aq-main::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 1px;
  background: linear-gradient(90deg, rgba(255,255,255,0.10) 0%, rgba(255,255,255,0.04) 50%, transparent 100%);
  pointer-events: none;
  z-index: 1;
}
/* Faint accent wash from the top-right of the main panel. Noise
   layer removed — the gradient reads cleanly on its own. */
.aq-main::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--aq-hero-glow);
  pointer-events: none;
  z-index: 0;
}
/* Light theme keeps the same gradient — no noise. */
body[data-theme="light"] .aq-main {
  background: var(--aq-main-grad);
}
/* Topbar sits ABOVE the page content's stacking context so topbar
   popovers (avatar dropdown, bell notifications, etc.) can paint over
   sticky elements inside .aq-content. Previously both shared z-index:1
   and DOM order put .aq-content visually on top — the avatar dropdown
   was getting overlapped by sticky panels (e.g. the displays page
   "Register screen" button + summary stats). z-index:100 keeps modals
   (typically 1000+) winning over the topbar while putting the topbar
   safely above scrolling content. */
.aq-topbar { position: relative; z-index: 100; }
.aq-content { position: relative; z-index: 1; }

.aq-sidebar-head {
  /* Left pad 18px so the wordmark's left edge lines up with the nav
     icon column (.aq-nav 8px + .aq-nav-item 10px) and the section
     labels — was 12px, which left the brand hanging ~6px off-axis. */
  padding: 14px 12px 10px 18px;
  display: flex;
  align-items: center;
  gap: 10px;
}

/* Legacy chevron-mark badge — kept as a no-op for any in-flight
   markup that still references it; the new brand identity is the
   wordmark + terminator square (see .aq-brand-wordmark below). */
.aq-brand-mark { display: none; }

/* Wordmark container — name and terminator square on a baseline.
   Bumped to 22px (from 14px) to give the sidebar brand the presence
   the new identity warrants. "Platform" sub-label removed — the
   wordmark alone is the brand anchor. */
.aq-brand-wordmark {
  display: inline-flex; align-items: baseline; gap: 0.10em;
  font-size: 22px;
  line-height: 1.05;
  color: var(--aq-text);
}
.aq-brand-name {
  font-family: var(--aq-ff-display);
  font-weight: 600;
  font-size: inherit;
  letter-spacing: -0.015em;
  line-height: 1;
}
.aq-brand-square {
  display: inline-block;
  width: 0.22em;
  height: 0.22em;
  background: currentColor;
  transform: translateY(-0.04em);
  flex-shrink: 0;
}
/* .aq-brand-sub — was the "Platform" tagline below the wordmark.
   Removed from sidebar.jsx 2026-05-19; kept as no-op for any stale
   markup that still references it. */
.aq-brand-sub { display: none; }

/* Collapsed sidebar — show only the square as the brand glyph. */
.aq-brand-square-only {
  width: 14px; height: 14px;
  background: var(--aq-text);
  flex-shrink: 0;
}

.aq-sidebar-search {
  margin: 4px 10px 8px;
  display: flex;
  align-items: center;
  gap: 8px;
  height: 28px;
  padding: 0 10px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 6px;
  color: var(--aq-text-faint);
  font-size: 12.5px;
  cursor: text;
  transition: background var(--aq-d-1) var(--aq-ease), border-color var(--aq-d-1) var(--aq-ease);
}
.aq-sidebar-search:hover {
  background: rgba(255,255,255,0.025);
}
.aq-sidebar-search .aq-kbd {
  margin-left: auto;
  font-size: 10px;
  padding: 1px 5px;
  border: 1px solid var(--aq-line);
  border-radius: 4px;
  color: var(--aq-text-faint);
  font-family: var(--aq-ff-mono);
}

.aq-nav { padding: 4px 8px; flex: 1; overflow-y: auto; }
.aq-nav-section { margin-bottom: 14px; }
.aq-nav-title {
  padding: 8px 10px 4px;
  font-size: 10.5px;
  font-weight: 500;
  color: var(--aq-text-faint);
  letter-spacing: 0.02em;
}
.aq-nav-item {
  display: flex;
  align-items: center;
  gap: 9px;
  height: var(--aq-row-h);
  padding: 0 10px;
  border-radius: 6px;
  color: var(--aq-text-dim);
  font-size: 13px;
  font-weight: 450;
  cursor: pointer;
  position: relative;
  transition: background var(--aq-d-1) var(--aq-ease), color var(--aq-d-1) var(--aq-ease);
}
.aq-nav-item:hover {
  background: rgba(255,255,255,0.03);
  color: var(--aq-text);
}
.aq-nav-item.is-active {
  background: var(--aq-surface-2);
  color: var(--aq-text);
  box-shadow: var(--aq-edge-top);
}
.aq-nav-item.is-active::before {
  content: '';
  position: absolute;
  left: -8px;
  top: 50%;
  transform: translateY(-50%);
  width: 2px;
  height: 14px;
  background: var(--aq-accent);
  border-radius: 2px;
}
.aq-nav-item svg {
  width: 15px;
  height: 15px;
  stroke-width: 1.5;
  flex-shrink: 0;
  opacity: 0.9;
}
.aq-nav-item .aq-badge {
  margin-left: auto;
  font-size: 10.5px;
  padding: 1px 6px;
  border-radius: 99px;
  background: var(--aq-surface-2);
  color: var(--aq-text-dim);
  font-weight: 500;
}
.aq-nav-item .aq-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--aq-warn);
  margin-left: auto;
  box-shadow: 0 0 8px currentColor;
  color: var(--aq-warn);
}

.aq-sidebar-foot {
  padding: 10px;
  border-top: 1px solid var(--aq-line);
  display: flex;
  align-items: center;
  gap: 10px;
}
.aq-avatar {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--aq-accent), color-mix(in srgb, var(--aq-accent) 50%, var(--aq-bg-2)));
  display: grid;
  place-items: center;
  font-size: 11px;
  font-weight: 600;
  color: var(--aq-accent-ink);
  flex-shrink: 0;
}
.aq-user-meta { flex: 1; min-width: 0; }
.aq-user-name {
  font-size: 12.5px;
  color: var(--aq-text);
  font-weight: 500;
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.aq-user-role {
  font-size: 10.5px;
  color: var(--aq-text-faint);
  margin-top: 1px;
}

/* ── Main ───────────────────────────────────────────────────────── */

.aq-main {
  position: relative;
  z-index: 2;
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.aq-topbar {
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 24px;
  /* Soft bottom rule — half the standard line opacity so the breadcrumb
     bar is gently delineated without a hard divider cutting the window. */
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
  flex-shrink: 0;
}
.aq-crumbs {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
  color: var(--aq-text-dim);
}
.aq-crumbs .aq-sep { color: var(--aq-text-faint); }
.aq-crumbs .aq-current { color: var(--aq-text); }
.aq-topbar-actions { display: flex; align-items: center; gap: 6px; }

.aq-icon-btn {
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  border-radius: 6px;
  background: transparent;
  border: 0;
  color: var(--aq-text-dim);
  cursor: pointer;
  transition: background var(--aq-d-1) var(--aq-ease), color var(--aq-d-1) var(--aq-ease);
}
.aq-icon-btn:hover { background: var(--aq-surface-2); color: var(--aq-text); }
.aq-icon-btn svg { width: 15px; height: 15px; stroke-width: 1.5; }

/* ── Settings modal — centered overlay launched from the cog ────── */
.aq-settings-modal {
  position: fixed; inset: 0; z-index: 9999;
  background: rgba(8, 10, 14, 0.78);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  display: flex; align-items: center; justify-content: center;
  padding: 32px;
  animation: aqModalFade 0.18s ease-out;
  isolation: isolate;
}
@keyframes aqModalFade { from { opacity: 0; } to { opacity: 1; } }

.aq-settings-card {
  position: relative;
  width: 100%; max-width: 920px;
  /* Fixed height so the card doesn't jump when switching tabs.
     Matches the Slack/Linear/Discord settings pattern — content
     scrolls inside the card rather than the card resizing. */
  height: 640px;
  max-height: 84vh;
  background: var(--aq-surface, #15192a);
  border: 1px solid var(--aq-line);
  border-radius: 14px;
  box-shadow: 0 24px 60px rgba(0,0,0,0.55), 0 1px 0 rgba(255,255,255,0.04) inset;
  overflow: hidden;
  display: flex; flex-direction: column;
  animation: aqModalRise 0.22s cubic-bezier(0.32, 0.72, 0, 1);
}
@keyframes aqModalRise {
  from { opacity: 0; transform: translateY(12px) scale(0.98); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

/* ── Shared animation utilities (May 2026 polish pass) ──────────────
   Linear-style: every motion is short, low-amplitude, and serves a
   single purpose — telling the user something happened. Three utilities
   below cover the bulk of the CMS:

   .aq-page-fade   — apply to a route's outer container so navigating
                     between hash routes feels like a buffer instead of
                     a context-switching slap.
   .aq-drawer-slide — apply to a side drawer (user detail, species
                      editor) for the same slide-from-right that the
                      campaign editor uses.
   .aq-row-hover    — wrap any table that doesn't have a hover affordance
                      yet (audit log, approvals). Matches the new
                      Users-page treatment.
   .aq-rise         — alias of aqModalRise for any popup that doesn't
                      use .aq-settings-card and needs the same look. */
@keyframes aqPageFade {
  from { opacity: 0; transform: translateY(3px); }
  to   { opacity: 1; transform: translateY(0); }
}
.aq-page-fade {
  animation: aqPageFade 160ms ease-out;
  /* Must transparently pass the flex context from .aq-main down to
     the page component, otherwise pages that rely on `flex: 1` +
     internal `overflow: auto` (campaigns gallery, species library,
     analytics, etc.) lose their scroll. Mirror .aq-main's flex
     column setup so the wrapper is a no-op as far as layout is
     concerned. `min-height: 0` is the standard trick that lets a
     flex child shrink below its content size so the inner scroll
     container can take over. */
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

@keyframes aqDrawerSlide {
  from { opacity: 0; transform: translateX(28px); }
  to   { opacity: 1; transform: translateX(0); }
}
.aq-drawer-slide { animation: aqDrawerSlide 220ms cubic-bezier(0.32, 0.72, 0, 1); }

.aq-row-hover { transition: background 120ms ease; }
.aq-row-hover:hover { background: color-mix(in srgb, var(--aq-surface-2) 60%, transparent); }

.aq-rise { animation: aqModalRise 0.22s cubic-bezier(0.32, 0.72, 0, 1); }

.aq-settings-close {
  position: absolute; top: 14px; right: 14px;
  width: 32px; height: 32px; border-radius: 50%;
  border: 1px solid var(--aq-line);
  background: rgba(255,255,255,0.04);
  color: var(--aq-text-dim);
  font-size: 22px; line-height: 1; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  z-index: 2;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.aq-settings-close:hover {
  background: var(--aq-surface-2);
  color: var(--aq-text);
  border-color: var(--aq-border-hover, var(--aq-line));
}

/* ── Generic popup window ────────────────────────────────────────
   Shared visual language for any popup-style window in the CMS —
   the screen-settings menu, contextual action panels, etc.
   Mirrors the system settings card (.aq-settings-card) so the
   curator's eye trains on one material family: same frosted
   backdrop, same gradient surface, same close button shape, same
   fade-in + rise animation. The difference is sizing: this card
   auto-fits its content rather than locking to 920x640.

   Use:
     <div class="aq-popup-modal" onClick={dismiss}>
       <div class="aq-popup-card" onClick={stopPropagation}>
         <button class="aq-popup-close">×</button>
         <header class="aq-popup-header">
           <h2>Title</h2>
           <p>Optional subtitle</p>
         </header>
         <div class="aq-popup-body">
           <div class="aq-popup-section">
             <div class="aq-popup-section-title">Group</div>
             <button class="aq-popup-item">Action…</button>
             <button class="aq-popup-item aq-popup-item--danger">Destroy…</button>
           </div>
         </div>
       </div>
     </div>
*/
.aq-popup-modal {
  position: fixed; inset: 0; z-index: 9999;
  background: rgba(8, 10, 14, 0.78);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  display: flex; align-items: center; justify-content: center;
  padding: 32px;
  animation: aqModalFade 0.18s ease-out;
  isolation: isolate;
}
.aq-popup-card {
  position: relative;
  width: 100%; max-width: 420px;
  max-height: 84vh;
  background: var(--aq-surface-grad, none), var(--aq-surface, #15192a);
  border: 1px solid var(--aq-line);
  border-radius: 14px;
  box-shadow: 0 24px 60px rgba(0,0,0,0.55), 0 1px 0 rgba(255,255,255,0.04) inset;
  overflow: hidden;
  display: flex; flex-direction: column;
  animation: aqModalRise 0.22s cubic-bezier(0.32, 0.72, 0, 1);
}
.aq-popup-close {
  position: absolute; top: 14px; right: 14px;
  width: 32px; height: 32px; border-radius: 50%;
  border: 1px solid var(--aq-line);
  background: rgba(255,255,255,0.04);
  color: var(--aq-text-dim);
  font-size: 22px; line-height: 1; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  z-index: 2;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.aq-popup-close:hover {
  background: var(--aq-surface-2);
  color: var(--aq-text);
  border-color: var(--aq-border-hover, var(--aq-line));
}
.aq-popup-header {
  padding: 22px 56px 14px 24px;          /* extra right padding to clear close btn */
  border-bottom: 1px solid var(--aq-line);
}
.aq-popup-header h2 {
  margin: 0;
  font-family: var(--aq-ff-display, var(--aq-ff-sans));
  font-size: 16px;
  font-weight: 500;
  color: var(--aq-text);
  letter-spacing: -0.005em;
}
.aq-popup-header p {
  margin: 4px 0 0;
  font-size: 12px;
  color: var(--aq-text-dim);
}
.aq-popup-body {
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto;
  padding: 0;                                 /* sections own their padding */
  display: flex; flex-direction: column;
  scrollbar-width: thin;
}
.aq-popup-section {
  display: flex; flex-direction: column;
  gap: 12px;
  padding: 16px 24px;
  border-bottom: 1px solid var(--aq-line-soft);    /* soft separator */
}
.aq-popup-section:last-child { border-bottom: 0; }
.aq-popup-section-title {
  font-family: var(--aq-ff-mono);
  font-size: 10px; font-weight: 500;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--aq-text-faint);
  margin: 0 0 4px;
}
/* Action rows — read as tappable cards rather than link text.
   Padded, full-width, with a chevron at the right that nudges right
   on hover for the "this leads somewhere" affordance. */
.aq-popup-item {
  appearance: none;
  background: var(--aq-surface-2);
  border: 0;
  border-radius: 8px;
  padding: 11px 14px;
  font: inherit;
  font-size: 13px;
  color: var(--aq-text);
  text-align: left;
  cursor: pointer;
  display: flex; align-items: center; gap: 10px;
  transition: background 140ms ease, color 140ms ease;
}
.aq-popup-item::after {
  content: "›";
  margin-left: auto;
  color: var(--aq-text-faint);
  font-size: 16px; line-height: 1;
  transition: transform 140ms ease, color 140ms ease;
}
.aq-popup-item:hover { background: rgba(255,255,255,0.08); }
.aq-popup-item:hover::after {
  transform: translateX(2px);
  color: var(--aq-text);
}
.aq-popup-item--danger { color: var(--aq-danger); }
.aq-popup-item--danger:hover {
  background: color-mix(in srgb, var(--aq-danger) 14%, transparent);
}
.aq-popup-item--danger::after { color: var(--aq-danger); opacity: 0.6; }
.aq-popup-item--danger:hover::after { color: var(--aq-danger); opacity: 1; }

/* Two-line action row — bold label on top, plain-English explainer
   underneath. Used for the Device section in the screen-settings
   popup where action names alone weren't enough ("Replace device"
   vs "Swap with another screen" needed context). */
.aq-popup-item--two-line {
  align-items: flex-start;
  flex-direction: column;
  gap: 3px;
  padding-top: 12px;
  padding-bottom: 12px;
}
.aq-popup-item--two-line::after {
  /* Pin chevron to the top-right corner since the row is taller. */
  position: absolute;
  top: 11px;
  right: 12px;
  margin-left: 0;
}
.aq-popup-item--two-line { position: relative; padding-right: 30px; }
.aq-popup-item-title {
  font-size: 13px;
  font-weight: 500;
  color: inherit;
  line-height: 1.25;
}
.aq-popup-item-sub {
  font-size: 11.5px;
  color: var(--aq-text-dim);
  line-height: 1.35;
}
.aq-popup-item--danger .aq-popup-item-sub {
  color: color-mix(in srgb, var(--aq-danger) 65%, var(--aq-text-dim));
}

/* Wider variant for popups that host a full form rather than a
   simple action list. */
.aq-popup-card--wide { max-width: 540px; }
/* Used by the Screen settings popup (Displays). It hosts longer-form
   content — inhabitants pills, a multiline tour script textarea, audio
   preview — so the regular 540px wide card feels cramped. Width tuned
   to match the per-screen Settings page in spirit while still living
   inside a modal.

   Locked to a stable size (76vh, ~720px on a 13" laptop) so the popup
   doesn't bounce around when the curator switches between Identity
   (tall — 8 fields) and Maintenance (short — one action). Mirrors how
   the Workspace settings page sits on a fixed page area with empty
   space below short tabs. */
.aq-popup-card--xwide {
  max-width: 880px;
  width: 880px;
  height: 76vh;
  min-height: 560px;
  max-height: 820px;
}
/* Inside this popup, drop the per-row divider on .x-form-field. With
   eight Identity rows visible at once the lines feel busy; the card
   border + row padding already give the eye enough structure. The
   Workspace Settings page keeps its lines because it has fewer rows
   per tab. */
.aq-popup-card .x-form-field { border-top: 0; padding: 10px 0; }
.aq-popup-card .x-form-field:first-child { padding-top: 0; }
/* Match the Workspace Settings page chromeless feel: no header
   underline, no footer overline, no sidebar/content vertical divider
   inside this popup. The card's outer border and the inner x-card
   border are the only frames. Scoped to --xwide so the regular
   .aq-popup-card variants (used by other narrow popups) keep their
   commit-modal chrome. */
.aq-popup-card--xwide .aq-popup-header { border-bottom: 0; }
.aq-popup-card--xwide .aq-popup-footer { border-top: 0; background: transparent; }
.aq-popup-card--xwide aside { border-right: 0 !important; }
/* Action items (Device + Maintenance tabs) — inline list rows that
   share the page's flat surface. All three rows look identical except
   Retire's title colour: same padding, same divider, same hover. No
   red tint on the danger row, no focus outline carryover. */
.aq-popup-card--xwide .aq-popup-item {
  background: transparent;
  border: 0;
  border-radius: 0;
  border-bottom: 1px solid var(--aq-line-soft);
  padding: 14px 30px 14px 2px;
  outline: 0;
  transition: background 120ms ease;
}
.aq-popup-card--xwide .aq-popup-item:last-child { border-bottom: 0; }
.aq-popup-card--xwide .aq-popup-item:hover {
  background: rgba(255,255,255,0.03);
}
.aq-popup-card--xwide .aq-popup-item:focus-visible {
  background: rgba(255,255,255,0.05);
  outline: 0;
}
/* Two-line rows — chevron pinned to the right edge of the row. */
.aq-popup-card--xwide .aq-popup-item--two-line { padding-right: 30px; }
.aq-popup-card--xwide .aq-popup-item--two-line::after { right: 6px; top: 16px; }
/* Danger row — same baseline as the others, just red title colour.
   No coloured background on hover/focus, no red border, no extra
   chrome. Mirrors how Apple System Settings handles destructive
   row items (e.g. Reset, Delete account). */
.aq-popup-card--xwide .aq-popup-item--danger {
  color: var(--aq-danger);
  background: transparent !important;
}
.aq-popup-card--xwide .aq-popup-item--danger:hover {
  background: rgba(255,255,255,0.03) !important;
}
.aq-popup-card--xwide .aq-popup-item--danger:focus-visible {
  background: rgba(255,255,255,0.05) !important;
}
/* Title + sub hierarchy — slightly stronger title weight for scan-ability. */
.aq-popup-card--xwide .aq-popup-item-title { font-size: 13.5px; font-weight: 500; }
.aq-popup-card--xwide .aq-popup-item-sub { font-size: 12px; margin-top: 2px; }

/* Form fields inside a popup body. Two layouts:
     1. Stacked (default) — label on top, control below. Long inputs.
     2. Row (--row modifier) — label left, control right. Aligned via
        a fixed 110px label column so every row's control lines up
        on the same vertical, regardless of label length. */
.aq-popup-field {
  display: flex; flex-direction: column; gap: 5px;
}
.aq-popup-field label {
  font-size: 11.5px;
  color: var(--aq-text-dim);
}
.aq-popup-field input[type="text"],
.aq-popup-field input[type="number"],
.aq-popup-field select {
  width: 100%;
  padding: 8px 10px;
  font: inherit; font-size: 13px;
  background: var(--aq-surface-2);
  border: 1px solid var(--aq-line);
  border-radius: 7px;
  color: var(--aq-text);
  outline: 0;
}
.aq-popup-field input:focus,
.aq-popup-field select:focus {
  border-color: var(--aq-accent);
}
.aq-popup-field--row {
  display: grid;
  grid-template-columns: 110px 1fr;
  align-items: center;
  gap: 14px;
}
.aq-popup-field--row label {
  font-size: 12px;
  color: var(--aq-text);                  /* lift label out of dim */
  margin: 0;
}
.aq-popup-field--row > :nth-child(2) {
  justify-self: start;                    /* control hugs left of its cell */
}
.aq-popup-field--row input[type="number"] {
  width: 80px;
}

/* Inline segmented toggle (Landscape / Portrait). */
.aq-popup-segmented {
  display: inline-flex;
  background: var(--aq-surface-2);
  border-radius: 7px;
  padding: 2px;
  gap: 2px;
}
.aq-popup-segmented button {
  appearance: none; background: transparent; border: 0;
  padding: 5px 12px;
  border-radius: 5px;
  font: inherit; font-size: 12px;
  color: var(--aq-text-dim);
  cursor: pointer;
  transition: background 140ms ease, color 140ms ease;
}
.aq-popup-segmented button:hover { color: var(--aq-text); }
.aq-popup-segmented button.is-active {
  background: rgba(255,255,255,0.10);
  color: var(--aq-text);
}

/* iOS-style toggle pill — direct lift of Apple's UISwitch palette.
   • OFF track: neutral grey #39393D (dark mode) / #E9E9EA (light).
     The colour-scheme switch under tokens.css doesn't carry to this
     literal, so we re-flip with the same html[data-color-scheme]
     selector that flips the rest of the chrome.
   • ON  track: Apple system green #34C759 (universal — doesn't
     follow the org's --aq-accent; matches every iOS toggle for
     instant recognition).
   • Knob: pure white with a 2-layer soft shadow + a 0.5px rim
     to lift it off the track. */
.aq-popup-toggle {
  appearance: none; border: 0; padding: 0; cursor: pointer;
  width: 44px; height: 26px;
  background: #39393D;
  border-radius: 999px;
  position: relative;
  transition: background 200ms ease;
}
.aq-popup-toggle span {
  position: absolute; top: 2px; left: 2px;
  width: 22px; height: 22px; border-radius: 50%;
  background: #fff;
  box-shadow:
    0 3px 8px rgba(0, 0, 0, 0.15),
    0 3px 1px rgba(0, 0, 0, 0.06),
    0 0 0 0.5px rgba(0, 0, 0, 0.04);
  transform: translateX(0);
  transition: transform 200ms cubic-bezier(0.32, 0.72, 0, 1);
}
.aq-popup-toggle.is-on {
  background: #34C759;
}
.aq-popup-toggle.is-on span { transform: translateX(16px); }

/* Light-mode OFF track follows iOS: light grey instead of dark grey. */
html[data-color-scheme="light"] .aq-popup-toggle {
  background: #E9E9EA;
}
html[data-color-scheme="light"] .aq-popup-toggle.is-on {
  background: #34C759;
}

/* Save / Cancel button row inside a popup form section. */
.aq-popup-actions {
  display: flex; justify-content: flex-end; gap: 8px;
}

/* Sticky footer for the primary commit action. Sits at the bottom
   of the card with a top border + subtle background tint so it's
   anchored even when the body scrolls. */
.aq-popup-footer {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 14px 24px;
  border-top: 1px solid var(--aq-line);
  background: color-mix(in srgb, var(--aq-surface) 92%, black);
}
.aq-popup-btn {
  appearance: none; border: 0;
  padding: 7px 14px;
  font: inherit; font-size: 12.5px; font-weight: 500;
  border-radius: 7px;
  background: var(--aq-surface-2);
  color: var(--aq-text);
  cursor: pointer;
  transition: background 140ms ease;
}
/* Hover lifts the surface tint slightly. Using color-mix against the
   text token keeps the hover visible in both themes (the previous
   rgba(255,255,255,0.10) was invisible on light backgrounds). */
.aq-popup-btn:hover {
  background: color-mix(in srgb, var(--aq-surface-2) 80%, var(--aq-text) 20%);
}
.aq-popup-btn.primary {
  background: var(--aq-accent);
  color: var(--aq-accent-ink, white);
}
.aq-popup-btn.primary:hover {
  background: color-mix(in srgb, var(--aq-accent) 88%, black);
}
.aq-popup-btn.primary:disabled { opacity: 0.55; cursor: default; }
.aq-popup-btn.danger {
  background: var(--aq-danger);
  color: #fff;
}
.aq-popup-btn.danger:hover {
  background: color-mix(in srgb, var(--aq-danger) 88%, black);
}
.aq-popup-btn.ghost { background: transparent; color: var(--aq-text-dim); }
.aq-popup-btn.ghost:hover { background: var(--aq-surface-2); color: var(--aq-text); }

/* Inline error caption inside a popup section. */
.aq-popup-error {
  margin: 4px 12px 0;
  padding: 6px 10px;
  border-radius: 6px;
  background: color-mix(in srgb, var(--aq-danger) 12%, transparent);
  color: var(--aq-danger);
  font-size: 12px;
}

/* Inline confirmation row — appears in place of the original button
   when an irreversible action is invoked. Replaces window.confirm. */
.aq-popup-confirm {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px;
  margin: 4px 0;
  background: var(--aq-surface-2);
  border-radius: 7px;
  font-size: 12.5px;
  color: var(--aq-text);
}
.aq-popup-confirm > span { flex: 1; min-width: 0; }

/* Scope SettingsScreen content to fit inside the modal card. The
   component renders `<div class="st-content">` with its own
   header + content; we tighten padding and let it scroll. */
.aq-settings-card .st-content {
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto;
  padding: 28px 32px 32px;
  scrollbar-width: thin;
}
.aq-settings-card .st-content > header { margin-bottom: 20px; }
.aq-settings-card .st-content > header h1 { font-size: 22px !important; }
.aq-settings-card .st-content > header p { font-size: 12px !important; }
/* The settings layout uses a 200px sidebar of tabs; tighten gap on
   smaller modal widths. */
@media (max-width: 720px) {
  .aq-settings-modal { padding: 0; align-items: stretch; }
  .aq-settings-card  { max-width: none; max-height: 100dvh; border-radius: 0; }
}

/* ─── Mobile shell (Phase N) ────────────────────────────────────
   Phones: collapse the sidebar entirely, give the content area the
   full viewport. The menu/back/breadcrumbs from the topbar are still
   accessible. Operators check the dashboard mid-tour rather than
   navigate, so hiding the sidebar is the right tradeoff for v1.
   v2 could re-introduce a hamburger drawer. */
@media (max-width: 768px) {
  .aq-app { grid-template-columns: 1fr !important; }
  .aq-sidebar { display: none; }
  .aq-content { padding: 0; }
  .aq-content-inner { padding: 14px 12px !important; max-width: 100% !important; }
  .aq-topbar { padding: 0 12px !important; }
  /* Modals fill the screen on phones — easier than tiny touch targets. */
  .aq-modal-card { max-width: none !important; max-height: 100dvh !important; border-radius: 0 !important; }
}

/* Editor action buttons (Preview / Submit / Save etc.) portalled into
   #aq-topbar-extra-actions. Strip their button chrome so they sit
   naturally next to the bell + cog icons rather than looking like
   form-style pill buttons. Hover gives the same subtle wash as
   .aq-icon-btn for visual continuity. */
#aq-topbar-extra-actions .btn,
#aq-topbar-extra-actions button.btn {
  background: transparent !important;
  border: 0 !important;
  box-shadow: none !important;
  color: var(--aq-text-dim) !important;
  font-weight: 500 !important;
  height: 28px;
  padding: 0 8px;
  border-radius: 6px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12.5px;
  cursor: pointer;
  transition: background var(--aq-d-1) var(--aq-ease), color var(--aq-d-1) var(--aq-ease);
}
#aq-topbar-extra-actions .btn:hover,
#aq-topbar-extra-actions button.btn:hover {
  background: var(--aq-surface-2) !important;
  color: var(--aq-text) !important;
}
#aq-topbar-extra-actions .btn:disabled,
#aq-topbar-extra-actions button.btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  background: transparent !important;
}
#aq-topbar-extra-actions .btn i {
  font-size: 12px;
  opacity: 0.85;
}
/* Keep the primary action (Submit / Publish / Save) slightly more prominent
   than ghost buttons so visitors can still find it — subtle accent tint
   instead of a hard pill. */
#aq-topbar-extra-actions .btn.btn-primary {
  color: var(--aq-text) !important;
  background: color-mix(in srgb, var(--aq-accent, #00c8b4) 14%, transparent) !important;
}
#aq-topbar-extra-actions .btn.btn-primary:hover {
  background: color-mix(in srgb, var(--aq-accent, #00c8b4) 22%, transparent) !important;
}

/* Content area */
.aq-content {
  flex: 1;
  overflow-y: auto;
  padding: 32px 48px 60px;
}
.aq-content-inner {
  max-width: 880px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: var(--aq-section-gap);
}

/* Header line above hero */
.aq-eyebrow {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 11.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--aq-text-faint);
  font-weight: 500;
}
.aq-eyebrow .aq-sep { opacity: 0.5; }

/* ── Hero variants ──────────────────────────────────────────────── */

.aq-hero h1 {
  font-family: var(--aq-ff-display);
  font-size: var(--aq-fs-h1);
  font-weight: 600;
  letter-spacing: -0.025em;
  color: var(--aq-text);
  line-height: 1.15;
  margin: 12px 0 0;
}
.aq-hero h1 .aq-hero-dot {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--aq-warn);
  vertical-align: middle;
  margin-right: 12px;
  margin-bottom: 4px;
  box-shadow: 0 0 14px var(--aq-warn);
}
.aq-hero-meta {
  margin-top: 8px;
  font-size: 13px;
  color: var(--aq-text-dim);
  display: flex;
  gap: 6px;
  align-items: center;
}
.aq-hero-meta .aq-sep { color: var(--aq-text-faint); }

/* Promoted card hero variant */
.aq-hero-card {
  position: relative;
  background: var(--aq-surface-grad), var(--aq-surface);
  border: 1px solid var(--aq-line);
  border-radius: var(--aq-r-lg);
  padding: 22px 24px;
  box-shadow: var(--aq-shadow-hero);
  overflow: hidden;
}
.aq-hero-card::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 80% 100% at 100% 0%, var(--aq-accent-glow), transparent 60%);
  pointer-events: none;
}
.aq-hero-card-row {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 24px;
}
.aq-hero-card-body { flex: 1; }
.aq-hero-card-title {
  font-family: var(--aq-ff-display);
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--aq-text);
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 6px;
}
.aq-hero-card-sub {
  color: var(--aq-text-dim);
  font-size: 13px;
  max-width: 480px;
  line-height: 1.5;
}
.aq-hero-card-cta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 32px;
  padding: 0 14px;
  background: var(--aq-accent);
  color: var(--aq-accent-ink);
  border: 0;
  border-radius: 7px;
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;
  transition: opacity var(--aq-d-1) var(--aq-ease);
}
.aq-hero-card-cta:hover { opacity: 0.9; }
.aq-hero-card-cta svg { width: 13px; height: 13px; stroke-width: 1.75; }

/* Inbox-stack hero */
.aq-inbox-list {
  display: flex;
  flex-direction: column;
  background: var(--aq-surface-grad), var(--aq-surface);
  border: 1px solid var(--aq-line);
  border-radius: var(--aq-r-lg);
  overflow: hidden;
  box-shadow: var(--aq-edge-top);
}
.aq-inbox-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--aq-line-soft);
  cursor: pointer;
  transition: background var(--aq-d-1) var(--aq-ease);
}
.aq-inbox-row:last-child { border-bottom: 0; }
.aq-inbox-row:hover { background: var(--aq-surface-2); }
.aq-inbox-row.is-active { background: var(--aq-surface-2); }
.aq-inbox-icon {
  width: 26px;
  height: 26px;
  border-radius: 6px;
  background: var(--aq-surface-2);
  color: var(--aq-text-dim);
  display: grid;
  place-items: center;
  flex-shrink: 0;
}
.aq-inbox-icon svg { width: 13px; height: 13px; stroke-width: 1.75; }
.aq-inbox-row.is-pending .aq-inbox-icon {
  background: color-mix(in srgb, var(--aq-warn) 18%, transparent);
  color: var(--aq-warn);
}
.aq-inbox-body { flex: 1; min-width: 0; }
.aq-inbox-title {
  font-size: 13px;
  color: var(--aq-text);
  font-weight: 500;
  letter-spacing: -0.005em;
  display: flex;
  align-items: center;
  gap: 10px;
}
.aq-inbox-title .aq-tag {
  font-size: 10.5px;
  color: var(--aq-text-faint);
  font-family: var(--aq-ff-mono);
  font-weight: 400;
  letter-spacing: 0;
}
.aq-inbox-meta {
  font-size: 12px;
  color: var(--aq-text-dim);
  margin-top: 1px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.aq-inbox-time {
  font-size: 11.5px;
  color: var(--aq-text-faint);
  flex-shrink: 0;
}

/* ── Stats row (borderless) ─────────────────────────────────────── */

.aq-stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 32px;
}
.aq-stat-label {
  font-size: 12px;
  color: var(--aq-text-dim);
  margin-bottom: 8px;
  letter-spacing: -0.005em;
}
.aq-stat-value {
  font-family: var(--aq-ff-display);
  font-size: var(--aq-fs-stat);
  font-weight: 600;
  color: var(--aq-text);
  letter-spacing: -0.025em;
  line-height: 1;
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.aq-stat-trend {
  font-size: 11.5px;
  color: var(--aq-text-dim);
  font-weight: 500;
  font-family: var(--aq-ff-sans);
}
.aq-stat-trend.is-up { color: var(--aq-success); }
.aq-stat-trend.is-down { color: var(--aq-danger); }
.aq-stat-trend.is-warn { color: var(--aq-warn); }
.aq-stat-sub {
  font-size: 11.5px;
  color: var(--aq-text-faint);
  margin-top: 6px;
}
/* Sub links are quiet by default — warn/danger tone must be earned by
   state (set inline by the caller), never the resting link colour. */
.aq-stat-sub a { color: var(--aq-text-dim); cursor: pointer; transition: color var(--aq-d-1) var(--aq-ease); }
.aq-stat-sub a:hover { color: var(--aq-text); }

/* ── Section blocks ─────────────────────────────────────────────── */

.aq-section {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.aq-section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.aq-section-title {
  font-size: 13px;
  font-weight: 500;
  color: var(--aq-text);
  letter-spacing: -0.005em;
  display: flex;
  align-items: center;
  gap: 8px;
}
.aq-section-title svg {
  width: 13px;
  height: 13px;
  stroke-width: 1.5;
  color: var(--aq-text-dim);
}
.aq-section-link {
  font-size: 12px;
  color: var(--aq-text-dim);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  transition: color var(--aq-d-1) var(--aq-ease);
}
.aq-section-link:hover { color: var(--aq-text); }

.aq-grid-2 {
  display: grid;
  grid-template-columns: 1.2fr 1fr;
  gap: 24px;
}

/* Card surface — subtle vertical gradient so each card has its own
   internal light direction, matching Linear's layered feel.
   Elevation grammar (2026-06-12): resting surfaces are FLUSH — border +
   edge-top only, no drop shadow. Cards sit at panel tone by design
   (Oli), and a flush surface casting a shadow is physically
   contradictory. Shadow now means something: --aq-shadow-1 = raised
   (hover, dropdowns), --aq-shadow-2/hero = floating (modals, the
   incident hero card). */
.aq-card {
  position: relative;
  background: var(--aq-surface-grad), var(--aq-surface);
  border: 1px solid var(--aq-line);
  border-radius: var(--aq-r-lg);
  padding: var(--aq-card-pad);
  box-shadow: var(--aq-edge-top);
}

/* Org / list rows inside cards */
.aq-list-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--aq-line-soft);
  cursor: pointer;
}
.aq-list-row:last-child { border-bottom: 0; }
.aq-list-row:hover .aq-list-name { color: var(--aq-text); }

.aq-list-mark {
  width: 28px;
  height: 28px;
  border-radius: 6px;
  background: var(--aq-surface-2);
  color: var(--aq-text-dim);
  display: grid;
  place-items: center;
  font-size: 11px;
  font-weight: 600;
  flex-shrink: 0;
}
.aq-list-body { flex: 1; min-width: 0; }
.aq-list-name {
  font-size: 13px;
  color: var(--aq-text-muted);
  font-weight: 500;
  transition: color var(--aq-d-1) var(--aq-ease);
}
.aq-list-meta {
  font-size: 11.5px;
  color: var(--aq-text-faint);
  margin-top: 1px;
}
.aq-list-action {
  font-size: 11.5px;
  color: var(--aq-text-faint);
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

/* Digest banner */
.aq-digest {
  position: relative;
  background: var(--aq-surface-grad), var(--aq-surface);
  border: 1px solid var(--aq-line);
  border-radius: var(--aq-r-lg);
  padding: 16px 20px;
  box-shadow: var(--aq-edge-top);
}
.aq-digest-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
}
.aq-digest-icon {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--aq-accent-soft);
  color: var(--aq-accent);
  display: grid;
  place-items: center;
  flex-shrink: 0;
}
.aq-digest-icon svg { width: 12px; height: 12px; stroke-width: 1.75; }
.aq-digest-title {
  font-size: 12.5px;
  font-weight: 500;
  color: var(--aq-text);
  letter-spacing: -0.005em;
}
.aq-digest-time {
  font-size: 11.5px;
  color: var(--aq-text-faint);
  font-family: var(--aq-ff-mono);
  margin-left: auto;
}
.aq-digest-body {
  font-size: 13px;
  line-height: 1.55;
  color: var(--aq-text-muted);
  text-wrap: pretty;
}
.aq-digest-tags {
  display: flex;
  gap: 6px;
  margin-top: 12px;
}
.aq-tag-pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 8px;
  font-size: 11px;
  font-weight: 500;
  border-radius: 99px;
  border: 1px solid var(--aq-line-strong);
  color: var(--aq-text-dim);
  background: rgba(255,255,255,0.02);
}
.aq-tag-pill .aq-tag-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.85;
}
.aq-tag-pill.is-info { color: oklch(0.78 0.10 240); }
.aq-tag-pill.is-warn { color: var(--aq-warn); }

/* Activity row (Linear-style log) */
.aq-activity { display: flex; flex-direction: column; }
.aq-activity-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 0;
  font-size: 12.5px;
  color: var(--aq-text-dim);
}
.aq-activity-row .aq-avatar-mini {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--aq-surface-2);
  display: grid;
  place-items: center;
  font-size: 9px;
  color: var(--aq-text-dim);
  flex-shrink: 0;
}
.aq-activity-row strong { color: var(--aq-text); font-weight: 500; }
.aq-activity-row .aq-time { margin-left: auto; color: var(--aq-text-faint); font-size: 11.5px; }

/* Manage link */
.aq-manage {
  margin-top: 22px;
  text-align: center;
  font-size: 12.5px;
  color: var(--aq-text-dim);
  cursor: pointer;
  transition: color var(--aq-d-1) var(--aq-ease);
}
.aq-manage:hover { color: var(--aq-text); }
.aq-manage::after {
  content: ' →';
  display: inline;
  margin-left: 2px;
}

/* ── Species Library ────────────────────────────────────────────── */

.aq-lib-toolbar {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
.aq-lib-search {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 30px;
  padding: 0 10px;
  background: var(--aq-surface);
  border: 1px solid var(--aq-line);
  border-radius: 7px;
  color: var(--aq-text-faint);
  font-size: 12.5px;
  width: 240px;
  flex-shrink: 0;
}
.aq-lib-search input {
  flex: 1;
  background: transparent;
  border: 0;
  outline: 0;
  color: var(--aq-text);
  font: inherit;
  font-size: 12.5px;
}
.aq-lib-search input::placeholder { color: var(--aq-text-faint); }
.aq-lib-search .aq-kbd {
  font-size: 10px;
  padding: 1px 5px;
  border: 1px solid var(--aq-line);
  border-radius: 4px;
  color: var(--aq-text-faint);
  font-family: var(--aq-ff-mono);
}

.aq-lib-tabs {
  display: flex;
  align-items: center;
  gap: 2px;
  flex: 1;
  overflow-x: auto;
}
.aq-tab {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 28px;
  padding: 0 10px;
  border-radius: 6px;
  background: transparent;
  border: 0;
  color: var(--aq-text-dim);
  font: inherit;
  font-size: 12.5px;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--aq-d-1) var(--aq-ease), color var(--aq-d-1) var(--aq-ease);
}
.aq-tab:hover { color: var(--aq-text); background: var(--aq-surface-2); }
.aq-tab.is-active { color: var(--aq-text); background: var(--aq-surface-2); box-shadow: var(--aq-edge-top); }
.aq-tab-count {
  font-size: 10.5px;
  padding: 1px 5px;
  border-radius: 99px;
  background: rgba(255,255,255,0.06);
  color: var(--aq-text-faint);
  font-weight: 500;
  min-width: 16px;
  text-align: center;
}
.aq-tab-count.is-warn { background: color-mix(in srgb, var(--aq-warn) 22%, transparent); color: var(--aq-warn); }
.aq-tab-count.is-danger { background: color-mix(in srgb, var(--aq-danger) 22%, transparent); color: var(--aq-danger); }

.aq-lib-actions { display: flex; align-items: center; gap: 6px; }
.aq-btn-primary {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 30px;
  padding: 0 12px;
  background: var(--aq-accent);
  color: var(--aq-accent-ink);
  border: 0;
  border-radius: 7px;
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
}
.aq-btn-primary:hover { opacity: 0.9; }

.aq-species-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px;
}
@media (max-width: 1100px) { .aq-species-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 800px)  { .aq-species-grid { grid-template-columns: repeat(2, 1fr); } }

/* Borderless cards (May 2026, Oli). Bg-removed cutouts float against
   the page background; metadata sits below without a visible card
   chrome. Hover gives a very subtle wash so visitors still get the
   "this is one species" feedback when scanning the grid, but no
   permanent border ringing every card. The previous styling
   (1px line + gradient surface + box-shadow) is kept commented for
   easy revert. */
.aq-species-card {
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--aq-r-lg);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  transition:
    background var(--aq-d-1) var(--aq-ease),
    border-color var(--aq-d-1) var(--aq-ease),
    transform var(--aq-d-1) var(--aq-ease);
}
/* Hover strengthened May 2026 — previously only a faint bg tint, which
   left the click target ambiguous in a dense grid. Now we add a 1px
   accent border so the card you're about to click is unmistakable. */
.aq-species-card:hover {
  background: color-mix(in srgb, var(--aq-surface) 55%, transparent);
  border-color: color-mix(in srgb, var(--aq-line) 80%, transparent);
  transform: translateY(-1px);
}

.aq-species-thumb {
  position: relative;
  /* Bumped 180 → 220 May 2026 to give object-fit:contain images more
     room. cover was cropping heads off tall subjects (penguin, polar
     bear); contain keeps everything visible but needs a taller thumb
     so landscape subjects don't look small. */
  height: 220px;
  /* Inner divider removed alongside the outer card border so the
     cutout image meets the metadata strip without a horizontal line. */
  overflow: hidden;
}
.aq-species-thumb-art {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 80% 110% at 30% 30%, oklch(0.55 0.10 var(--sp-hue) / 0.55), transparent 60%),
    radial-gradient(ellipse 60% 80% at 80% 80%, oklch(0.40 0.14 var(--sp-hue) / 0.45), transparent 65%),
    repeating-linear-gradient(135deg, rgba(255,255,255,0.02) 0 1px, transparent 1px 8px),
    oklch(0.22 0.04 var(--sp-hue));
  display: grid;
  place-items: center;
}
.aq-species-thumb-mono {
  font-family: var(--aq-ff-mono);
  font-size: 10.5px;
  letter-spacing: 0.12em;
  color: rgba(255,255,255,0.55);
  background: rgba(0,0,0,0.18);
  padding: 3px 8px;
  border-radius: 4px;
  border: 1px solid rgba(255,255,255,0.06);
}
.aq-species-badges {
  position: absolute;
  top: 8px;
  left: 8px;
  display: flex;
  gap: 6px;
}

.aq-species-body {
  /* Tightened May 2026 (top padding 12→8, gap 10→6) so the name sits
     closer to the photo and each card reads as one tighter unit. */
  padding: 8px 14px 12px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.aq-species-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}
.aq-species-name {
  font-family: var(--aq-ff-display);
  font-size: 14px;
  font-weight: 600;
  color: var(--aq-text);
  letter-spacing: -0.01em;
  line-height: 1.2;
}
.aq-species-latin {
  font-size: 11.5px;
  color: var(--aq-text-faint);
  font-style: italic;
  margin-top: 2px;
}

.aq-species-stats {
  display: flex;
  gap: 14px;
  font-size: 12px;
  color: var(--aq-text-dim);
}
.aq-species-stats > div { display: inline-flex; align-items: baseline; gap: 4px; }
.aq-species-stat-v { font-size: 12.5px; color: var(--aq-text); font-weight: 500; font-variant-numeric: tabular-nums; }
.aq-species-stat-k { font-size: 11.5px; color: var(--aq-text-faint); }

.aq-species-habitat {
  font-size: 12px;
  color: var(--aq-text-dim);
  line-height: 1.45;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-wrap: pretty;
}

.aq-species-flag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11.5px;
  color: var(--aq-text-dim);
  padding-top: 8px;
  border-top: 1px solid var(--aq-line);
}
.aq-species-flag.is-warn { color: var(--aq-warn); }
.aq-species-flag.is-danger { color: var(--aq-danger); }

/* Pills used across library + dashboard */
.aq-pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 8px;
  font-size: 10.5px;
  font-weight: 500;
  border-radius: 99px;
  border: 1px solid var(--aq-line-strong);
  background: rgba(0,0,0,0.45);
  color: var(--aq-text);
  letter-spacing: -0.005em;
  backdrop-filter: blur(8px);
}
.aq-pill .aq-pill-dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: currentColor;
}
.aq-pill.is-warn { color: var(--aq-warn); border-color: color-mix(in srgb, var(--aq-warn) 36%, transparent); }
.aq-pill.is-success { color: var(--aq-success); border-color: color-mix(in srgb, var(--aq-success) 36%, transparent); }
.aq-pill.is-danger { color: var(--aq-danger); border-color: color-mix(in srgb, var(--aq-danger) 36%, transparent); }
.aq-pill.is-neutral { color: var(--aq-text-dim); }
.aq-pill.is-soft { background: transparent; border-color: var(--aq-line-strong); }
.aq-pill.is-soft.is-warn { background: color-mix(in srgb, var(--aq-warn) 12%, transparent); border-color: color-mix(in srgb, var(--aq-warn) 30%, transparent); }
.aq-pill.is-soft.is-success { background: color-mix(in srgb, var(--aq-success) 10%, transparent); border-color: color-mix(in srgb, var(--aq-success) 28%, transparent); }
.aq-pill.is-soft.is-danger { background: color-mix(in srgb, var(--aq-danger) 12%, transparent); border-color: color-mix(in srgb, var(--aq-danger) 30%, transparent); }
.aq-pill.is-soft.is-neutral { color: var(--aq-text-dim); background: rgba(255,255,255,0.04); }
.aq-content::-webkit-scrollbar,
.aq-nav::-webkit-scrollbar { width: 8px; height: 8px; }
.aq-content::-webkit-scrollbar-thumb,
.aq-nav::-webkit-scrollbar-thumb { background: var(--aq-line-strong); border-radius: 4px; }
.aq-content::-webkit-scrollbar-track,
.aq-nav::-webkit-scrollbar-track { background: transparent; }


/* ── Light theme ─────────────────────────────────────────────────
   Flips the core surface/text/line tokens. Per-screen stylesheets
   that hardcode aquarium-content colors (display device frames,
   campaign editor preview, pairing TV) intentionally stay dark —
   they're showing dark content on screens, not chrome. */
body[data-theme="light"] {
  --aq-page:      #f4f4f0;
  --aq-bg:        #ececea;
  --aq-bg-2:      #f4f4f0;
  --aq-surface:   #ffffff;
  --aq-surface-2: #f7f7f4;
  --aq-surface-3: #ededea;

  --aq-page-grad:    radial-gradient(ellipse 80% 60% at 30% 0%, #fafaf6 0%, #ececea 70%);
  --aq-main-grad:    radial-gradient(ellipse 130% 110% at 0% 0%, #ffffff 0%, #fafaf7 30%, #f3f3f0 65%, #ededea 100%);
  --aq-surface-grad: linear-gradient(155deg, #ffffff 0%, #fafaf7 50%, #f4f4f0 100%);
  --aq-hero-glow:    radial-gradient(ellipse 50% 70% at 0% 0%, rgba(0,0,0,0.025) 0%, transparent 55%);

  --aq-line:        rgba(0, 0, 0, 0.10);
  --aq-line-soft:   rgba(0, 0, 0, 0.06);
  --aq-line-strong: rgba(0, 0, 0, 0.13);
  --aq-line-bright: rgba(0, 0, 0, 0.18);

  --aq-edge-top: inset 0 1px 0 rgba(255, 255, 255, 0.7);

  --aq-text:       #1d1f24;
  --aq-text-muted: #44464d;
  --aq-text-dim:   #6c6e76;
  --aq-text-faint: #9a9ca2;

  --aq-shadow-1: 0 1px 2px rgba(20, 22, 30, 0.06), 0 4px 14px rgba(20, 22, 30, 0.05);
  --aq-shadow-2: 0 2px 4px rgba(20, 22, 30, 0.06), 0 12px 32px rgba(20, 22, 30, 0.08);
  --aq-shadow-hero: 0 1px 0 rgba(255, 255, 255, 0.8) inset,
                    0 24px 60px -20px rgba(20, 22, 30, 0.18),
                    0 1px 2px rgba(20, 22, 30, 0.05);

  --aq-accent-soft: oklch(0.62 0.13 245 / 0.10);
  --aq-accent-line: oklch(0.62 0.13 245 / 0.28);
  --aq-accent-glow: oklch(0.62 0.13 245 / 0.12);
  --aq-accent-ink:  rgba(255, 255, 255, 0.98);

  /* Status colours for light surfaces (2026-06-12 audit): the dark-canvas
     values (L 0.70–0.78) sat at <2:1 on white — amber links and success
     dots were effectively invisible. Lightness dropped, chroma held. */
  --aq-warn:    oklch(0.60 0.13 70);
  --aq-danger:  oklch(0.54 0.17 25);
  --aq-success: oklch(0.52 0.13 160);
  --aq-danger-soft:  oklch(0.54 0.17 25 / 0.10);
  --aq-danger-line:  oklch(0.54 0.17 25 / 0.30);
  --aq-warn-soft:    oklch(0.60 0.13 70 / 0.12);
  --aq-warn-line:    oklch(0.60 0.13 70 / 0.30);
  --aq-success-soft: oklch(0.52 0.13 160 / 0.10);
  --aq-success-line: oklch(0.52 0.13 160 / 0.30);
}

/* Light-mode primary buttons that use var(--aq-text) as bg need light text.
   These buttons set `background: var(--aq-text)` which flips dark in
   light mode — so their text needs to flip white to stay visible.
   Buttons that hardcode `background: white` (like .ss-btn.primary and
   .zn-detail-actions .zn-btn.primary) are NOT in this list — their
   text should stay dark in light mode (otherwise white-on-white).

   IMPORTANT (2026-05-15 light-mode audit): the previous selector here
   was `body[data-theme="light"]`, but the actual color-scheme attribute
   is set on `<html data-color-scheme="light">` by /shared/theme-
   color-scheme.js — so these overrides NEVER fired. Result: every
   primary button on the CMS rendered as dark-text-on-dark-button in
   light mode (effectively invisible until hover changed the bg).
   Switched selectors to the right attribute below. */
/* Every primary button that sets `background: var(--aq-text)` lands
   here so its text flips to white in light mode. The full inventory
   came from grepping for `background: var(--aq-text)` across the CMS
   stylesheets — keep this list aligned if you add new dark-bg
   primary buttons. */
html[data-color-scheme="light"] .x-btn,
html[data-color-scheme="light"] .st-btn.primary,
html[data-color-scheme="light"] .scs-btn:not(.ghost),
html[data-color-scheme="light"] .sc-compose-tools button,
html[data-color-scheme="light"] .ds-btn.primary,
html[data-color-scheme="light"] .nf-btn,
html[data-color-scheme="light"] .nf-action.primary,
html[data-color-scheme="light"] .ob-btn:not(.ghost):not(.ob-btn--ghost),
html[data-color-scheme="light"] .sc-btn:not(.ghost),
html[data-color-scheme="light"] .ce-publish,
html[data-color-scheme="light"] .se-btn.primary {
  color: #ffffff !important;
}
html[data-color-scheme="light"] .x-btn.ghost { color: var(--aq-text) !important; }
html[data-color-scheme="light"] .x-btn.is-success { color: white !important; }

/* Hover state of these buttons sets bg to rgba(255,255,255,0.92) —
   which on light mode lands as near-white on near-white background,
   making the dark-text rule above invert again. Force light-mode
   hover to stay dark so the contrast stays consistent. */
html[data-color-scheme="light"] .st-btn.primary:hover,
html[data-color-scheme="light"] .scs-btn:not(.ghost):hover {
  background: color-mix(in srgb, var(--aq-text) 88%, white) !important;
}

/* Scrollbars */
html[data-color-scheme="light"] .aq-content::-webkit-scrollbar-thumb,
html[data-color-scheme="light"] .aq-nav::-webkit-scrollbar-thumb {
  background: rgba(0, 0, 0, 0.18);
}

/* Light-mode accent variants reduce alphas slightly so they read on white.
   NOTE (2026-06-12 audit): data-accent is set on <body> (app.jsx boot),
   not <html> — the original `html[...][data-accent=...]` selectors never
   matched, so none of these fired. Most visibly: pearl stayed white-on-
   white in light mode. Both attribute placements are covered now. */
html[data-color-scheme="light"] body[data-accent="indigo"],
body[data-theme="light"][data-accent="indigo"] {
  --aq-accent-soft: oklch(0.66 0.16 270 / 0.10);
  --aq-accent-line: oklch(0.55 0.20 270 / 0.32);
  --aq-accent-glow: oklch(0.66 0.16 270 / 0.12);
}
html[data-color-scheme="light"] body[data-accent="slateblue"],
body[data-theme="light"][data-accent="slateblue"] {
  --aq-accent-soft: oklch(0.62 0.13 245 / 0.10);
  --aq-accent-line: oklch(0.52 0.15 245 / 0.32);
  --aq-accent-glow: oklch(0.62 0.13 245 / 0.12);
}
html[data-color-scheme="light"] body[data-accent="aqua"],
body[data-theme="light"][data-accent="aqua"] {
  --aq-accent-soft: oklch(0.74 0.12 200 / 0.12);
  --aq-accent-line: oklch(0.55 0.14 200 / 0.30);
  --aq-accent-glow: oklch(0.74 0.12 200 / 0.14);
}
html[data-color-scheme="light"] body[data-accent="coral"],
body[data-theme="light"][data-accent="coral"] {
  --aq-accent-soft: oklch(0.72 0.16 35 / 0.12);
  --aq-accent-line: oklch(0.60 0.18 35 / 0.32);
  --aq-accent-glow: oklch(0.72 0.16 35 / 0.14);
}
/* Pearl mirrors across schemes: white accent on dark, near-black on light.
   Ink flips with it so accent-filled buttons stay legible. */
html[data-color-scheme="light"] body[data-accent="pearl"],
body[data-theme="light"][data-accent="pearl"] {
  --aq-accent:      rgba(0, 0, 0, 0.85);
  --aq-accent-soft: rgba(0, 0, 0, 0.06);
  --aq-accent-line: rgba(0, 0, 0, 0.15);
  --aq-accent-glow: rgba(0, 0, 0, 0.06);
  --aq-accent-ink:  rgba(255, 255, 255, 0.96);
}

/* ══════════════════════════════════════════════════════════════════
   GLOBAL UTILITIES — Apple Quality Polish Pass
   Added 2026-06-08
   ══════════════════════════════════════════════════════════════════ */

/* ── Skeleton shimmer ──────────────────────────────────────────────
   Promoted from displays.css ds-skeleton-shimmer to a shared
   utility. Apply .aq-skeleton to any loading placeholder.         */
@keyframes aq-skeleton-shimmer {
  from { background-position: -300px 0; }
  to   { background-position:  300px 0; }
}
.aq-skeleton {
  background: linear-gradient(
    90deg,
    var(--aq-surface)   25%,
    var(--aq-surface-2) 50%,
    var(--aq-surface)   75%
  );
  background-size: 600px 100%;
  animation: aq-skeleton-shimmer 1.4s ease infinite;
  border-radius: 4px;
}
@media (prefers-reduced-motion: reduce) {
  .aq-skeleton { animation: none; background: var(--aq-surface-2); }
}

/* ── Toast keyframes ───────────────────────────────────────────────
   Entrance: slide up 8px + scale from 0.97. Exit: slide down + fade. */
@keyframes aq-toast-in {
  from { opacity: 0; transform: translateY(8px) scale(0.97); }
  to   { opacity: 1; transform: translateY(0)   scale(1);    }
}
@keyframes aq-toast-out {
  from { opacity: 1; transform: translateY(0)  scale(1);    }
  to   { opacity: 0; transform: translateY(4px) scale(0.96); }
}
.aq-toast {
  animation: aq-toast-in var(--aq-d-2) var(--aq-ease) both;
  /* layout */
  display: flex; align-items: flex-start; gap: 10px;
  padding: 10px 12px;
  border-radius: 8px;
  box-shadow: var(--aq-shadow-2);
  font-size: 12.5px; color: var(--aq-text);
  min-width: 220px;
}
.aq-toast.is-leaving {
  animation: aq-toast-out 160ms var(--aq-ease) both;
}
@media (prefers-reduced-motion: reduce) {
  .aq-toast, .aq-toast.is-leaving { animation: none; }
}
.aq-toast-dot {
  width: 6px; height: 6px; border-radius: 50%;
  margin-top: 7px; flex-shrink: 0;
}
.aq-toast-msg {
  flex: 1; line-height: 1.45; color: var(--aq-text);
}
.aq-toast-action {
  padding: 2px 7px; font-size: 11.5px;
  background: transparent;
  border: 1px solid var(--aq-line);
  border-radius: 5px; cursor: pointer;
  font-family: inherit; flex-shrink: 0;
}
.aq-toast-close {
  padding: 0; width: 16px; height: 16px;
  background: transparent; border: 0;
  color: var(--aq-text-faint); cursor: pointer;
  display: grid; place-items: center; flex-shrink: 0;
  margin-top: 2px;
}

/* ── Popover entrance ──────────────────────────────────────────────
   Used by TopbarAvatar, bell popover, QueueBadge dropdown.         */
@keyframes aq-popover-in {
  from { opacity: 0; transform: translateY(-4px) scale(0.98); }
  to   { opacity: 1; transform: translateY(0)     scale(1);    }
}
.aq-popover {
  animation: aq-popover-in var(--aq-d-2) var(--aq-ease) both;
}
@media (prefers-reduced-motion: reduce) {
  .aq-popover { animation: none; }
}

/* ── Search modal entrance ─────────────────────────────────────────
   Cmd+K command palette — drop in from slightly above.             */
@keyframes aq-search-drop {
  from {
    opacity: 0;
    transform: translateX(-50%) translateY(-8px) scale(0.98);
  }
  to {
    opacity: 1;
    transform: translateX(-50%) translateY(0)     scale(1);
  }
}

/* ── Global :active press states ──────────────────────────────────
   Every button gets a 1px press-down. Components with their own
   :active (auth.css) are unaffected — specificity wins.           */
.x-btn:active,
.st-btn:active,
.nf-btn:active,
.nf-action:active,
.sc-btn:active,
.ds-btn:active,
.us-btn:active,
.aq-row-btn:active,
.aq-org-card:active,
.ce-ghost-btn:active,
.cp-new-main:active,
.cp-new-arrow:active,
.cp-qs-tile:active {
  transform: translateY(1px);
  transition-duration: 60ms !important;
}

/* ── Global keyboard focus recovery ───────────────────────────────
   Catches any input/button where outline:0 was set without a paired
   focus-visible style. Scoped to :focus-visible so mouse/touch
   focus is unaffected. Components with intentional custom focus
   treatments (species editor borderless inputs, auth inputs) can
   override this by setting outline:none in their own :focus-visible. */
*:focus-visible {
  outline: 2px solid var(--aq-accent);
  outline-offset: 2px;
}
/* Borderless-until-focus inputs — intentional Linear-style treatment */
.se-input:focus-visible,
.se-textarea:focus-visible {
  outline: none;
}
/* Auth surface uses its own ring (box-shadow: 0 0 0 2px slate-bone) */
.aq-auth-input:focus-visible {
  outline: none;
}

/* ══════════════════════════════════════════════════════════════════
   Dashboard — Mission Control (2026-06-12 redesign)
   Builds on the existing primitives: .aq-hero-card (promoted hero),
   .aq-inbox-* (attention queue), .aq-stats (KPI strip), .aq-activity.
   Prototype reference: public/cms/mocks/dashboard-mission-control.html
   ══════════════════════════════════════════════════════════════════ */

/* Staggered entrance — one cascade on mount, then inert. */
@keyframes aqDashRise {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}
.aq-dash-stagger > * { animation: aqDashRise 420ms var(--aq-ease) backwards; }
.aq-dash-stagger > *:nth-child(1) { animation-delay: 0ms; }
.aq-dash-stagger > *:nth-child(2) { animation-delay: 60ms; }
.aq-dash-stagger > *:nth-child(3) { animation-delay: 120ms; }
.aq-dash-stagger > *:nth-child(4) { animation-delay: 180ms; }
.aq-dash-stagger > *:nth-child(5) { animation-delay: 240ms; }
.aq-dash-stagger > *:nth-child(6) { animation-delay: 300ms; }
@media (prefers-reduced-motion: reduce) {
  .aq-dash-stagger > * { animation: none; }
}

/* Hero — danger/warn incident variants of the promoted card. */
.aq-hero-card.is-danger { border-color: var(--aq-danger-line); }
.aq-hero-card.is-danger::before {
  background: radial-gradient(ellipse 70% 110% at 100% 0%, var(--aq-danger-soft), transparent 60%);
}
.aq-hero-card.is-warn { border-color: var(--aq-warn-line); }
.aq-hero-card.is-warn::before {
  background: radial-gradient(ellipse 70% 110% at 100% 0%, var(--aq-warn-soft), transparent 60%);
}
@keyframes aqDotBreathe {
  0%, 100% { box-shadow: 0 0 8px var(--aq-danger); }
  50%      { box-shadow: 0 0 18px var(--aq-danger); }
}
.aq-hero-dot.is-breathing { animation: aqDotBreathe 2.2s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) {
  .aq-hero-dot.is-breathing { animation: none; }
}

/* Hero CTA press + focus (Apple-style: lift on hover, sink on press). */
.aq-hero-card-cta {
  transition: opacity var(--aq-d-1) var(--aq-ease), transform var(--aq-d-1) var(--aq-ease);
}
.aq-hero-card-cta:hover { transform: translateY(-1px); }
.aq-hero-card-cta:active { transform: scale(0.97); opacity: 1; }
.aq-hero-card-cta:focus-visible { outline: 2px solid var(--aq-accent-line); outline-offset: 2px; }
.aq-hero-card-cta.is-ghost {
  background: transparent;
  border: 1px solid var(--aq-line-strong);
  color: var(--aq-text-dim);
  font-weight: 500;
}
.aq-hero-card-cta.is-ghost:hover { color: var(--aq-text); opacity: 1; }

/* Chips — offline-screen pills inside the incident hero. */
.aq-chip-row { position: relative; display: flex; gap: 6px; margin-top: 14px; flex-wrap: wrap; }
.aq-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 9px; font-size: 11px; font-weight: 500; border-radius: 99px;
  border: 1px solid var(--aq-line-strong); color: var(--aq-text-dim);
  background: rgba(255,255,255,0.02); cursor: pointer;
  transition: border-color var(--aq-d-1) var(--aq-ease),
              color var(--aq-d-1) var(--aq-ease),
              transform var(--aq-d-1) var(--aq-ease);
}
.aq-chip:hover { border-color: var(--aq-danger-line); color: var(--aq-text); transform: translateY(-1px); }
.aq-chip:active { transform: none; }
.aq-chip .aq-chip-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--aq-danger); flex-shrink: 0; }
.aq-chip .aq-chip-time { color: var(--aq-text-faint); font-variant-numeric: tabular-nums; }

/* KPI strip extensions — sparkline + tabular numerals. */
.aq-stat-value { font-variant-numeric: tabular-nums; }
.aq-stat-spark { margin-top: 10px; height: 22px; }
.aq-stat-spark svg { width: 100%; height: 22px; display: block; }
.aq-stat-frac { font-size: 16px; color: var(--aq-text-faint); font-weight: 500; }

/* Attention inbox extensions on .aq-inbox-* (rows/icons already exist). */
.aq-inbox-row.is-danger .aq-inbox-icon { background: var(--aq-danger-soft); color: var(--aq-danger); }
.aq-inbox-row.is-warn   .aq-inbox-icon { background: var(--aq-warn-soft);   color: var(--aq-warn); }
.aq-inbox-row.is-info   .aq-inbox-icon { background: var(--aq-accent-soft); color: var(--aq-accent); }
.aq-inbox-act {
  flex-shrink: 0; font-size: 11.5px; font-weight: 500; color: var(--aq-text-dim);
  border: 1px solid var(--aq-line-strong); border-radius: 6px; padding: 3px 10px;
  opacity: 0;
  transition: opacity var(--aq-d-1) var(--aq-ease), color var(--aq-d-1) var(--aq-ease);
}
.aq-inbox-row:hover .aq-inbox-act,
.aq-inbox-row:focus-within .aq-inbox-act { opacity: 1; }
.aq-inbox-act:hover { color: var(--aq-text); }
.aq-inbox-zero { padding: 30px 16px; text-align: center; }
.aq-inbox-zero .aq-zero-icon {
  width: 40px; height: 40px; border-radius: 10px;
  background: var(--aq-success-soft); color: var(--aq-success);
  display: inline-grid; place-items: center; margin-bottom: 10px;
}
.aq-inbox-zero .aq-zero-icon svg { width: 18px; height: 18px; stroke-width: 1.75; }
.aq-inbox-zero h4 { margin: 0 0 3px; font-size: 13px; font-weight: 500; color: var(--aq-text); }
.aq-inbox-zero p { margin: 0; font-size: 12px; color: var(--aq-text-faint); }
.aq-count-pill {
  font-size: 10.5px; font-weight: 600; padding: 1px 7px; border-radius: 99px;
  background: var(--aq-warn-soft); color: var(--aq-warn);
  border: 1px solid var(--aq-warn-line); font-variant-numeric: tabular-nums;
}

/* Fleet strip — miniature display bezels (compact cousin of .ds-tile). */
.aq-fleet { display: grid; grid-template-columns: repeat(5, 1fr); gap: 14px; }
@media (max-width: 1100px) { .aq-fleet { grid-template-columns: repeat(3, 1fr); } }
.aq-fleet-tile { cursor: pointer; min-width: 0; }
.aq-fleet-frame {
  aspect-ratio: 16/9; border-radius: 8px; padding: 5px;
  background: #0a0b0d; position: relative; overflow: hidden;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.07), 0 8px 22px rgba(0,0,0,0.45);
  transition: transform var(--aq-d-2) var(--aq-ease), box-shadow var(--aq-d-2) var(--aq-ease);
}
.aq-fleet-tile:hover .aq-fleet-frame {
  transform: translateY(-2px);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.09),
    0 0 0 3px var(--aq-accent-soft), 0 0 20px 4px var(--aq-accent-glow),
    0 12px 28px rgba(0,0,0,0.5);
}
.aq-fleet-tile:focus-visible { outline: none; }
.aq-fleet-tile:focus-visible .aq-fleet-frame {
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.09),
    0 0 0 3px var(--aq-accent-soft), 0 0 20px 4px var(--aq-accent-glow);
}
.aq-fleet-screen { position: absolute; inset: 5px; border-radius: 4px; overflow: hidden; }
.aq-fleet-screen img { width: 100%; height: 100%; object-fit: cover; display: block; }
.aq-fleet-tile.is-offline .aq-fleet-screen img,
.aq-fleet-tile.is-idle .aq-fleet-screen img,
.aq-fleet-tile.is-offline .aq-fleet-ph,
.aq-fleet-tile.is-idle .aq-fleet-ph {
  filter: brightness(0.38) saturate(0.4) blur(0.5px);
}
.aq-fleet-ph { position: absolute; inset: 0; }
.aq-fleet-status {
  position: absolute; inset: 0; display: grid; place-items: center;
  font-size: 10px; font-weight: 500; letter-spacing: 0.04em; text-transform: uppercase;
  color: rgba(255,255,255,0.75); text-shadow: 0 1px 4px rgba(0,0,0,0.6);
}
.aq-fleet-led {
  position: absolute; bottom: 1px; left: 50%; transform: translateX(-50%);
  width: 4px; height: 4px; border-radius: 50%; background: var(--aq-text-faint);
}
.aq-fleet-tile.is-online  .aq-fleet-led { background: var(--aq-success); box-shadow: 0 0 5px var(--aq-success); }
.aq-fleet-tile.is-offline .aq-fleet-led { background: var(--aq-danger);  box-shadow: 0 0 5px var(--aq-danger); }
.aq-fleet-tile.is-idle    .aq-fleet-led { background: var(--aq-warn); }
.aq-fleet-caption { display: flex; align-items: center; gap: 6px; margin-top: 7px; font-size: 11px; min-width: 0; }
.aq-fleet-caption .aq-fleet-cdot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; background: var(--aq-text-faint); }
.aq-fleet-tile.is-online  .aq-fleet-cdot { background: var(--aq-success); box-shadow: 0 0 5px var(--aq-success); }
.aq-fleet-tile.is-offline .aq-fleet-cdot { background: var(--aq-danger); }
.aq-fleet-tile.is-idle    .aq-fleet-cdot { background: var(--aq-warn); }
.aq-fleet-name {
  color: var(--aq-text-muted); font-weight: 500;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.aq-fleet-state { margin-left: auto; color: var(--aq-text-faint); flex-shrink: 0; font-variant-numeric: tabular-nums; }

/* Activity — humanized sentences. */
.aq-activity-row em { font-style: normal; color: var(--aq-text-muted); }
.aq-avatar-mini.is-sys { background: var(--aq-surface-3); color: var(--aq-text-faint); }

/* Keyboard completeness (2026-06-12): every dashboard interactive gets
   the same focus treatment as the hero CTA. Fleet tiles keep their own
   frame-glow focus style defined above. */
.aq-chip:focus-visible,
.aq-inbox-row:focus-visible,
.aq-section-link:focus-visible,
.aq-stat-sub a:focus-visible,
.aq-list-row:focus-visible {
  outline: 2px solid var(--aq-accent-line);
  outline-offset: 2px;
  border-radius: 6px;
}
