/* ==========================================================================
   Alembic — Core Stylesheet
   Design tokens, reset, buttons, layout, sidebar, topbar, dashboard,
   modals, mobile, loading, animations, auth, user menu, org switcher
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Design Tokens (Custom Properties)
   -------------------------------------------------------------------------- */
:root {
  /* Colors — Primary (blue scale) */
  --color-blue-700: #1A6FC2;
  --color-blue-600: #1F7AD4;
  --color-blue-500: #4A9BE8;
  --color-blue-400: #7AB6EF;
  --color-blue-200: #B8D7F5;
  --color-blue-100: #E8F2FC;
  --color-blue-50: #F4F8FD;
  --color-blue: var(--color-blue-600);
  --color-blue-bg: var(--color-blue-100);

  /* Colors — Neutrals (warm ink scale, hue ~45 tan undertone) */
  --color-ink: #16130E;
  --color-ink-900: #16130E;
  --color-ink-80: #3D3730;
  --color-ink-700: #3D3730;
  --color-ink-60: #655D53;
  --color-ink-600: #655D53;
  --color-ink-500: #7A7168;
  --color-ink-40: #9B9289;
  --color-ink-400: #9B9289;
  --color-ink-300: #B5ADA5;
  --color-ink-20: #CFC9C2;
  --color-ink-200: #CFC9C2;
  --color-ink-10: #E6E2DD;
  --color-ink-100: #E6E2DD;
  --color-ink-05: #F2F0ED;
  --color-ink-50: #F2F0ED;
  /* Aliases used by .al-btn / islands — must flip in dark (match --ink-*) */
  --color-ink-25: #CFC9C2;
  --color-ink-06: #F2F0ED;
  --color-ink-03: #F8F6F3;
  --color-warm-bg: #F5F2EB;
  --color-white: #FFFFFF;

  /* Colors — Semantic: Green */
  --color-green: #34A853;
  --color-green-800: #166534;
  --color-green-700: #1E7E34;
  --color-green-600: #34A853;
  --color-green-300: #86EFAC;
  --color-green-200: #BBF7D0;
  --color-green-bg: #E6F4EA;
  --color-green-100: #DCFCE7;
  --color-green-text: #1E7E34;
  --color-green-50: #F0FDF4;

  /* Colors — Primary Action (Alembic warm green, distinct from status green)
     Base is AA on white (5.42:1) and on the --color-action-100 tint (4.62:1).
     Hover is AAA (7.08:1) so the hover state is never less legible than rest.
     --color-action-light is the 3:1 companion for large fills, tints, gradient
     light stops, focus borders, and every dark-surface usage. */
  --color-action: #3B7558;
  --color-action-hover: #2F6249;
  --color-action-light: #569F7A;
  /* Derived, never restated — these track --color-action automatically so a
     palette change is one line instead of hundreds of rgba literals. */
  --color-action-soft: color-mix(in srgb, var(--color-action) 7%, transparent);
  --color-action-glow: color-mix(in srgb, var(--color-action) 17.5%, transparent);
  /* Numbered action scale — used by settings/billing/admin; must flip in dark */
  --color-action-50: #F0F7F3;
  --color-action-100: #E2F0E9;
  --color-action-400: var(--color-action-light);
  --color-action-700: #356B50;

  /* Colors — Semantic: Amber */
  --color-amber: #E8A830;
  --color-amber-600: #D97706;
  --color-amber-500: #F59E0B;
  --color-amber-400: #FBBF24;
  --color-amber-bg: #FEF3CD;
  --color-amber-text: #8B6914;
  --color-amber-100: #FEF3C7;
  --color-amber-50: #FFFBEB;

  /* Colors — Semantic: Red */
  --color-red: #E34234;
  --color-red-600: #DC2626;
  --color-red-500: #EF4444;
  --color-red-bg: #FCE8E6;
  --color-red-text: #C5221F;
  --color-red-100: #FEE2E2;
  --color-red-50: rgba(239, 68, 68, 0.08);

  /* Colors — Semantic: Purple */
  --color-purple: #7B61FF;
  --color-purple-600: #7C3AED;
  --color-purple-bg: #F0EDFF;
  --color-purple-text: #6B4EE6;
  --color-purple-100: #EDE9FE;
  --color-purple-50: #F5F3FF;

  /* Typography — Families */
  --font-display: 'Fraunces', Georgia, serif;
  --font-body: 'DM Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-mono: 'IBM Plex Mono', 'SF Mono', Menlo, monospace;

  /* Typography — Sizes */
  --text-display: 48px;
  --text-h1: 32px;
  --text-h2: 24px;
  --text-h3: 18px;
  --text-body: 16px;
  --text-body-medium: 16px;
  --text-base: 1rem;
  --text-small: 14px;
  --text-caption: 13px;
  --text-label: 11px;
  --text-mono: 13px;
  --text-mono-sm: 12px;

  /* Spacing (4px base) */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-8: 32px;
  --space-10: 40px;
  --space-12: 48px;
  --space-16: 64px;
  --space-20: 80px;

  /* Border Radii */
  --radius-sm: 6px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --radius-xl: 16px;
  --radius-2xl: 20px;
  --radius-full: 9999px;

  /* Shadows */
  --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.04);
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.06);
  --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08);
  --shadow-lg: 0 8px 40px rgba(0, 0, 0, 0.06);
  --shadow-xl: 0 16px 64px rgba(0, 0, 0, 0.08);

  /* Motion */
  --duration-fast: 100ms;
  --duration-normal: 150ms;
  --duration-slow: 250ms;
  --duration-enter: 200ms;
  --duration-exit: 150ms;
  --ease-default: ease;
  --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-out: cubic-bezier(0, 0, 0.2, 1);
  --ease-in: cubic-bezier(0.4, 0, 1, 1);
  --ease-decelerate: cubic-bezier(0.22, 1, 0.36, 1);

  /* Layout */
  --sidebar-width: 240px;
  --sidebar-collapsed-width: 56px;
  --topbar-height: 48px;
  --mobile-tab-height: 60px;
  /* Same clamp DistlrIsland / tokens.css use — pin reservation on #app. */
  --distlr-panel-w: clamp(480px, 40vw, 600px);
  --distlr-panel-w-review: 480px;

  /* Z-index scale */
  --z-mobile-tab: 80;
  --z-topbar: 90;
  --z-sidebar: 140;
  --z-chat-fab: 150;
  --z-chat-drawer: 160;
  /* Menus/popovers that must float above the sidebar + page chrome */
  --z-dropdown: 170;
  --z-modal: 200;

  /* Semantic Aliases — primary is now warm green (Dot Language) */
  --primary: var(--color-action);
  --primary-light: color-mix(in srgb, var(--color-action) 62%, transparent);
  --primary-dark: var(--color-action-hover);
  --primary-bg: var(--color-action-soft);
  --bg-body: var(--color-white);
  --bg-white: var(--color-white);
  --bg-sidebar: var(--color-warm-bg);
  --bg-sidebar-hover: var(--color-ink-05);
  --bg-terminal: var(--color-warm-bg);
  --bg-terminal-header: var(--color-ink-05);
  /* Terminal / syntax code surfaces — stay dark in both themes (do not invert) */
  --color-code-bg: #16130E;
  --color-code-text: #CFC9C2;
  --color-code-border: #3D3730;
  --color-code-muted: #9B9289;
  --bg-card: var(--color-white);
  --bg-muted: var(--color-warm-bg);
  --bg-tertiary: var(--color-ink-05);
  --bg-surface-raised: var(--color-warm-bg);
  --bg-surface-inset: var(--color-warm-bg);
  --text-primary: var(--color-ink-80);
  --text-secondary: var(--color-ink-60);
  /* A TEXT role, no longer an alias of the ink scale — because the two have
     different jobs. --color-ink-40 (#9B9289) is a perfectly good ink step and
     is still exactly right for --border-dark below, but as small text it
     measured 3.06:1 on white and 2.74:1 on --color-warm-bg: the second fails
     even the 3:1 large-text floor, and muted carries real copy (captions,
     hints, empty states, the "or" between choices).

     #746D67 is the MINIMUM value that clears 4.5:1 on both light surfaces
     (4.55:1 worst, on --color-warm-bg), and minimum is the point. Light
     --text-secondary is #655D53, so going darker for a comfortable margin
     walks muted straight into secondary and destroys the hierarchy the token
     exists to express — #6B6259 measured 5.34:1 and sat 0.014 luminance from
     secondary, passing the contrast maths by breaking the thing it labels.
     A border does not have to be readable; a sentence does. */
  --text-muted: #746D67;
  --text-inverse: var(--color-white);
  --border-light: var(--color-ink-10);
  --border-medium: var(--color-ink-20);
  --border-dark: var(--color-ink-40);
  --border-default: var(--color-ink-10);
  --status-success: var(--color-green);
  --status-success-bg: var(--color-green-bg);
  --status-success-dark: var(--color-green-text);
  --status-warning: var(--color-amber);
  --status-warning-bg: var(--color-amber-bg);
  --status-error: var(--color-red);
  --status-error-bg: var(--color-red-bg);
  --status-error-hover: var(--color-red-text);
  --status-info: var(--color-blue-600);
  --status-info-bg: var(--color-blue-100);
  --color-sonnet: var(--color-blue-600);
  --color-tools: var(--color-purple);
  --warning: var(--color-amber);

  /* Transition aliases */
  --transition-fast: var(--duration-fast) var(--ease-default);
  --transition-normal: var(--duration-normal) var(--ease-default);
  --transition-slow: var(--duration-slow) var(--ease-default);

  /* Preview type scale */
  --preview-title: 0.95rem;
  --preview-label: 0.72rem;
  --preview-body: 0.82rem;

  /* Component color tokens (bridge to design ref) */
  --alembic: #1F7AD4;
  --alembic-bright: #4A9BE8;
  --alembic-soft: #7AB6EF;
  --alembic-wash: #E8F2FC;
  --alembic-ghost: #F4F8FD;
  --complete: #3DAF6A;
  --complete-soft: #8AD4A8;
  --complete-wash: #EAF6EF;
  --warn: #C4952E;
  --warn-wash: #FDF5E3;
  --error: #D4534A;
  --error-wash: #FCEEED;
  --purple: #7B61FF;
  --purple-wash: #F3EEFF;
  --ink: #16130E;
  --ink-90: #251F19;
  --ink-80: #3D3730;
  --ink-70: #4A4239;
  --ink-60: #655D53;
  --ink-50: #7A7168;
  --ink-40: #9B9289;
  --ink-25: #CFC9C2;
  --ink-12: #E6E2DD;
  --ink-06: #F2F0ED;
  --ink-04: #FAF9F7;
  --ink-03: #F8F6F3;
  --ink-00: #FFFFFF;
  --spring: cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* --------------------------------------------------------------------------
   1b. Dark Mode — follows OS preference
   -------------------------------------------------------------------------- */
[data-theme="dark"] {
    /* Neutrals — inverted warm ink scale for dark mode */
    --color-ink: #ECE9E4;
    --color-ink-900: #ECE9E4;
    --color-ink-80: #CFC9C2;
    --color-ink-700: #CFC9C2;
    --color-ink-60: #9B9289;
    --color-ink-600: #9B9289;
    --color-ink-500: #7A7168;
    --color-ink-40: #655D53;
    --color-ink-400: #655D53;
    --color-ink-300: #4A4239;
    --color-ink-20: #302A24;
    --color-ink-200: #302A24;
    --color-ink-10: #231F1A;
    --color-ink-100: #231F1A;
    --color-ink-05: #1B1814;
    --color-ink-50: #1B1814;
    --color-ink-25: #4A4239;
    --color-ink-06: #231F1A;
    --color-ink-03: #1B1814;
    --color-warm-bg: #151210;
    --color-white: #1F1C18;

    /* Blues — slightly brighter for dark bg contrast */
    --color-blue-700: #4A9BE8;
    --color-blue-600: #1F7AD4;
    --color-blue-500: #1A6FC2;
    --color-blue-400: #1A5FA6;
    --color-blue-200: #172A42;
    --color-blue-100: #141E2E;
    --color-blue-50: #111820;
    --color-blue: var(--color-blue-700);
    --color-blue-bg: var(--color-blue-100);

    /* Action scale — inverted for dark. The base green lightens (the light-mode
       #3B7558 is only 3.12:1 on #201C16); hover lightens further so hover is
       still the more legible state. Every tint below is a color-mix off the
       (now light) base, so they can never drift from it. */
    --color-action: #569F7A;
    --color-action-hover: #6AAF8A;
    --color-action-light: #6AAF8A;
    /* Soft fills for settings/billing chips in dark */
    --color-action-soft: color-mix(in srgb, var(--color-action) 14%, transparent);
    --color-action-glow: color-mix(in srgb, var(--color-action) 28%, transparent);
    --color-action-50: color-mix(in srgb, var(--color-action) 12%, transparent);
    --color-action-100: color-mix(in srgb, var(--color-action) 18%, transparent);
    --color-action-400: var(--color-action-light);
    --color-action-700: #86C4A0;

    /* Semantic colors — dark-adapted */
    --color-green-bg: #0F2618;
    --color-green-text: #86EFAC;
    --color-green-100: #0F2618;
    --color-green-50: #0C1F14;
    --color-amber-bg: #2A2008;
    --color-amber-text: #FBBF24;
    --color-amber-100: #2A2008;
    --color-amber-50: #1F1806;
    --color-red-bg: #2A1215;
    --color-red-text: #FCA5A5;
    --color-red-100: #2A1215;
    --color-red-50: rgba(239, 68, 68, 0.1);
    --color-purple-bg: #1E1635;
    --color-purple-100: #1E1635;
    --color-purple-50: #181228;

    /* Semantic aliases — dark overrides.
       Elevation ramp (2026-07-11 focus-card contract §2, global per ruling):
       page #17140F → ambient card #201C16 → raised surface #272219.
       Elevation = lightness on dark; wells go lighter than their card. */
    --bg-body: #17140F;
    --bg-white: #1F1C18;
    --bg-sidebar: #19160F;
    --bg-sidebar-hover: #231F1A;
    --bg-terminal: #19160F;
    --bg-terminal-header: #231F1A;
    --bg-card: #201C16;
    --bg-muted: #19160F;
    --bg-tertiary: #1B1814;
    --bg-surface-raised: #272219;
    --bg-surface-inset: #19160F;
    --text-primary: #ECE9E4;
    --text-secondary: #B5ADA5;
    /* AA on every dark surface, not just the page.
       #7A7168 measured 3.84:1 on --bg-body and 3.30:1 on
       --bg-surface-raised — below the 4.5:1 small-text floor everywhere, and
       worst exactly where the elevation ramp puts the most text (cards and
       raised wells). Muted carries real copy: captions, format hints, the
       "or" between choices, every empty-state line on the onboarding canvas.
       #948B81 is the first value that clears 4.5:1 against all six dark
       surfaces (4.72:1 worst case, on --bg-surface-raised) while staying a
       clear step below --text-secondary, which is the whole point of muted. */
    --text-muted: #948B81;
    --text-inverse: #16130E;
    --border-light: #231F1A;
    --border-medium: #302A24;
    --border-dark: #4A4239;
    --border-default: #231F1A;

    /* Shadows — stronger for dark bg */
    --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.2);
    --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.3);
    --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.3);
    --shadow-lg: 0 8px 40px rgba(0, 0, 0, 0.3);
    --shadow-xl: 0 16px 64px rgba(0, 0, 0, 0.4);

    /* Component tokens — dark-adapted */
    --alembic-wash: #141E2E;
    --alembic-ghost: #111820;
    --complete-wash: #0F2618;
    --warn-wash: #2A2008;
    --error-wash: #2A1215;
    --purple-wash: #1E1635;
    --ink: #ECE9E4;
    --ink-90: #F5F2ED;
    --ink-80: #CFC9C2;
    --ink-70: #CFC9C2;
    --ink-60: #9B9289;
    --ink-50: #9B9289;
    --ink-40: #655D53;
    --ink-25: #4A4239;
    --ink-12: #2B2620;
    --ink-06: #231F1A;
    --ink-04: #1A1814;
    --ink-03: #1B1814;
    --ink-00: #0F0D0A;
}

/* Dark mode — element overrides */
[data-theme="dark"] ::-webkit-scrollbar-track { background: #151210; }
[data-theme="dark"] ::-webkit-scrollbar-thumb { background: #302A24; }
[data-theme="dark"] ::-webkit-scrollbar-thumb:hover { background: #4A4239; }
[data-theme="dark"] input,
[data-theme="dark"] textarea,
[data-theme="dark"] select { color-scheme: dark; }

/* Soften stat cards and outlined containers in dark mode.
   Borders that are fine in light mode become harsh outlines on dark bg. */
[data-theme="dark"] .stat-card {
  border-color: var(--color-ink-100);
  box-shadow: none;
}

/* DISTLR Intelligence card + triage card borders */
[data-theme="dark"] .triage-card,
[data-theme="dark"] .distlr-notif-card {
  border-color: var(--color-ink-100) !important;
}

/* Document table readability */
[data-theme="dark"] .doc-table th {
  color: var(--color-ink-400);
}
[data-theme="dark"] .doc-row:hover {
  background: var(--bg-surface-raised);
}

/* Settings cards */
[data-theme="dark"] .settings-card {
  border-color: var(--color-ink-100);
  background: var(--bg-card);
}

/* Search input */
[data-theme="dark"] .search-input {
  background: var(--bg-surface-inset);
  border-color: var(--color-ink-100);
  color: var(--text-primary);
}

/* Select dropdowns */
[data-theme="dark"] .al-select,
[data-theme="dark"] .al-input,
[data-theme="dark"] .al-textarea {
  background: var(--bg-surface-inset);
  border-color: var(--color-ink-100);
  color: var(--text-primary);
}

/* New Space button */
[data-theme="dark"] .sidebar-new-space-btn {
  border-color: #302A24;
  color: #B5ADA5;
}
[data-theme="dark"] .sidebar-new-space-btn:hover {
  border-color: #4A4239;
  color: #ECE9E4;
}


/* --------------------------------------------------------------------------
   2. Reset & Base
   -------------------------------------------------------------------------- */
*, *::before, *::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html {
  font-size: 16px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  scroll-behavior: smooth;
}

body {
  font-family: var(--font-body);
  background: var(--bg-body);
  color: var(--text-primary);
  line-height: 1.6;
  min-height: 100vh;
}

a {
  color: inherit;
  text-decoration: none;
}

button {
  font-family: inherit;
  cursor: pointer;
  border: none;
  background: none;
}

input, select, textarea {
  font-family: inherit;
  font-size: inherit;
}

img, svg {
  display: block;
  max-width: 100%;
}

ul, ol {
  list-style: none;
}

.hidden {
  display: none !important;
}

:focus-visible {
  outline: 2px solid var(--color-action);
  outline-offset: 2px;
}

button:focus-visible,
a:focus-visible,
[role="button"]:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: 2px solid var(--color-action);
  outline-offset: 2px;
}


/* --------------------------------------------------------------------------
   3. Buttons
   -------------------------------------------------------------------------- */
/* ═══════════════════════════════════════════════════════════════════════
   BUTTONS — Dot Language Design System
   Warm green primary, scale hover, inner shadow depth, spring physics.
   ═══════════════════════════════════════════════════════════════════════ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  height: 36px;
  padding: 0 1.15rem;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: background 350ms var(--ease-out, ease),
              border-color 350ms var(--ease-out, ease),
              box-shadow 350ms var(--ease-out, ease),
              color 200ms var(--ease-out, ease),
              transform 150ms var(--ease-out, ease);
  white-space: nowrap;
  position: relative;
  overflow: hidden;
  -webkit-user-select: none;
  user-select: none;
}
.btn:active:not(:disabled) { transform: scale(0.97); }

/* ── Primary — warm green, inner shadow depth ── */
.btn-primary {
  background: var(--color-action);
  color: var(--color-white);
  border-color: var(--color-action-hover);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.15), 0 1px 2px rgba(0,0,0,0.06);
}
.btn-primary:hover {
  background: var(--color-action-hover);
  transform: scale(1.02);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.2), 0 3px 10px var(--color-action-glow);
}
.btn-primary:active:not(:disabled) {
  transform: scale(0.97);
  box-shadow: inset 0 2px 4px rgba(0,0,0,0.15);
}

/* ── Secondary — warm border, white fill ── */
.btn-secondary {
  background: var(--color-white);
  color: var(--color-ink-700, var(--text-secondary, #3D3730));
  border-color: var(--color-ink-200, var(--border-light, #CFC9C2));
  box-shadow: 0 1px 2px rgba(0,0,0,0.04);
}
.btn-secondary:hover {
  border-color: var(--color-ink-400, var(--border-medium, #9B9289));
  background: var(--color-ink-50, #F2F0ED);
  transform: scale(1.02);
  box-shadow: 0 2px 6px rgba(0,0,0,0.06);
}
.btn-secondary:active:not(:disabled) {
  transform: scale(0.97);
  box-shadow: inset 0 1px 3px rgba(0,0,0,0.08);
}

/* ── Danger — restrained red, border only at rest ── */
.btn-danger {
  background: transparent;
  color: var(--color-red-text, #B5453C);
  border-color: rgba(181,69,60,0.2);
  transition: all 350ms var(--ease-out, ease);
}
.btn-danger:hover {
  background: rgba(181,69,60,0.06);
  border-color: rgba(181,69,60,0.35);
  transform: scale(1.02);
}
.btn-danger:active:not(:disabled) {
  transform: scale(0.97);
  background: rgba(181,69,60,0.1);
}
.btn-danger:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  transform: none !important;
  box-shadow: none;
}
.btn-danger:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px rgba(181, 69, 60, 0.25);
}

/* ── Ghost — minimal, text-only feel ── */
.btn-ghost {
  background: transparent;
  color: var(--color-ink-600, var(--text-secondary, #655D53));
}
.btn-ghost:hover {
  background: var(--color-ink-50, #F2F0ED);
  color: var(--color-ink-900, var(--text-primary, #16130E));
}

/* Upload button with icon — arrow bounce on hover */
#upload-trigger-btn:hover svg polyline,
#upload-trigger-btn:hover svg line {
  animation: upload-arrow-micro 0.6s ease-in-out;
}

.btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  pointer-events: none;
}

/* ── Button loading state — spinner before text ──────────────────────── */
.btn--loading {
  pointer-events: none;
  opacity: 0.8;
}
.btn--loading::before {
  content: '';
  display: inline-block;
  width: 14px;
  height: 14px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: var(--radius-full);
  animation: btn-spin 700ms linear infinite;
  flex-shrink: 0;
}
@keyframes btn-spin {
  to { transform: rotate(360deg); }
}

/* ── Button success flash — green confirm after save ─────────────────── */
.btn--success {
  background: var(--color-action) !important;
  color: var(--color-white) !important;
  border-color: var(--color-action-hover) !important;
  pointer-events: none;
  animation: btn-success-settle 1200ms var(--ease-out, cubic-bezier(0, 0, 0.2, 1)) both;
}
@keyframes btn-success-settle {
  0% { transform: scale(1.04); }
  30% { transform: scale(1); }
  100% { transform: scale(1); opacity: 0.85; }
}

/* ── Copy button pop ─────────────────────────────────────────────────── */
.btn--copied {
  animation: btn-copy-pop 400ms var(--spring, cubic-bezier(0.34, 1.56, 0.64, 1)) both;
}
@keyframes btn-copy-pop {
  0% { transform: scale(0.85); }
  50% { transform: scale(1.08); }
  100% { transform: scale(1); }
}

.btn-sm {
  height: 30px;
  padding: 0 0.65rem;
  font-size: 12px;
}

.btn-icon {
  width: 36px;
  height: 36px;
  padding: 0;
  border-radius: var(--radius-sm);
  justify-content: center;
}
.btn-icon.btn-sm {
  width: 30px;
  height: 30px;
}

/* ── Text button — link-style, no chrome ── */
.btn-text {
  background: none;
  border: none;
  padding: 0;
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 500;
  color: var(--color-ink-600, #655D53);
  cursor: pointer;
  transition: color 200ms var(--ease-out, ease);
}
.btn-text:hover { color: var(--color-ink-900, #16130E); }
.btn-text.danger:hover { color: var(--color-red-text, #B5453C); }

/* ═══════════════════════════════════════════════════════════════════
   DOT LANGUAGE BUTTONS (.al-btn)
   Canvas-based dot morph with spring physics hover animation.
   Requires: dot-morph.js, dot-engine.js, dot-button-states.js
   ═══════════════════════════════════════════════════════════════════ */

.al-btn {
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 600;
  height: 40px;
  padding: 0 20px 0 12px;
  border: 1px solid var(--color-ink-10);
  border-radius: var(--radius-md, 8px);
  cursor: pointer;
  background: var(--color-white);
  color: var(--color-ink-80, #3D3730);
  line-height: 1;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2, 8px);
  position: relative;
  overflow: hidden;
  transition: background 800ms var(--ease-out, ease),
              border-color 800ms var(--ease-out, ease),
              box-shadow 800ms var(--ease-out, ease),
              transform 350ms var(--ease-out, ease);
  -webkit-user-select: none;
  user-select: none;
}
.al-btn:active:not(:disabled) { transform: scale(0.97); }
.al-btn:disabled { opacity: 0.35; cursor: not-allowed; }
.al-btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--color-action-glow);
}
.al-btn--sm {
  height: 32px;
  padding: 0 14px 0 10px;
  font-size: 13px;
}

.al-btn canvas.al-dot {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
}

/* Primary — green border accent, soft hover bg */
.al-btn--primary {
  border-width: 1.5px;
  border-color: var(--color-action);
  color: var(--color-ink-80, #3D3730);
  font-weight: 700;
}
.al-btn--primary:hover {
  background: var(--color-action-soft);
  box-shadow: 0 0 0 3px var(--color-action-glow);
}

/* Secondary — subtle border, ink hover */
.al-btn--secondary:hover {
  border-color: var(--color-ink-25, var(--ink-25, #CFC9C2));
  background: var(--color-ink-03, var(--ink-03, #F8F6F3));
}

/* Ghost — no border, transparent */
/* Icon-only — the dot IS the icon (rest: dot; hover: the morph). No label
   span, so the button squares off around the canvas. 28px keeps the WCAG
   2.5.8 ≥24px target: the house "no .al-btn under 24px" rule is about the
   hit target, which this preserves, not the glyph inside it. aria-label is
   required at the type level (AlButtonPropsStrict). */
.al-btn--icon-only {
  height: 32px;
  width: 32px;
  padding: 0;
  justify-content: center;
  gap: 0;
}

.al-btn-confirm {
  display: inline-flex;
  align-items: center;
  position: relative;
}

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

.al-btn--ghost {
  border-color: transparent;
  background: transparent;
  color: var(--color-ink-60, #655D53);
}
.al-btn--ghost:hover {
  background: var(--color-ink-06, var(--ink-06, #F2F0ED));
  color: var(--color-ink-80, #3D3730);
}

/* Danger — border goes red on hover */
.al-btn--danger { color: var(--color-ink-60, #655D53); }
.al-btn--danger:hover {
  color: #B5453C;
  border-color: rgba(181,69,60,0.25);
  background: rgba(181,69,60,0.03);
}

/* --- Inputs --- */
.input {
  font-family: var(--font-body);
  font-size: var(--text-small);
  padding: 10px 14px;
  border: 1px solid var(--color-ink-10);
  border-radius: var(--radius-md);
  background: var(--color-white);
  color: var(--color-ink);
  transition: border-color var(--duration-normal) var(--ease-default), box-shadow var(--duration-normal) var(--ease-default);
  width: 100%;
}
.input::placeholder { color: var(--color-ink-40); }
.input:focus {
  outline: none;
  border-color: var(--color-action);
  box-shadow: 0 0 0 3px var(--color-action-soft);
}

.input.error,
.input:invalid:not(:placeholder-shown) {
  border-color: var(--color-red);
  box-shadow: 0 0 0 3px rgba(227, 66, 52, 0.08);
}

.input.error:focus {
  border-color: var(--color-red);
  box-shadow: 0 0 0 3px rgba(227, 66, 52, 0.12);
}

.input-shake {
  animation: inputShake 0.4s ease;
}

@keyframes inputShake {
  0%, 100% { transform: translateX(0); }
  15% { transform: translateX(-6px); }
  30% { transform: translateX(5px); }
  45% { transform: translateX(-4px); }
  60% { transform: translateX(3px); }
  75% { transform: translateX(-2px); }
}

.section-label {
  font-family: var(--font-body);
  font-size: var(--text-label);
  font-weight: 600;
  color: var(--color-ink-40);
  text-transform: uppercase;
  letter-spacing: 2px;
  margin-bottom: var(--space-3);
}

.page-title {
  font-family: var(--font-display);
  font-size: var(--text-h1);
  font-weight: 500;
  color: var(--color-ink);
  line-height: 1.2;
}

.inbox-answer-input {
  width: 140px;
  font-size: var(--text-small);
  padding: 6px 10px;
  border: 1px solid var(--color-ink-10);
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  background: var(--color-white);
  color: var(--color-ink);
}
.inbox-answer-input:focus {
  outline: none;
  border-color: var(--color-action);
  box-shadow: 0 0 0 3px var(--color-action-soft);
}

.settings-empty-text {
  color: var(--color-ink-40);
  font-size: var(--text-small);
}

.pattern-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 0;
  border-bottom: 1px solid var(--color-ink-10);
  font-size: var(--text-small);
}
.pattern-row-text { flex: 1; }
.pattern-row-meta {
  color: var(--color-ink-40);
  white-space: nowrap;
}

.hint-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 0;
  font-size: var(--text-small);
}
.hint-row-text { flex: 1; }

.hint-input-row {
  display: flex;
  gap: 8px;
  margin-top: 8px;
}
.hint-input-row input { flex: 1; }

.history-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 0;
  border-bottom: 1px solid var(--color-ink-10);
  font-size: var(--text-small);
}
.history-version { font-weight: 600; }
.history-reason { flex: 1; color: var(--color-ink-60); }
.history-date { color: var(--color-ink-40); }

.preview-section-label {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-ink-60);
  margin-bottom: 8px;
}
.preview-section-label + .preview-section-label { margin-top: 12px; }

.preview-description {
  color: var(--color-ink-60);
  margin-bottom: 12px;
  font-size: var(--text-small);
}

.upload-file-size {
  color: var(--color-ink-40);
  font-size: var(--text-caption);
}

.api-keys-container { margin-bottom: var(--space-4); }

.monospace { font-family: var(--font-mono); }

.cell-copy-flash {
  background: var(--color-green-bg);
  transition: background 0.4s ease;
}


/* --------------------------------------------------------------------------
   4. Sidebar
   -------------------------------------------------------------------------- */
.sidebar {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  width: var(--sidebar-width);
  background: var(--bg-sidebar);
  color: var(--text-primary);
  border-right: 1px solid var(--border-light);
  display: flex;
  flex-direction: column;
  z-index: var(--z-sidebar);
  transition: width var(--duration-slow) var(--ease-out);
  overflow: hidden;
}

.sidebar.collapsed {
  width: var(--sidebar-collapsed-width);
}

/* SPA auth/org gate hold — shell-shaped so cold loads match AppLayout chrome */
.spa-auth-pending {
  position: fixed;
  inset: 0;
  display: flex;
  background: var(--color-warm-bg);
  z-index: var(--z-sidebar, 100);
}
.spa-auth-pending__sidebar {
  width: var(--sidebar-width);
  flex-shrink: 0;
  background: var(--bg-sidebar);
  border-right: 1px solid var(--border-light);
}
.spa-auth-pending__main {
  flex: 1;
  background: var(--color-warm-bg);
}
@media (max-width: 768px) {
  .spa-auth-pending__sidebar { display: none; }
}

.sidebar.collapsed .sidebar-label,
.sidebar.collapsed .sidebar-section-title,
.sidebar.collapsed .sidebar-section-label,
.sidebar.collapsed .sidebar-logo-text,
.sidebar.collapsed .sidebar-badge,
.sidebar.collapsed .sidebar-space-name {
  display: none;
}

.sidebar.collapsed .sidebar-new-space-btn {
  padding: 0.5rem;
  justify-content: center;
  position: relative;
}


/* Collapsed rail: the icon row stacks vertically (as the old stacked nav).
   Tight padding — 44px targets + 2x4px fits the 56px rail. */
.sidebar.collapsed .sidebar-nav {
  flex-direction: column;
  gap: 2px;
  padding: var(--space-1);
}

.sidebar.collapsed .sidebar-header {
  justify-content: center;
}

.sidebar.collapsed .sidebar-collapse-btn svg {
  transform: rotate(180deg);
}

.sidebar.collapsed .sidebar-space-item {
  justify-content: center;
  padding: 0.5rem;
}

.sidebar.collapsed .sidebar-space-item:hover {
  padding-left: 0.5rem;
}


/* Tooltip layer — portal to body (RailTooltip.tsx) to avoid overflow clip.
   Labels the collapsed rail (space rows, search, controls) and the bottom
   icon nav. The rendering JS was lost with legacy app.js; revived in the
   sidebar island. */
.al-tooltip {
  position: fixed;
  background: var(--color-ink);
  color: var(--text-inverse);
  padding: 6px 12px;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 500;
  white-space: nowrap;
  pointer-events: none;
  z-index: 10000;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  opacity: 0;
  transition: opacity 0.15s var(--ease-out), transform 0.15s var(--ease-out);
}

/* Right of the rail: anchored at the trigger's vertical center */
.al-tooltip--right {
  transform: translate(-4px, -50%) translateX(10px);
}

/* Above the icon nav row: anchored at the trigger's horizontal center */
.al-tooltip--top {
  transform: translate(-50%, calc(-100% - 4px));
}

.al-tooltip.visible {
  opacity: 1;
}

.al-tooltip--right.visible {
  transform: translate(0, -50%) translateX(10px);
}

.al-tooltip--top.visible {
  transform: translate(-50%, calc(-100% - 8px));
}

/* Two-line body: space name + status meta (collapsed space rows) */
.sidebar-tip-body {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.sidebar-tip-meta {
  font-size: 11px;
  font-weight: 400;
  opacity: 0.75;
}

@media (prefers-reduced-motion: reduce) {
  .al-tooltip {
    transition: none;
  }
}

/* Sidebar usage meter — compact single line (track + count + Upgrade).
   Was a three-line ~80px block; now ~36px, returning space to the list. */
.sidebar-usage-bar {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  margin: 0 var(--space-3) var(--space-2);
  padding: var(--space-2) var(--space-3);
  background: var(--color-ink-05);
  border-radius: var(--radius-md);
  font-size: var(--text-mono-sm);
  cursor: pointer;
  transition: background var(--duration-normal) var(--ease-default);
}
/* Each meter line is the old single-row layout; paid plans stack two (docs +
   included AI), free plans show one. */
.sidebar-usage-bar .usage-line {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.sidebar-usage-bar .usage-line--ai .usage-track {
  height: 3px;
}
.sidebar-usage-bar .usage-line--ai .usage-count {
  color: var(--color-ink-40);
}
/* Included-AI fill is informational, not a health state — --status-info per
   the design rules ("informational status indicators stay blue"). */
.sidebar-usage-bar .usage-fill--ai {
  background: var(--status-info);
}
.sidebar-usage-bar:hover {
  background: var(--color-ink-10);
}
.sidebar-usage-bar:focus-visible {
  outline: 2px solid var(--color-action);
  outline-offset: 1px;
}
.sidebar-usage-bar .usage-track {
  flex: 1;
  min-width: 0;
  height: 4px;
  background: var(--color-ink-100);
  border-radius: var(--radius-full);
  overflow: hidden;
}
.sidebar-usage-bar .usage-fill {
  height: 100%;
  border-radius: var(--radius-full);
  transition: width var(--duration-slow) var(--ease-default), background var(--duration-slow) var(--ease-default);
}
.sidebar-usage-bar .usage-fill.level-ok { background: var(--color-green-600); }
.sidebar-usage-bar .usage-fill.level-warn { background: var(--color-amber); }
.sidebar-usage-bar .usage-fill.level-danger { background: var(--color-red); }
.sidebar-usage-bar .usage-count {
  color: var(--color-ink-60);
  font-weight: 500;
  white-space: nowrap;
}
.sidebar-usage-bar .usage-upgrade {
  font-size: var(--text-label);
  color: var(--color-action);
  font-weight: 600;
  white-space: nowrap;
}
.sidebar-usage-bar .usage-upgrade--urgent {
  color: var(--color-red-text);
  text-decoration: underline;
  text-underline-offset: 2px;
}
/* Collapsed rail: the usage bar becomes a level-colored pip, not nothing.
   `display: none` here meant a collapsed-sidebar user had zero ambient usage
   signal — the meter vanished exactly for the people who tucked the rail away.
   The pip inherits the root-level level-* class UsageBar mirrors from its fill,
   and the element keeps its click target + title summary. */
.sidebar.collapsed .sidebar-usage-bar {
  justify-content: center;
  align-items: center;
  padding: var(--space-2);
  margin: 0 var(--space-2) var(--space-2);
}
.sidebar.collapsed .sidebar-usage-bar .usage-line {
  display: none;
}
.sidebar.collapsed .sidebar-usage-bar::before {
  content: '';
  width: var(--space-2);
  height: var(--space-2);
  border-radius: var(--radius-full);
  background: var(--color-green-600);
}
.sidebar.collapsed .sidebar-usage-bar.level-warn::before { background: var(--color-amber); }
.sidebar.collapsed .sidebar-usage-bar.level-danger::before { background: var(--color-red); }

/* Post-checkout "activating" bridge — the webhook race window where the user
   has paid but org.plan hasn't flipped. Quiet by design: a gentle breath, no
   spinner, no Upgrade affordance (they just bought it). */
.sidebar-usage-bar.usage-bar-activating {
  justify-content: center;
  cursor: default;
}
.sidebar-usage-bar.usage-bar-activating .usage-count {
  color: var(--color-ink-60);
  animation: usage-activating-breath 2.4s var(--ease-default) infinite;
}
@keyframes usage-activating-breath {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.55; }
}
@media (prefers-reduced-motion: reduce) {
  .sidebar-usage-bar.usage-bar-activating .usage-count { animation: none; }
}

/* Mobile ambient usage: on phones the sidebar is an off-canvas drawer, so the
   meter lives behind a hamburger nobody opens. At >=80% usage the trigger
   itself carries a level-colored pip (AppTopBar renders .topbar-usage-pip), so
   the at-limit story is never a total ambush on a phone. */
.topbar-mobile-menu {
  position: relative;
}
.topbar-usage-pip {
  position: absolute;
  top: var(--space-1);
  right: var(--space-1);
  width: var(--space-2);
  height: var(--space-2);
  border-radius: var(--radius-full);
  background: var(--color-amber);
}
.topbar-usage-pip.level-danger {
  background: var(--color-red);
}

/* Sidebar Header / Logo — compact, aligned with the topbar (48px) */
.sidebar-header {
  display: flex;
  align-items: center;
  height: var(--topbar-height);
  padding: 0 1rem;
  flex-shrink: 0;
}

.sidebar-logo {
  display: flex;
  align-items: center;
  gap: 0.625rem;
}

.sidebar-logo-icon {
  flex-shrink: 0;
  color: var(--alembic);
}

/* Logo hover — dots scatter up, blocks bounce */
.sidebar-logo:hover .logo-dot-1 {
  animation: logo-hover-dot1 0.8s ease-in-out;
}
.sidebar-logo:hover .logo-dot-2 {
  animation: logo-hover-dot2 0.8s ease-in-out;
}
.sidebar-logo:hover .logo-dot-3 {
  animation: logo-hover-dot3 0.8s ease-in-out;
}
.sidebar-logo:hover .logo-block-1 {
  animation: logo-hover-block 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) 0.1s;
}
.sidebar-logo:hover .logo-block-2 {
  animation: logo-hover-block 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) 0.15s;
}
.sidebar-logo:hover .logo-block-3 {
  animation: logo-hover-block 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) 0.2s;
}
.sidebar-logo:hover .logo-block-4 {
  animation: logo-hover-block 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) 0.25s;
}

@keyframes logo-hover-dot1 {
  0% { cy: 10; opacity: 0.4; r: 5; }
  30% { cy: 4; opacity: 0.6; r: 5.5; }
  60% { cy: 16; opacity: 0.15; r: 3; }
  100% { cy: 10; opacity: 0.4; r: 5; }
}
@keyframes logo-hover-dot2 {
  0% { cy: 7; opacity: 0.3; r: 4.5; }
  25% { cy: 2; opacity: 0.55; r: 5; }
  55% { cy: 13; opacity: 0.12; r: 2.5; }
  100% { cy: 7; opacity: 0.3; r: 4.5; }
}
@keyframes logo-hover-dot3 {
  0% { cy: 13; opacity: 0.35; r: 3.5; }
  35% { cy: 6; opacity: 0.55; r: 4; }
  65% { cy: 18; opacity: 0.1; r: 2; }
  100% { cy: 13; opacity: 0.35; r: 3.5; }
}
@keyframes logo-hover-block {
  0% { transform: scaleY(1); }
  40% { transform: scaleY(0.7); }
  70% { transform: scaleY(1.08); }
  100% { transform: scaleY(1); }
}

.sidebar-logo-text {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 18px;
  letter-spacing: -0.5px;
  color: var(--color-ink);
}

/* New Space Button */
.sidebar-new-space-btn {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0 0.75rem 0.75rem;
  padding: 0.5rem 0.875rem;
  background: transparent;
  border: 1px dashed var(--border-medium);
  color: var(--text-secondary);
  border-radius: var(--radius-md);
  font-size: 0.85rem;
  font-weight: 600;
  transition: background var(--transition-fast);
  width: calc(100% - 1.5rem);
  /* The collapsed state is a <button> and the expanded drop zone is a <div>
     (it holds text inputs, which a button may not contain — see
     NewSpaceButton.tsx). The global `button` reset supplies these two; a div
     needs them stated, or the expanded zone loses its pointer and inherits
     the sidebar's box-sizing. */
  cursor: pointer;
  box-sizing: border-box;
}

.sidebar-new-space-btn:hover {
  background: var(--bg-sidebar-hover);
}

/* ── Sidebar Global Search — an in-flow row that becomes the field ─────────
   The trigger and the field occupy the same slot among the nav rows, and the
   results render beneath them in the sidebar's own flow. Sidebar hides the
   space list while they are showing.

   This replaced a right-anchored popover. Rendering in flow deletes the entire
   class of problems that version had: `.sidebar` sets `overflow: hidden` so an
   absolutely-positioned panel was clipped; escaping that needed position:fixed;
   fixed needed a measured anchor and a resize listener; and it needed to
   outrank --z-sidebar to be visible at all. None of that exists now. */
/* Explicit, because the sidebar has a standing rule — `.sidebar .ri-root {
   flex: 1 1 0% }` in sidebar.css, for a full-height island mount — that this
   row must never pick up. It grew to 209px and pushed the space list toward the
   bottom of the sidebar when it did. Stating the intent here means the row
   cannot inherit growth from any future ancestor rule either. */
.sidebar-search {
  flex: 0 0 auto;
  /* Bottom padding matches .sidebar-space-search, the find-a-space input that
     occupies the same role directly above the space list. Without it the group
     header ("WORKING") butts straight against the search row — the fix for the
     list sinking overshot into having no separation at all. */
  padding: 0 var(--space-2, 8px) var(--space-2, 8px);
}

/* Open but with nothing to show, the search is just its field — it must not
   reserve height for results that do not exist. So `is-open` (the field is
   showing) carries NO growth, and only `is-expanded` (there are results, a
   loader or an empty state) claims room. Splitting the two is the whole fix:
   one class meaning "open" did both jobs and left a tall empty box on screen
   from the moment you clicked Search.

   Expanded, it takes the room the space list gave up and its results scroll
   INSIDE that room — the same `flex: 1 + min-height: 0 + overflow-y` pattern
   .sidebar-section already uses for the space list, because it is the same
   job. min-height: 0 is the load-bearing part: without it a flex child refuses
   to shrink below its content, so the list would push the nav rows and the
   usage bar out of the sidebar instead of scrolling. */
.sidebar-search.is-expanded {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
}

.sidebar-search.is-expanded .sidebar-search-panel {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
}

.sidebar-search-trigger {
  display: flex;
  align-items: center;
  width: 100%;
  height: 28px;
  /* Left inset clears the magnifier the PANEL now draws, and is chosen so the
     label sits on the same x as the input's text (panel border 1 + this 34 =
     the input's 8 padding + 26 text inset). Aligned, the label and the
     placeholder do not slide past each other during the swap. */
  padding: 0 var(--space-2, 8px) 0 34px;
  border: none;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--text-secondary);
  cursor: pointer;
  /* --duration-normal, not --duration-fast: hover is the first half of one
     continuous ramp into the open field, and a 100ms hover against a 200ms
     morph reads as two different speeds on the same control. */
  transition: background var(--duration-normal) var(--ease-out),
              color var(--duration-normal) var(--ease-out);
}

/* The sidebar's OWN row-hover language, not a second one. This row sits among
   space rows, and `.sidebar-space-item:hover` lightens toward --bg-white while
   this lightened toward --color-ink-05 — which against the sidebar's #F5F2EB
   ground is a 3-value step, so hovering Search did visibly nothing while
   hovering the row beneath it did. Two hover treatments on adjacent rows is
   the fork worth closing; the fact that one of them was invisible is what made
   it noticeable. */
.sidebar-search-trigger:hover {
  background: color-mix(in srgb, var(--bg-white) 70%, transparent);
  color: var(--text-primary);
}

/* Held open: the trigger stays lit for as long as its popover is showing, so
   the button and the panel beside it read as one grouped thing rather than a
   panel floating next to an idle icon. Hover alone cannot do this — by the
   time the panel is up the pointer has left the button and is over the
   results, or the panel was opened from the keyboard and the pointer was never
   there at all.

   Keyed off aria-expanded rather than a second class, so the look cannot
   disagree with the state that is announced. It only ever matches on the rail:
   the expanded sidebar's trigger unmounts when the field opens, so its
   aria-expanded is never true there.

   ink-10, NOT the ink-05 that :hover uses, and the difference is not taste.
   The rail's ground is --bg-sidebar, which is #F5F2EB light and #19160F dark;
   ink-05 is #F2F0ED and #1B1814, so it lands 3 and 2 values away — measured,
   not estimated. That is survivable for a hover the pointer is sitting on and
   useless for a state that has to hold on its own while the eye is somewhere
   else. ink-10 is one rung further up the same scale and lands +15 and +10,
   which is also why it needs no per-theme override. */
.sidebar-search-trigger[aria-expanded='true'] {
  background: var(--color-ink-10);
  color: var(--text-primary);
}

.sidebar-search-trigger:focus-visible {
  outline: 2px solid var(--color-action);
  outline-offset: -2px;
}

.sidebar-search-trigger-label {
  flex: 1;
  min-width: 0;
  text-align: left;
  font-size: var(--text-label, 11px);
  font-weight: 500;
  line-height: 1.2;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Collapsed rail: icon only, centred. */
.collapsed .sidebar-search-trigger {
  justify-content: center;
  padding: 0;
}

/* The field replaces the trigger in the same slot. Height matches the trigger
   row so the rows above and below do not shift when it opens — .al-input's
   own min-height is sized for a form, not a 28px sidebar row. */
.sidebar-search-input.al-input {
  /* 28px to match .sidebar-search-trigger EXACTLY. When they differed by 2px
     the box could not morph on padding alone, and the row twitched. */
  min-height: 28px;
  height: 28px;
  /* Left padding clears the magnifier; right stays tight so the native
     type="search" clear affordance is not crowded. */
  padding: 0 var(--space-2, 8px) 0 26px;
  font-size: var(--text-caption);
}

/* Open state: field + results share one bounded surface, so a result reads as
   an answer to what is typed above it rather than as another sidebar row that
   happens to sit nearby. Inset (ink-05), not elevated — it belongs to the
   sidebar, it is not floating over it.

   ── This element is PERSISTENT, and that is the point ──────────────────────
   It used to mount when the field opened and unmount when it closed, with a
   fade to soften the cut. A cut is all a mount/unmount swap can be: the box
   went 28px → 48px, its radius 8 → 12, its background and border from nothing
   to something, all in one frame, and closing was not animated at all because
   an unmounting element has nowhere to animate to.

   So the panel is now rendered in every state and the trigger lives INSIDE it.
   Closed it wears no surface — transparent fill, transparent border, no
   padding — and is visually just the trigger row. Opening transitions those
   four properties, which is also what carries the height: 16px of the 20px
   change is the padding, and the row itself no longer changes at all (the
   input is 28px, matching the trigger). Closing runs the same transition
   backwards, for free.

   The border is transparent rather than absent when closed so the box does not
   jump 2px sideways at the moment the border appears.

   --ease-out, not --spring. The design system reserves spring for playful
   surfaces (drawers, canvas cards); a search field should feel precise, and an
   overshoot on something you are about to type into reads as jitter. */
.sidebar-search-panel {
  position: relative; /* positioning context for the persistent magnifier */
  background: var(--color-ink-05);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg, 10px);
  padding: var(--space-2, 8px);
  transition: background-color var(--duration-enter) var(--ease-out),
              border-color var(--duration-enter) var(--ease-out),
              border-radius var(--duration-enter) var(--ease-out),
              padding var(--duration-enter) var(--ease-out);
}

/* Closed. Scoped to `.sidebar-search:not(.is-open)` rather than written as an
   `.is-open` addition, so the rail's PORTALLED copy — which has no
   `.sidebar-search` ancestor at all — always gets the open look above without
   needing a rule of its own. */
.sidebar-search:not(.is-open) .sidebar-search-panel {
  background: transparent;
  border-color: transparent;
  border-radius: var(--radius-md);
  padding: 0;
}

/* The magnifier, rendered once by the panel and slid between the two states.

   Two separate icons — one in the button, one in the field — sat 9px apart
   horizontally and 6px vertically, so the swap jumped no matter how the rest
   was eased. This is the same element throughout, and absolute positioning is
   relative to the padding BOX, which the padding transition above does not
   move: these two offsets are the only thing carrying it, so the slide is
   exactly as long as the box morph and lands with it. */
.sidebar-search-icon {
  position: absolute;
  left: 16px;
  top: 14.5px;
  display: flex;
  align-items: center;
  color: var(--text-muted);
  pointer-events: none; /* clicks belong to the control underneath */
  transition: left var(--duration-enter) var(--ease-out),
              top var(--duration-enter) var(--ease-out),
              color var(--duration-enter) var(--ease-out);
}

.sidebar-search:not(.is-open) .sidebar-search-icon {
  /* 7px, not 8px, so the icon lands on the same x as the other sidebar rows'
     glyphs once the panel's 1px border is counted. */
  left: 7px;
  top: 6.5px;
  color: var(--text-secondary);
}

/* The two label lines above rows: the result count, and the "Names" /
   "Mentioned in" group headings. One rule, because they are one thing — a
   quiet uppercase label in the sidebar's own section vocabulary — and two
   copies of these seven declarations would drift the moment either is tuned.

   The count is aria-hidden in the markup: the listbox already announces its
   own size, and hearing it twice is worse than not seeing it once. */
.sidebar-search-count,
.sidebar-search-group {
  animation: sidebarItemIn var(--duration-enter) var(--ease-out) both;
  padding: var(--space-2, 8px) var(--space-2, 8px) 4px;
  font-size: var(--text-label, 11px);
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-muted);
}

/* Everything below the search slides down and out when search takes over.
   `.sidebar` already sets overflow: hidden, so the translate genuinely leaves
   the frame rather than spilling. max-height collapses the space it was
   holding, so the results can use it. */
/* This wrapper now IS the sidebar's growing element. `.sidebar-section` (the
   space list) carries `flex: 1` and used to be a direct child of
   .sidebar-inner, which is what absorbed the leftover height and kept the list
   directly under the search row. Wrapping it moved that growth into a plain
   block, so nothing claimed the slack and the list sank toward the bottom of
   the sidebar. Making the wrapper a flex column that grows restores it, and the
   list inside keeps its own `flex: 1` and its own scrolling.

   NOT max-height for the collapse: `max-height: 100vh` was a magic number that
   is wrong the moment the content is taller than the viewport, and it silently
   resolved to 0 in one renderer. `flex: 0 0 0` + `height: 0` collapses by the
   same mechanism that sizes it, with no number to be wrong. */
.sidebar-below-search {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden;
  /* Coming BACK: an entrance, so --duration-enter + --ease-out. */
  transition: opacity var(--duration-enter) var(--ease-out),
              transform var(--duration-enter) var(--ease-out);
}

.sidebar-below-search.is-pushed {
  /* Going AWAY: an exit, so --duration-exit + --ease-in. The design system
     splits these deliberately and one transition list cannot express both, so
     the exit timing lives on the state that leaves. */
  transition: opacity var(--duration-exit) var(--ease-in),
              transform var(--duration-exit) var(--ease-in);
  /* Size collapses immediately so the results get the room; the fade and slide
     are what the eye reads as "this moved out of the way". */
  flex: 0 0 0;
  height: 0;
  transform: translateY(24px);
  opacity: 0;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .sidebar-below-search { transition: none; }
}

/* Results: a sidebar list, not a floating card. No background, no shadow —
   they sit on the sidebar's own ground where the space list used to be. */
.sidebar-search-results {
  margin-top: var(--space-2, 8px);
  display: flex;
  flex-direction: column;
  /* No gap: consecutive rows are separated by a hairline (below), and a gap
     as well would read as two competing separators. */
  gap: 0;
  /* Scrolls within whatever height the sidebar leaves, rather than a magic
     viewport fraction: 55vh was arbitrary and still overflowed on short
     windows. Observed on preview — an unbounded list pushed the nav rows and
     the usage bar out of the frame. Scroll the results, never the sidebar. */
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}

/* The matched fragment. Two lines maximum — enough to see WHY it matched,
   not enough to turn a sidebar row into a paragraph. */
.sidebar-search-hit-snippet {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: var(--text-label, 11px);
  line-height: 1.4;
  color: var(--text-secondary);
}

.sidebar-search-hit-snippet mark {
  background: var(--color-action-soft);
  color: var(--text-primary);
  border-radius: 2px;
  padding: 0 1px;
}

.sidebar-search-hit {
  position: relative; /* anchors the hairline divider below */
  display: flex;
  flex-direction: column;
  gap: 1px;
  width: 100%;
  padding: var(--space-2, 8px);
  /* Reserved transparent border so the hovered/highlighted hairline appears
     without shifting the row by a pixel. */
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  text-align: left;
  cursor: pointer;
  transition: background var(--duration-normal) var(--ease-out),
              border-color var(--duration-fast) var(--ease-out),
              color var(--duration-fast) var(--ease-out);
  /* The sidebar's OWN row entrance, reused rather than reinvented — these rows
     occupy the slot the space list just vacated, so they should arrive the way
     space rows do. The stagger is tighter than .sidebar-space-item's 60ms and
     capped in the component, because that list mounts once while this one can
     re-resolve on any keystroke: a 25-row cascade at 60ms is a second and a
     half of movement nobody asked for. */
  animation: sidebarItemIn var(--duration-enter) var(--ease-out) both;
  animation-delay: var(--stagger, 0ms);
}

/* Hairline between consecutive results, drawn as an inset pseudo-element
   rather than a border-top. A real border would square off the row's rounded
   hover fill; insetting it by the panel's padding also makes it read as a
   divider between items instead of a box around each one. */
.sidebar-search-hit + .sidebar-search-hit::before {
  content: '';
  position: absolute;
  top: 0;
  left: var(--space-2, 8px);
  right: var(--space-2, 8px);
  height: 1px;
  background: var(--border-default);
}

/* Hover and keyboard highlight are the SAME treatment on purpose: both mean
   "this is what Enter opens", so showing them differently would be a lie.
   Matches .sidebar-space-item:hover — the rows these replace — rather than
   inventing a second hover language.

   NOT --color-ink-05: the panel behind these rows is already ink-05, so that
   fill would be invisible on it. */
.sidebar-search-hit:hover,
.sidebar-search-hit.highlighted {
  background: color-mix(in srgb, var(--bg-white) 70%, transparent);
  border-color: var(--border-default);
}

.sidebar-search-hit:hover .sidebar-search-hit-label,
.sidebar-search-hit.highlighted .sidebar-search-hit-label {
  color: var(--color-ink);
}

/* The divider would otherwise cut across the top of a hovered row's fill. */
.sidebar-search-hit:hover::before,
.sidebar-search-hit.highlighted::before,
.sidebar-search-hit:hover + .sidebar-search-hit::before,
.sidebar-search-hit.highlighted + .sidebar-search-hit::before {
  background: transparent;
}

@media (prefers-reduced-motion: reduce) {
  .sidebar-search-hit,
  .sidebar-search-group,
  .sidebar-search-count,
  .sidebar-search-trigger,
  .sidebar-search-icon,
  .sidebar-search-panel {
    animation: none;
    transition: none;
  }
}

/* ── Dark mode: bigger steps between surfaces ───────────────────────────────
   Measured in the browser, dark put every surface within ~8/255 of its
   neighbour: sidebar #151210, panel #1B1814 (+6), its border #231F1A (+8),
   and the highlighted row composited to ~#1E1B17 (+3 over the panel). The
   light palette has room to be subtle; the dark one does not, because the
   whole range is compressed into the bottom of the scale.

   Each override moves one rung up the SAME ink scale rather than inventing a
   colour, so the steps land near +13 and the treatment still follows the
   theme. */
[data-theme="dark"] .sidebar-search-panel {
  background: var(--color-ink-10);
  border-color: var(--border-medium);
}

[data-theme="dark"] .sidebar-search-hit:hover,
[data-theme="dark"] .sidebar-search-hit.highlighted {
  background: var(--color-ink-20);
  border-color: var(--border-dark);
}

[data-theme="dark"] .sidebar-search-hit + .sidebar-search-hit::before {
  background: var(--border-medium);
}

[data-theme="dark"] .sidebar-search-input.al-input {
  background: var(--color-ink-05);
}

.sidebar-search-hit-label {
  font-size: var(--text-caption);
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* A page result's journey: "Spaces › Resume Space › Documents".
   The last segment is the page and keeps the row's normal weight; the ones
   before it are context and recede, so the eye lands on the destination rather
   than reading the path left to right. */
.sidebar-search-trail {
  display: flex;
  align-items: baseline;
  min-width: 0;
  color: var(--text-muted);
}

/* Gives way first. `flex: 0 1 auto` + min-width:0 is what lets it shrink below
   its content, which is the only way the ellipsis lands here rather than on
   the destination. */
.sidebar-search-trail-ancestors {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Never shrinks: this is the word that says WHICH page, and a row that has
   truncated it is a row you cannot tell from its neighbours. */
.sidebar-search-trail-leaf {
  flex: 0 0 auto;
  white-space: nowrap;
  color: var(--text-primary);
  font-weight: 500;
}

/* A chevron, not a slash: this is a path through the UI, not a URL. Kept
   aria-hidden in the markup — the row's aria-label spells the trail out with
   commas, which reads better than a screen reader announcing punctuation. */
.sidebar-search-trail-sep {
  margin: 0 4px;
  opacity: 0.55;
}

.sidebar-search-hit-meta {
  font-size: var(--text-label, 11px);
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* "Archived" beside a profile's kind. Quiet enough not to compete with the
   name, distinct enough that the row cannot be mistaken for a live profile —
   the whole reason these are shown rather than filtered out. */
.sidebar-search-hit-tag {
  display: inline-block;
  margin-left: 6px;
  padding: 0 5px;
  border-radius: var(--radius-sm, 4px);
  background: var(--color-ink-10);
  color: var(--text-secondary);
  font-size: var(--text-label, 11px);
  font-weight: 500;
  letter-spacing: 0.02em;
}

.sidebar-search-message,
.sidebar-search-hint {
  display: flex;
  align-items: center;
  gap: var(--space-2, 8px);
  padding: var(--space-2, 8px);
  font-size: var(--text-label, 11px);
  line-height: 1.4;
  color: var(--text-muted);
}

.sidebar-search-spinner {
  width: 12px;
  height: 12px;
  flex-shrink: 0;
  border: 1.5px solid var(--color-ink-10);
  border-top-color: var(--color-action);
  border-radius: var(--radius-full, 9999px);
  animation: sidebarSearchSpin 0.7s linear infinite;
}

@keyframes sidebarSearchSpin {
  to { transform: rotate(360deg); }
}

/* style.css carries no blanket reduced-motion rule — each component stills its
   own motion, so this one does too. */
@media (prefers-reduced-motion: reduce) {
  .sidebar-search-spinner { animation: none; }
}

/* ── Collapsed rail: the same panel, floating ──────────────────────────────
   The rail is --sidebar-collapsed-width (56px). There is no in-flow slot a
   search field can occupy there, so on the rail — and only there — the panel
   is portalled to <body> and placed beside the trigger. Everything the in-flow
   version was built to avoid is paid here, once, deliberately:

     position: fixed  — `.sidebar` sets `overflow: hidden`, so a panel that
                        stayed in the tree would be clipped to 56px.
     --z-dropdown     — 170, above --z-sidebar's 140. It is the token every
                        other flyout in this app uses; a raw number here would
                        be the start of a second stacking scheme.
     top/left/width/max-height — set inline by GlobalSearch.tsx, because a
                        portalled element inherits no layout and the numbers
                        are measured per open.

   The surface is NOT changed to a lighter fill. The panel is already ink-05
   with a border, and over the document canvas that plus a shadow reads as
   elevated on its own — while re-tinting it would break the row highlight,
   which is `--bg-white` at 70% precisely because it sits on ink-05. */
.sidebar-search-pop {
  position: fixed;
  z-index: var(--z-dropdown);
  display: flex;
  flex-direction: column;
  /* Wide enough for a filename plus its "Document · Space" meta line. Fixed,
     so it belongs here and not in the style attribute beside the three numbers
     that genuinely are measured per open. */
  width: 300px;
  /* Grows from the trigger's edge, so the zoom reads as the panel coming OUT
     of the button rather than appearing over it. */
  transform-origin: left top;
  animation: sidebarSearchPopIn var(--duration-enter) var(--ease-out) both;
}

/* Scale, not a slide. --spring is reserved for playful surfaces and would
   overshoot a field you are about to type into; 0.96 is a hint of depth rather
   than a zoom you can watch. The 6px of travel comes from the trigger's side,
   so the panel arrives from where it was summoned. */
@keyframes sidebarSearchPopIn {
  from { opacity: 0; transform: scale(0.96) translateX(-6px); }
  to   { opacity: 1; transform: scale(1) translateX(0); }
}

.sidebar-search-pop .sidebar-search-panel {
  /* Fill the measured max-height, and let the results scroll inside it — the
     same `flex: 1 + min-height: 0` contract `.sidebar-search.is-expanded`
     gives the in-flow panel, which no ancestor out here can provide. */
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
  /* Floating over the canvas, so it needs the elevation the sidebar's own
     ground was giving it for free. */
  box-shadow: var(--shadow-lg);
  border-color: var(--border-medium);
  /* The wrapper owns the entrance now. Two animations on one element — the
     panel's own slide plus the wrapper's zoom — read as a stutter. */
  animation: none;
}

[data-theme="dark"] .sidebar-search-pop .sidebar-search-panel {
  /* Dark's elevation is lightness, not shadow: a shadow on #1B1814 over
     #17140F is invisible, so the step up the ink scale does the work. The
     border goes one rung too, or the panel has no edge against the canvas. */
  background: var(--bg-surface-raised);
  border-color: var(--border-dark);
}

@media (prefers-reduced-motion: reduce) {
  .sidebar-search-pop { animation: none; }
}

/* Sidebar Space Search — quiet find-a-space input under the New Space zone.
   Rendered only when the org has >8 spaces and the sidebar is expanded.
   Follows the .dash-space-search-input precedent; tokens only. */
.sidebar-space-search {
  flex-shrink: 0;
  padding: 0 0.75rem var(--space-2, 8px);
}

.sidebar-space-search-input {
  width: 100%;
  height: 32px; /* matches .sidebar-space-search-skeleton — no load jump */
  padding: 0 var(--space-3, 12px);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  font-family: var(--font-body);
  font-size: var(--text-caption);
  color: var(--text-primary);
  background: var(--bg-sidebar);
  outline: none;
  transition: border-color var(--duration-fast) var(--ease-out),
              background var(--duration-fast) var(--ease-out),
              box-shadow var(--duration-fast) var(--ease-out);
}

.sidebar-space-search-input::placeholder {
  color: var(--text-muted);
}

.sidebar-space-search-input:focus {
  border-color: var(--color-action);
  background: var(--color-action-soft);
  box-shadow: 0 0 0 2px rgba(74, 139, 106, 0.15);
}

/* Loading: reserved search row (last-known space count > 8) so the list
   doesn't jump when the real input appears. */
.sidebar-space-search-skeleton {
  height: 32px;
  border-radius: var(--radius-md);
  background: linear-gradient(90deg, var(--color-ink-05) 25%, var(--color-ink-10) 50%, var(--color-ink-05) 75%);
  background-size: 200% 100%;
  animation: skeletonShimmer 1.5s ease-in-out infinite;
}

/* Search with no matches — honest row + one-tap Clear */
.sidebar-space-search-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2, 8px);
  padding: var(--space-4, 16px) var(--space-3, 12px);
  text-align: center;
}

.sidebar-space-search-empty-text {
  font-size: var(--text-caption);
  color: var(--text-muted);
  overflow-wrap: anywhere;
}

.sidebar-space-search-clear {
  font-size: 11px;
  padding: 4px 12px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-ink-20);
  background: transparent;
  color: var(--color-ink-60);
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-out);
}

.sidebar-space-search-clear:hover {
  background: var(--color-ink-05);
}

/* Keyboard highlight — arrows from the search input walk the list */
.sidebar-space-option--highlighted .sidebar-space-item {
  background: var(--color-action-soft);
  color: var(--color-ink);
  outline: 1.5px solid var(--color-action);
  outline-offset: -1.5px;
}

/* The sidebar filter chips (Needs you / Working / All) were retired on
   2026-08-05: they and the list's group headers were two mechanisms for one
   idea stacked in 20px of column. The chips BECAME the headers — see
   @shared/nav/space-groups and .sidebar-section-label. */

/* .al-chip — THE house chip base (one chip system). Promoted from the
   sidebar-scoped block so every filter-chip surface (sidebar, table
   toolbar, settings mode chips) shares one recipe. Surfaces add deltas
   under their own class, never a parallel chip system. */
.al-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 32px;
  padding: var(--space-2) var(--space-3);
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.4;
  color: var(--text-secondary);
  background: transparent;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-full);
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--duration-fast) var(--ease-out),
              border-color var(--duration-fast) var(--ease-out),
              color var(--duration-fast) var(--ease-out);
}

.al-chip:hover {
  background: var(--color-ink-05);
  color: var(--color-ink);
}

.al-chip:focus-visible {
  outline: 2px solid var(--color-action);
  outline-offset: 1px;
}

.al-chip--active {
  color: var(--color-action);
  border-color: var(--color-action);
  background: var(--color-action-soft);
}

/* The filter chips are count-free by design (2026-07-16 review): the chip
   counted spaces while row badges count items — the badges ARE the count. */

/* Collapsed rail search affordance — expands the sidebar + focuses search */
.sidebar-rail-search {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  margin: 0 auto var(--space-2);
  flex-shrink: 0;
  border: none;
  background: transparent;
  color: var(--text-secondary);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-out),
              color var(--duration-fast) var(--ease-out);
}

.sidebar-rail-search:hover {
  background: var(--bg-sidebar-hover);
  color: var(--color-action);
}

.sidebar-rail-search:focus-visible {
  outline: 2px solid var(--color-action);
  outline-offset: -2px;
}

/* Sidebar Section */
.sidebar-section {
  flex: 1;
  overflow-y: auto;
  padding: 0 0.5rem;
  mask-image: linear-gradient(to bottom, black calc(100% - 24px), transparent 100%);
  -webkit-mask-image: linear-gradient(to bottom, black calc(100% - 24px), transparent 100%);
}

.sidebar-section-title,
.sidebar-section-label {
  font-size: 0.65rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-muted);
  padding: 0.5rem 0.625rem 0.375rem;
  list-style: none;
}

/* Space List */
.sidebar-space-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

@keyframes sidebarItemIn {
  from { opacity: 0; transform: translateX(-6px); }
  to { opacity: 1; transform: translateX(0); }
}

.sidebar-space-item {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.5rem 0.625rem;
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: background var(--duration-normal) var(--ease-out),
              color var(--duration-normal) var(--ease-out),
              padding-left var(--duration-normal) var(--ease-out);
  font-size: 0.875rem;
  color: var(--text-secondary);
  animation: sidebarItemIn var(--duration-enter) var(--ease-out) both;
  animation-delay: var(--stagger, 0ms);
}

.sidebar-space-item:hover {
  background: color-mix(in srgb, var(--bg-white) 70%, transparent);
  color: var(--color-ink);
  padding-left: calc(0.625rem + 3px);
}

.sidebar-space-item.active {
  background: var(--color-action-soft);
  color: var(--color-ink);
  font-weight: 500;
}

.sidebar-space-name {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Row shell — hosts the overflow menu (SpaceRowMenu, .srm-* family in
   hover-card.css) beside the HoverCard trigger. The ellipsis reveals on
   row hover / focus-within and always at (hover: none) — the keyboard and
   touch path to Pin/Upload/Answer; the hover card stays the pointer
   fast-path. */
.sidebar-space-row {
  display: flex;
  align-items: center;
  min-width: 0;
}

.sidebar-space-row .sidebar-space-item-trigger {
  flex: 1;
  min-width: 0;
}

/* Search mode: each li carries an invisible option proxy that owns the
   listbox option role + accessible name (options must not contain
   interactive content — the row's link/buttons stay outside the ARIA
   option). Covers the row's box so aria-activedescendant scrolling works. */
.sidebar-space-list > li {
  position: relative;
}

.sidebar-space-option-proxy {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* Trailing badge/count/pulse styles live in the consolidated
   ".sidebar-signal" family further down (search: "Sidebar signal"). */

/* Sidebar Nav */
/* Primary nav — ONE horizontal icon row above the utility row (pitch
   §2.2b). Five stacked ~38px rows became 44px icon targets in a single
   ~52px strip; the reclaimed height flows to the space list via
   .sidebar-section's flex: 1. Labels live in the tooltip layer +
   aria-label; the old left-edge active bar is now an underline dot. */
.sidebar-nav {
  flex-shrink: 0;
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-evenly;
  gap: var(--space-1);
  padding: var(--space-1) var(--space-2);
  border-top: 1px solid var(--border-light);
}

.sidebar-nav-item {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  flex-shrink: 0;
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  position: relative;
  transition: background var(--duration-normal) var(--ease-out),
              color var(--duration-normal) var(--ease-out);
}

.sidebar-nav-item:hover {
  background: color-mix(in srgb, var(--bg-white) 70%, transparent);
  color: var(--color-action);
}

/* Active underline dot (replaces the left-edge bar) */
.sidebar-nav-item::after {
  content: '';
  position: absolute;
  bottom: 5px;
  left: 50%;
  width: 4px;
  height: 4px;
  border-radius: var(--radius-full);
  background: var(--color-action);
  opacity: 0;
  transform: translateX(-50%) scale(0);
  transition: transform var(--duration-enter) var(--spring),
              opacity var(--duration-enter) var(--ease-out);
}

.sidebar-nav-item.active {
  color: var(--color-action);
}

.sidebar-nav-item.active::after {
  opacity: 1;
  transform: translateX(-50%) scale(1);
}

.sidebar-nav-item:focus-visible {
  outline: 2px solid var(--color-action);
  outline-offset: -2px;
}

/* Badge slot (dashboard icon) — corner dot-badge in the icon row */
.sidebar-badge {
  font-size: 0.7rem;
  font-weight: 700;
  background: var(--color-red);
  color: var(--text-inverse);
  padding: 0.1rem 0.45rem;
  border-radius: var(--radius-full);
  min-width: 18px;
  text-align: center;
}

.sidebar-nav-item .sidebar-badge {
  position: absolute;
  top: 4px;
  right: 2px;
  font-size: 0.6rem;
  padding: 0 0.3rem;
  min-width: 14px;
  line-height: 1.5;
}

/* Unseen-release dot ("What's new" icon) — quiet green corner dot, cleared
   the moment the release is acknowledged (visit /whats-new or dismiss the
   dashboard teaser). Informational, not an alert — action green, not red. */
.sidebar-nav-unseen {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 7px;
  height: 7px;
  border-radius: var(--radius-full);
  background: var(--color-action);
  box-shadow: 0 0 0 2px var(--bg-sidebar, var(--bg-white));
}

/* Sidebar Collapse Toggle */
.sidebar-collapse-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-full, 50%);
  color: var(--text-muted);
  flex-shrink: 0;
  transition:
    color var(--transition-fast),
    background var(--transition-fast),
    transform var(--transition-fast);
}

.sidebar-collapse-btn:hover {
  color: var(--text-primary);
  background: var(--color-ink-05, rgba(0, 0, 0, 0.03));
  transform: scale(1.05);
}

/* Sidebar close button (mobile only) */
.sidebar-close-btn {
  display: none;
  align-items: center;
  justify-content: center;
  padding: 4px;
  color: var(--text-muted);
  border-radius: var(--radius-sm);
  transition: color var(--transition-fast), background var(--transition-fast);
  margin-left: auto;
}

.sidebar-close-btn:hover {
  color: var(--text-primary);
  background: rgba(0, 0, 0, 0.06);
}

/* Sidebar overlay (mobile only) — hidden on desktop */
.sidebar-overlay {
  display: none;
}

.sidebar-collapse-btn svg {
  transition: transform var(--transition-normal);
}


/* --------------------------------------------------------------------------
   5. Top Bar
   -------------------------------------------------------------------------- */
.topbar {
  position: sticky;
  top: 0;
  height: var(--topbar-height);
  background: var(--bg-white);
  border-bottom: 1px solid var(--border-light);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 1.5rem;
  margin-left: var(--sidebar-width);
  z-index: var(--z-topbar);
  transition: margin-left var(--duration-slow) var(--ease-out),
              background var(--duration-normal) var(--ease-out),
              box-shadow var(--duration-normal) var(--ease-out),
              border-bottom-color var(--duration-normal) var(--ease-out),
              backdrop-filter var(--duration-normal) var(--ease-out),
              -webkit-backdrop-filter var(--duration-normal) var(--ease-out);
}

body.sidebar-collapsed .topbar {
  margin-left: var(--sidebar-collapsed-width);
}

.topbar.scrolled {
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  background: color-mix(in srgb, var(--bg-white) 85%, transparent);
  box-shadow: 0 1px 8px rgba(0, 0, 0, 0.04);
  border-bottom-color: transparent;
}

/* Drag-overlay — full-page drop target (element lives in _app.html) */
.drag-overlay {
  position: fixed;
  inset: 0;
  z-index: 300;
  background: rgba(15, 20, 26, 0.55);
  backdrop-filter: blur(4px);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
}
.drag-overlay.visible {
  opacity: 1;
  pointer-events: auto;
}
.drag-card {
  background: var(--color-white);
  border-radius: 20px;
  padding: 48px 56px;
  text-align: center;
  box-shadow: 0 24px 80px rgba(0, 0, 0, 0.15);
  transform: scale(0.92);
  transition: transform 0.3s var(--spring);
}
.drag-overlay.visible .drag-card { transform: scale(1); }
.drag-orb {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: var(--alembic-wash);
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto 16px;
}
.drag-orb svg {
  width: 28px;
  height: 28px;
  stroke: var(--alembic);
  stroke-width: 2;
  fill: none;
}
.drag-title {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 500;
  color: var(--ink);
  margin-bottom: 4px;
}
.drag-hint {
  font-size: 14px;
  color: var(--ink-60);
}

.topbar-left {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.topbar-mobile-menu {
  display: none;
  color: var(--text-secondary);
  padding: 0.25rem;
}

.topbar-title {
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 500;
  color: var(--color-ink);
}

.topbar-right {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.topbar-search {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  background: var(--bg-muted);
  border: 1px solid var(--border-light);
  border-radius: var(--radius-md);
  padding: 0.375rem 0.75rem;
  transition: border-color var(--transition-fast);
}

.topbar-search:focus-within {
  border-color: var(--primary);
}

.topbar-search svg {
  color: var(--text-muted);
  flex-shrink: 0;
}

.topbar-search input {
  border: none;
  background: none;
  font-size: 0.875rem;
  color: var(--text-primary);
  width: 200px;
}

.topbar-search input::placeholder {
  color: var(--text-muted);
}

.topbar-filter select {
  padding: 0.375rem 0.75rem;
  border: 1px solid var(--border-light);
  border-radius: var(--radius-md);
  background: var(--bg-white);
  font-size: 0.85rem;
  color: var(--text-secondary);
  cursor: pointer;
}

.topbar-filter select:focus {
  border-color: var(--primary);
}

/* -- Topbar Stepper Mode (doc detail pages) -- */
.topbar-stepper {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  overflow: visible;
  padding: 0 4px;
}
/* React island .ri-root wrapper must fill the stepper */
.topbar-stepper > .ri-root {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
}
.topbar-stepper::-webkit-scrollbar { display: none; }
.topbar-stepper.hidden { display: none; }

.topbar--stepper-mode {
  position: fixed;
  top: 0;
  right: 0;
  left: var(--sidebar-width);
  height: 72px;
  padding: 0;
  margin-left: 0;
  z-index: var(--z-topbar);
  transition: height 0.25s ease;
}
.topbar--stepper-mode.scrolled {
  height: var(--topbar-height);
}
body.sidebar-collapsed .topbar--stepper-mode {
  left: var(--sidebar-collapsed-width);
}
.topbar--stepper-mode .topbar-left { display: none; }
.topbar--stepper-mode .topbar-right { display: none; }
.topbar--stepper-mode .topbar-stepper {
  justify-content: center;
}

/* When scrolled — show action buttons in topbar alongside stepper */
.topbar--stepper-mode.scrolled .topbar-right {
  display: flex;
  align-items: center;
  gap: 4px;
  position: absolute;
  right: 16px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 5;
}

/* Shrink stepper to make room for actions when merged */
.topbar--stepper-mode.scrolled .topbar-stepper {
  padding-right: 200px;
}

/* Scroll-merge + stepper-mode padding removed — consolidated bar is self-contained */

/* --------------------------------------------------------------------------
   6. Main Content Area
   -------------------------------------------------------------------------- */
#app {
  margin-left: var(--sidebar-width);
  padding: 1.5rem;
  min-height: calc(100vh - var(--topbar-height) - 40px);
  transition: margin-left var(--duration-slow) var(--ease-out),
              padding-right 280ms var(--ease-decelerate, cubic-bezier(0.22, 1, 0.36, 1));
}

/* DISTLR pin — same reservation as doc-detail reading posture. The panel
   stays a fixed overlay; this shoves page content left so Flags never sits
   under the chat. Hidden (no class) when remaining width would be unusable. */
#app.app-distlr-pinned {
  padding-right: var(--distlr-panel-w);
  box-sizing: border-box;
}

html.distlr-pin-review,
html.distlr-pin-review .ri-root,
#app.app-distlr-pinned.app-distlr-pin-review {
  --distlr-panel-w: var(--distlr-panel-w-review, 480px);
}

#app.app-distlr-pinned .doc-detail.doc-detail--reading {
  padding-right: 0;
}

body.sidebar-collapsed #app {
  margin-left: var(--sidebar-collapsed-width);
}

#app:has(.doc-detail) {
  padding: 0;
  min-height: 0;
}

#app:has(.architect-page) {
  padding: 0;
  min-height: 0;
}

/* Welcome / review page is a full-bleed two-column layout */
#app:has(.review-page) {
  padding: 0;
  min-height: 0;
}


/* --------------------------------------------------------------------------
   7. Stat Cards (used by wizard preview panels)
   -------------------------------------------------------------------------- */
.stat-card {
  background: var(--bg-card);
  border-radius: var(--radius-lg);
  padding: 1.25rem;
  box-shadow: none;
  border: 1px solid var(--border-light);
}

.stat-card-label {
  font-size: 0.72rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  margin-bottom: 0.375rem;
}

.stat-card-value {
  font-size: 1.75rem;
  font-weight: 700;
  color: var(--text-primary);
}



/* --------------------------------------------------------------------------
   14. Inbox
   -------------------------------------------------------------------------- */
.inbox-container {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.inbox-controls {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.inbox-filter select {
  padding: 0.375rem 0.75rem;
  border: 1px solid var(--border-light);
  border-radius: var(--radius-md);
  background: var(--bg-white);
  font-size: 0.85rem;
  color: var(--text-secondary);
  cursor: pointer;
}

.inbox-batch-actions {
  display: flex;
  gap: 0.5rem;
  margin-left: auto;
}

.inbox-bulk-bar {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.625rem 1rem;
  background: var(--primary-bg);
  border-radius: var(--radius-md);
  font-size: 0.85rem;
  color: var(--primary);
}

.inbox-bulk-bar .selected-count {
  font-weight: 700;
}

.inbox-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
  background: var(--bg-card);
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--border-light);
}

.inbox-table th {
  text-align: left;
  padding: 0.625rem 1rem;
  background: var(--bg-muted);
  border-bottom: 1px solid var(--border-light);
  font-weight: 600;
  color: var(--text-muted);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.inbox-table td {
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--border-light);
  vertical-align: middle;
}

.inbox-table tr:last-child td {
  border-bottom: none;
}

.inbox-table tr:hover td {
  background: var(--bg-muted);
}

/* Severity Badges */
.severity-badge {
  display: inline-flex;
  align-items: center;
  padding: 0.15rem 0.5rem;
  border-radius: var(--radius-full);
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.severity-badge--critical {
  background: var(--color-red-bg);
  color: var(--color-red);
}

.severity-badge--important {
  background: var(--color-amber-bg);
  color: var(--color-amber-text);
}

.severity-badge--minor {
  background: var(--color-blue-100);
  color: var(--status-info);
}


/* --------------------------------------------------------------------------
   16. Upload Modal & Drop Zone
   -------------------------------------------------------------------------- */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
  z-index: var(--z-modal);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity var(--duration-exit) var(--ease-out),
              visibility 0s linear var(--duration-exit);
}

.modal-overlay.visible {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition: opacity var(--duration-enter) var(--ease-out),
              visibility 0s linear 0s;
}

.modal-dialog {
  background: var(--bg-white);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-xl);
  width: 100%;
  max-height: 90vh;
  overflow-y: auto;
  transform: scale(0.97) translateY(4px);
  opacity: 0;
  transition: transform var(--duration-exit) var(--ease-out),
              opacity var(--duration-exit) var(--ease-out);
}

.modal-overlay.visible .modal-dialog {
  transform: scale(1) translateY(0);
  opacity: 1;
  transition: transform var(--duration-enter) cubic-bezier(0.22, 1, 0.36, 1),
              opacity var(--duration-enter) var(--ease-out);
}

.privacy-modal-dialog {
  max-width: 520px;
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1.25rem 1.5rem;
  border-bottom: 1px solid var(--border-light);
}

.modal-header h2 {
  font-size: 1.125rem;
  font-weight: 700;
}

.modal-close-btn {
  color: var(--text-muted);
  padding: 0.25rem;
  border-radius: var(--radius-sm);
  transition: color var(--transition-fast), transform 0.15s ease, background 0.15s ease;
}

.modal-close-btn:hover {
  color: var(--text-primary);
  background: var(--color-ink-05);
  transform: scale(1.1);
}

.modal-body {
  padding: 1.5rem;
  min-width: 0;
  overflow-x: hidden;
}

.modal-body p {
  font-size: 0.9rem;
  line-height: 1.65;
  color: var(--text-secondary);
  margin-bottom: 0.75rem;
}

.modal-body p:last-child {
  margin-bottom: 0;
}

/* Modal form field cascade */
@keyframes modalFieldIn {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}

.modal-body > * {
  animation: modalFieldIn var(--duration-enter) var(--ease-out) both;
}
.modal-body > *:nth-child(1) { animation-delay: 80ms; }
.modal-body > *:nth-child(2) { animation-delay: 140ms; }
.modal-body > *:nth-child(3) { animation-delay: 200ms; }
.modal-body > *:nth-child(4) { animation-delay: 260ms; }
.modal-body > *:nth-child(5) { animation-delay: 320ms; }
.modal-body > *:nth-child(n+6) { animation-delay: 380ms; }

.modal-footer {
  display: flex;
  justify-content: flex-end;
  gap: 0.75rem;
  padding: 1rem 1.5rem;
  border-top: 1px solid var(--border-light);
}

/* Drop Zone */
.drop-zone {
  border: 2px dashed var(--border-medium);
  border-radius: var(--radius-lg);
  padding: 3rem 2rem;
  text-align: center;
  cursor: pointer;
  transition: border-color var(--transition-fast), background var(--transition-fast);
  animation: upload-zone-breathe 3s ease-in-out infinite;
}

.drop-zone:hover,
.drop-zone.dragover {
  border-color: var(--primary);
  background: var(--primary-bg);
  animation: none;
}

/* Hover: arrow floats up */
.drop-zone:hover svg polyline,
.drop-zone:hover svg line {
  transform: translateY(-3px);
}
.drop-zone:hover svg {
  color: var(--primary);
}

/* Drag-active: border solidifies, arrow bobs */
.drop-zone.dragover {
  border-style: solid;
  box-shadow: 0 0 0 3px rgba(59, 117, 88, 0.105);
}
.drop-zone.dragover svg polyline,
.drop-zone.dragover svg line {
  animation: upload-arrow-bob 0.8s cubic-bezier(0.34, 1.56, 0.64, 1) infinite alternate;
}
.drop-zone.dragover svg {
  color: var(--primary);
}

.drop-zone-content svg {
  color: var(--text-muted);
  margin: 0 auto 1rem;
  transition: color 0.2s ease;
}
.drop-zone-content svg polyline,
.drop-zone-content svg line {
  transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.drop-zone-content svg path {
  transition: none;
}

.drop-zone-text {
  color: var(--text-secondary);
  font-size: 1rem;
  margin-bottom: 0.375rem;
}

.drop-zone-hint {
  color: var(--text-muted);
  font-size: 0.82rem;
}

.file-label {
  color: var(--primary);
  cursor: pointer;
  font-weight: 600;
}

.file-label:hover {
  text-decoration: underline;
}

/* Upload File List */
.upload-file-list {
  margin-top: 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
}

.upload-file-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.5rem 0.75rem;
  background: var(--bg-muted);
  border-radius: var(--radius-md);
  font-size: 0.85rem;
}

.upload-file-name {
  font-weight: 600;
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.upload-file-size {
  color: var(--color-ink-40);
  font-size: var(--text-caption);
  flex-shrink: 0;
  margin-left: 0.75rem;
}

.upload-file-remove {
  color: var(--text-muted);
  padding: 0.2rem;
  margin-left: 0.5rem;
  flex-shrink: 0;
}

.upload-file-remove:hover {
  color: var(--status-error-hover);
}


/* --------------------------------------------------------------------------
   17. PDF Viewer
   -------------------------------------------------------------------------- */
.pdf-panel {
  position: sticky;
  top: 0;
  align-self: start;
  background: var(--bg-card);
  border-radius: 0;
  border: none;
  border-left: 1px solid var(--ink-06);
  box-shadow: none;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  height: 100vh;
  min-width: 0;
  transition: width 0.25s ease, min-width 0.25s ease, border 0.25s ease;
}

/* PDF panel collapse/expand toggle — lives in .doc-detail grid, not in .pdf-panel */
.pdf-toggle-btn {
  position: fixed;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--color-white);
  border: 1px solid var(--ink-12);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  z-index: 60;
  color: var(--ink-40);
  box-shadow: 0 1px 3px rgba(0,0,0,0.08);
  transition: all 0.15s;
}

.pdf-toggle-btn:hover {
  background: var(--ink-03);
  color: var(--ink);
  border-color: var(--ink-20);
}

.pdf-toggle-btn svg {
  width: 14px;
  height: 14px;
  transition: transform 0.2s;
}

.doc-detail.pdf-collapsed .pdf-toggle-btn svg {
  transform: rotate(180deg);
}

/* PDF resize handle — fully inside panel to avoid overflow:hidden clipping */
.pdf-resize-handle {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 12px;
  cursor: col-resize;
  z-index: 10;
  background: transparent;
  transition: background 0.15s;
}

.pdf-resize-handle:hover,
.pdf-resize-handle.dragging {
  background: linear-gradient(to right, var(--alembic-wash), transparent);
}

.pdf-resize-handle::after {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 3px;
  height: 40px;
  border-radius: 1.5px;
  background: var(--ink-20);
  opacity: 0;
  transition: opacity 0.15s;
}

.pdf-resize-handle:hover::after,
.pdf-resize-handle.dragging::after {
  opacity: 1;
}

.pdf-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.375rem 0.625rem;
  font-size: 0.8rem;
  background: var(--bg-muted);
  border-bottom: 1px solid var(--border-light);
  flex-shrink: 0;
}

.pdf-page-nav {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.85rem;
  color: var(--text-secondary);
}

.pdf-page-nav button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  transition: background var(--transition-fast);
}

.pdf-page-nav button:hover {
  background: var(--border-light);
}

.pdf-page-nav button:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.pdf-canvas-wrapper {
  flex: 1;
  overflow-y: auto;
  position: relative;
}

.pdf-canvas-wrapper canvas {
  display: block;
  width: 100%;
}

.pdf-page {
  position: relative;
  border-bottom: 1px solid var(--border-light);
}

.pdf-highlight-overlay {
  position: absolute;
  top: 0;
  left: 0;
  pointer-events: none;
}

.pdf-page:last-child {
  border-bottom: none;
}

.pdf-page.pdf-highlight {
  outline: 2px solid var(--primary);
  outline-offset: -2px;
}

/* Text layer overlay for selection */
.pdf-text-layer {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  overflow: hidden;
  opacity: 0.25;
  line-height: 1;
}

.pdf-text-layer span {
  position: absolute;
  white-space: pre;
  color: transparent;
  cursor: text;
}

/* PDF selection + source highlight deliberately use --color-action-light, not
   the darkened base: these washes sit UNDER live document text, so darkening
   them costs legibility of the text being highlighted. Alphas are unchanged
   for the same reason — the intent here is luminosity, not weight. */
.pdf-text-layer span::selection {
  background: rgba(86, 159, 122, 0.3);
}

/* Source highlight animation */
.pdf-highlight {
  position: absolute;
  background: rgba(86, 159, 122, 0.15);
  border: 2px solid var(--primary);
  border-radius: var(--radius-sm);
  animation: highlight-pulse 2s ease-out;
  pointer-events: none;
}

@keyframes highlight-pulse {
  0% {
    background: rgba(86, 159, 122, 0.4);
    box-shadow: 0 0 12px rgba(86, 159, 122, 0.5);
  }
  100% {
    background: rgba(86, 159, 122, 0.1);
    box-shadow: none;
  }
}


/* --- React PDF Viewer Island mount --- */

.pdf-viewer-mount {
  flex: 1;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

/* Skeleton placeholder shown while React PDF island loads */
.pdf-viewer-mount:empty {
  align-items: center;
  justify-content: center;
  background: var(--ink-03);
}

.pdf-viewer-mount:empty::before {
  content: '';
  width: 60%;
  height: 70%;
  border-radius: var(--radius-md, 8px);
  background: linear-gradient(110deg, var(--ink-06) 30%, var(--ink-03) 50%, var(--ink-06) 70%);
  background-size: 200% 100%;
  animation: pdf-skeleton-shimmer 1.5s ease-in-out infinite;
}

@keyframes pdf-skeleton-shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

@media (prefers-reduced-motion: reduce) {
  .pdf-viewer-mount:empty::before {
    animation: none;
    background: var(--ink-06);
  }
}

.pdf-viewer-mount .ri-root {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.pdf-viewer-toolbar-extra {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding: 4px 8px;
  background: var(--bg-muted);
  border-bottom: 1px solid var(--border-light);
  flex-shrink: 0;
}

/* Field flash animation (reverse navigation from PDF to data) */
.field-flash {
  animation: fieldFlash 1.5s ease-out;
}

/* fieldFlash keyframes defined near .field-flash class below */

/* --------------------------------------------------------------------------
   18. Privacy Footer
   -------------------------------------------------------------------------- */
.privacy-footer {
  margin-left: var(--sidebar-width);
  padding: 0.75rem 1.5rem;
  text-align: center;
  font-size: 0.78rem;
  color: var(--text-muted);
  transition: margin-left var(--transition-normal);
}

body.sidebar-collapsed .privacy-footer {
  margin-left: var(--sidebar-collapsed-width);
}

.privacy-footer-sep {
  margin: 0 0.375rem;
  color: var(--border-medium);
}

.privacy-footer-link {
  color: var(--text-muted);
  font-size: 0.78rem;
  text-decoration: underline;
  cursor: pointer;
  transition: color var(--transition-fast);
}

.privacy-footer-link:hover {
  color: var(--primary);
}


/* --------------------------------------------------------------------------
   19. Mobile Bottom Tab Bar
   -------------------------------------------------------------------------- */
.mobile-tab-bar {
  display: none;
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  height: var(--mobile-tab-height);
  background: var(--bg-white);
  border-top: 1px solid var(--border-light);
  z-index: var(--z-mobile-tab);
  align-items: center;
  justify-content: space-around;
  padding-bottom: env(safe-area-inset-bottom, 0);
}

.mobile-tab {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.2rem;
  flex: 1;
  padding: 0.5rem 0;
  color: var(--text-muted);
  font-size: 0.65rem;
  font-weight: 600;
  transition: color var(--transition-fast);
  position: relative;
}

/* The DISTLR tab is a <button> (it toggles a panel, it doesn't navigate) —
   flatten the UA button chrome so it sits flush with its anchor siblings. */
button.mobile-tab {
  background: none;
  border: none;
  font-family: inherit;
  cursor: pointer;
}

.mobile-tab.active {
  color: var(--primary);
}

.mobile-tab-icon {
  width: 22px;
  height: 22px;
  display: block;
  position: relative;
}

/* CSS icon shapes for mobile tabs */
.mobile-tab-icon--dashboard::before {
  content: '';
  position: absolute;
  inset: 2px;
  border: 2px solid currentColor;
  border-radius: 3px;
}
.mobile-tab-icon--dashboard::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 2px;
  right: 2px;
  height: 2px;
  background: currentColor;
}

.mobile-tab-icon--spaces::before {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  width: 8px;
  height: 8px;
  border: 2px solid currentColor;
  border-radius: 2px;
}
.mobile-tab-icon--spaces::after {
  content: '';
  position: absolute;
  bottom: 2px;
  right: 2px;
  width: 8px;
  height: 8px;
  border: 2px solid currentColor;
  border-radius: 2px;
}

.mobile-tab-icon--distlr::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 12px;
  height: 12px;
  border: 2px solid currentColor;
  border-radius: 3px;
  transform: translate(-50%, -50%) rotate(45deg);
}
.mobile-tab-icon--distlr::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 4px;
  height: 4px;
  background: currentColor;
  border-radius: 50%;
  transform: translate(-50%, -50%);
}

.mobile-tab-icon--settings::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 10px;
  height: 10px;
  border: 2px solid currentColor;
  border-radius: 50%;
  transform: translate(-50%, -50%);
}
.mobile-tab-icon--settings::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 18px;
  height: 18px;
  border: 2px solid currentColor;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  clip-path: polygon(50% 0%, 65% 15%, 85% 15%, 100% 35%, 85% 50%, 100% 65%, 85% 85%, 65% 85%, 50% 100%, 35% 85%, 15% 85%, 0% 65%, 15% 50%, 0% 35%, 15% 15%, 35% 15%);
}

.mobile-tab-label {
  white-space: nowrap;
}

.mobile-tab-badge {
  position: absolute;
  top: 2px;
  right: calc(50% - 18px);
  min-width: 14px;
  height: 14px;
  border-radius: var(--radius-full);
  background: var(--color-red);
  color: var(--text-inverse);
  font-size: 0.55rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 3px;
}


/* --------------------------------------------------------------------------
   20. Distill Mark Loading Animations
   -------------------------------------------------------------------------- */

/* Backward-compatible .spinner — now wraps a logo-inline SVG via JS */
@keyframes spin {
  to { transform: rotate(360deg); }
}

.spinner {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
}

.spinner-sm {
  width: 12px;
  height: 12px;
}

.spinner-lg {
  width: 32px;
  height: 32px;
}

/* --- 48px Spinner (primary loader) --- */
.logo-spinner {
  width: 48px;
  height: 48px;
}

.logo-spinner .spin-dot { fill: var(--alembic); }
.logo-spinner .spin-block { fill: var(--alembic); }

.logo-spinner .spin-dot-1 { animation: spindot1 2.4s ease-in-out infinite; }
@keyframes spindot1 {
  0%, 5% { cx: 10; cy: 9; r: 4; opacity: 0.4; }
  15% { cx: 10; cy: 9; r: 4; opacity: 0.5; }
  40% { cx: 16; cy: 22; r: 2.5; opacity: 0.5; }
  55%, 72% { cx: 14; cy: 28; r: 0; opacity: 0; }
  88%, 100% { cx: 10; cy: 9; r: 4; opacity: 0.4; }
}

.logo-spinner .spin-dot-2 { animation: spindot2 2.4s ease-in-out infinite; }
@keyframes spindot2 {
  0%, 8% { cx: 24; cy: 5; r: 3.5; opacity: 0.3; }
  18% { cx: 24; cy: 5; r: 3.5; opacity: 0.4; }
  43% { cx: 24; cy: 22; r: 2; opacity: 0.45; }
  58%, 72% { cx: 24; cy: 28; r: 0; opacity: 0; }
  88%, 100% { cx: 24; cy: 5; r: 3.5; opacity: 0.3; }
}

.logo-spinner .spin-dot-3 { animation: spindot3 2.4s ease-in-out infinite; }
@keyframes spindot3 {
  0%, 5% { cx: 37; cy: 8; r: 4.5; opacity: 0.35; }
  12% { cx: 37; cy: 8; r: 4.5; opacity: 0.45; }
  42% { cx: 32; cy: 22; r: 2.5; opacity: 0.5; }
  56%, 72% { cx: 34; cy: 28; r: 0; opacity: 0; }
  88%, 100% { cx: 37; cy: 8; r: 4.5; opacity: 0.35; }
}

.logo-spinner .spin-block-1 {
  animation: spinblock1 2.4s ease-in-out infinite;
  transform-origin: 14.5px 31.5px;
}
@keyframes spinblock1 {
  0%, 48% { opacity: 0; transform: scaleX(0.3); }
  62% { opacity: 1; transform: scaleX(1); }
  80%, 83% { opacity: 1; transform: scaleX(1); }
  94%, 100% { opacity: 0; transform: scaleX(0.5); }
}

.logo-spinner .spin-block-2 {
  animation: spinblock2 2.4s ease-in-out infinite;
  transform-origin: 31.5px 31.5px;
}
@keyframes spinblock2 {
  0%, 51% { opacity: 0; transform: scaleX(0.3); }
  65% { opacity: 0.75; transform: scaleX(1); }
  80%, 83% { opacity: 0.75; transform: scaleX(1); }
  94%, 100% { opacity: 0; transform: scaleX(0.5); }
}

.logo-spinner .spin-block-3 {
  animation: spinblock3 2.4s ease-in-out infinite;
  transform-origin: 16.5px 40.5px;
}
@keyframes spinblock3 {
  0%, 54% { opacity: 0; transform: scaleX(0.3); }
  68% { opacity: 0.75; transform: scaleX(1); }
  80%, 83% { opacity: 0.75; transform: scaleX(1); }
  94%, 100% { opacity: 0; transform: scaleX(0.5); }
}

.logo-spinner .spin-block-4 {
  animation: spinblock4 2.4s ease-in-out infinite;
  transform-origin: 33.5px 40.5px;
}
@keyframes spinblock4 {
  0%, 57% { opacity: 0; transform: scaleX(0.3); }
  70% { opacity: 1; transform: scaleX(1); }
  80%, 83% { opacity: 1; transform: scaleX(1); }
  94%, 100% { opacity: 0; transform: scaleX(0.5); }
}

/* --- 24px Inline Spinner (buttons, inline) --- */
.logo-inline {
  width: 24px;
  height: 24px;
}

.logo-inline .tiny-dot { fill: var(--alembic); }

.logo-inline .tiny-dot-1 { animation: tinydot1 2s ease-in-out infinite; }
@keyframes tinydot1 {
  0%, 5% { cx: 8; cy: 8; r: 4; opacity: 0.4; }
  40% { cx: 12; cy: 20; r: 2; opacity: 0.5; }
  55%, 70% { cx: 12; cy: 26; r: 0; opacity: 0; }
  88%, 100% { cx: 8; cy: 8; r: 4; opacity: 0.4; }
}

.logo-inline .tiny-dot-2 { animation: tinydot2 2s ease-in-out infinite; }
@keyframes tinydot2 {
  0%, 8% { cx: 28; cy: 6; r: 4.5; opacity: 0.35; }
  43% { cx: 28; cy: 20; r: 2.5; opacity: 0.5; }
  58%, 70% { cx: 30; cy: 26; r: 0; opacity: 0; }
  88%, 100% { cx: 28; cy: 6; r: 4.5; opacity: 0.35; }
}

.logo-inline .tiny-block-1 {
  fill: var(--color-action);
  animation: tinyblock1 2s ease-in-out infinite;
  transform-origin: 14px 33px;
}
@keyframes tinyblock1 {
  0%, 48% { opacity: 0; transform: scaleX(0.2); }
  65% { opacity: 1; transform: scaleX(1); }
  78%, 82% { opacity: 1; transform: scaleX(1); }
  94%, 100% { opacity: 0; transform: scaleX(0.4); }
}

.logo-inline .tiny-block-2 {
  fill: var(--color-action);
  animation: tinyblock2 2s ease-in-out infinite;
  transform-origin: 24px 33px;
}
@keyframes tinyblock2 {
  0%, 52% { opacity: 0; transform: scaleX(0.2); }
  68% { opacity: 0.7; transform: scaleX(1); }
  78%, 82% { opacity: 0.7; transform: scaleX(1); }
  94%, 100% { opacity: 0; transform: scaleX(0.4); }
}

.logo-inline .tiny-block-3 {
  fill: var(--color-action);
  animation: tinyblock3 2s ease-in-out infinite;
  transform-origin: 20px 41px;
}
@keyframes tinyblock3 {
  0%, 55% { opacity: 0; transform: scaleX(0.2); }
  70% { opacity: 0.85; transform: scaleX(1); }
  78%, 82% { opacity: 0.85; transform: scaleX(1); }
  94%, 100% { opacity: 0; transform: scaleX(0.4); }
}

/* --- Contextual Loading Bar --- */
.loading-bar {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  background: var(--color-warm-bg);
  padding: var(--space-4) var(--space-6);
  border-radius: var(--radius-lg);
  border: 1px solid var(--color-ink-10);
}

.loading-bar .logo-spinner {
  width: 32px;
  height: 32px;
  flex-shrink: 0;
}

.loading-bar-text {
  font-size: var(--text-small);
  color: var(--color-ink-60);
  font-family: var(--font-body);
}

.loading-bar-text .highlight {
  color: var(--color-action);
  font-weight: 500;
}

/* --- Large Centered Spinner (for full-page/section loading) --- */
.loading-section {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  padding: var(--space-16) 0;
}

.loading-section .logo-spinner {
  width: 64px;
  height: 64px;
}

.loading-section-text {
  font-size: var(--text-small);
  color: var(--color-ink-40);
}


/* --------------------------------------------------------------------------
   21. Agent Progress Steps (Processing)
   -------------------------------------------------------------------------- */
.agent-step {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.625rem 1rem;
  background: var(--bg-card);
  border-radius: var(--radius-md);
  margin-bottom: 0.375rem;
  box-shadow: var(--shadow-xs);
  font-size: 0.875rem;
}

.agent-step .status-icon {
  width: 24px;
  text-align: center;
  font-size: 1rem;
  flex-shrink: 0;
}

.agent-step .agent-name {
  font-weight: 700;
  min-width: 160px;
  color: var(--text-primary);
}

.agent-step .agent-message {
  color: var(--text-muted);
  flex: 1;
}

.agent-step.running {
  border-left: 3px solid var(--primary);
}

.agent-step.done {
  border-left: 3px solid var(--color-green);
}

.agent-step.error {
  border-left: 3px solid var(--color-red);
}

.agent-step.pending {
  border-left: 3px solid var(--border-light);
  opacity: 0.6;
}


/* --------------------------------------------------------------------------
   21b. App.js Generated Elements (Supplementary Rules)
   -------------------------------------------------------------------------- */

/* Section title */
.section-title {
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--text-primary);
  margin: 1.5rem 0 0.75rem;
}

/* Document list container */
.doc-list-container {
  padding: 0 1.5rem 1.5rem;
}

/* Document row clickable — interaction polish */
.doc-row.clickable {
  cursor: pointer;
}

.doc-row.clickable td {
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
  position: relative;
}

.doc-row.clickable:hover td {
  background: var(--color-ink-05);
  transform: translateX(4px);
}

/* Left accent bar on hover — appears on first td */
.doc-row.clickable td:first-child::before {
  content: '';
  position: absolute;
  left: 0;
  top: 20%;
  bottom: 20%;
  width: 3px;
  border-radius: 0 3px 3px 0;
  background: var(--color-action);
  opacity: 0;
  transform: scaleY(0);
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}

.doc-row.clickable:hover td:first-child::before {
  opacity: 1;
  transform: scaleY(1);
}

.doc-filename {
  font-weight: 500;
  max-width: 300px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  transition: font-weight 0.15s ease;
}

.doc-row:hover .doc-filename {
  font-weight: 600;
  color: var(--color-ink);
}

/* Status chip hover: slight scale + shadow */
.doc-row:hover .status-badge {
  transform: scale(1.05);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}

/* Processing row: scan-line animation at bottom */
.doc-row.doc-row-processing td {
  position: relative;
  overflow: hidden;
}

.doc-row.doc-row-processing td:last-child::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  height: 2px;
  width: 100%;
  background: linear-gradient(90deg, transparent, var(--color-action), transparent);
  animation: scan-line 2s ease-in-out infinite;
}

/* New row entrance animation */
.doc-row.new-row-enter {
  animation: row-slide-in 0.4s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}

.doc-row.new-row-glow td {
  animation: row-glow 2s ease-out forwards;
}

/* Doc card (mobile) */
.doc-card {
  display: block;
  text-decoration: none;
  color: inherit;
  background: var(--bg-white);
  border: 1px solid var(--border-light);
  border-radius: var(--radius-md);
  padding: 0.75rem 1rem;
  margin-bottom: 0.5rem;
}

.doc-card:hover {
  border-color: var(--primary-light);
  box-shadow: var(--shadow-sm);
}

.doc-card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 0.5rem;
}

.doc-card-filename {
  font-weight: 600;
  font-size: 0.9rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.doc-card-meta {
  display: flex;
  gap: 1rem;
  font-size: 0.78rem;
  color: var(--text-muted);
}

/* Empty state */
.empty-state {
  text-align: center;
  padding: 3rem 1.5rem;
  color: var(--text-muted);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
}
.empty-state-icon {
  margin-bottom: var(--space-2);
  opacity: 0.6;
}
.empty-state-title {
  font-size: var(--text-h3);
  font-weight: 600;
  color: var(--color-ink);
}
.empty-state-desc {
  font-size: var(--text-small);
  color: var(--color-ink-60);
  max-width: 360px;
  line-height: 1.5;
}
.empty-state-cta {
  margin-top: var(--space-2);
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

.empty-state p {
  margin-bottom: 1rem;
}

/* Section card actions */
.section-card-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.copy-section-btn {
  font-size: 0.75rem;
  color: var(--text-muted);
}

.copy-section-btn:hover {
  color: var(--primary);
}

/* Section empty */
.section-empty {
  color: var(--text-muted);
  font-style: italic;
  font-size: 0.85rem;
  padding: 0.5rem 0;
}

/* Validation item sub-elements */
.validation-item {
  font-size: 0.85rem;
  color: var(--text-secondary);
  margin-bottom: 0.25rem;
  line-height: 1.5;
}

.validation-item-field {
  font-weight: 600;
  color: var(--text-primary);
  margin-right: 0.5rem;
}

.validation-item-msg {
  color: var(--text-secondary);
}

.validation-clean {
  color: var(--color-green);
  font-weight: 500;
}

/* Summary sections */
.summary-card .summary-body {
  padding: 0.625rem 1rem;
}

.summary-text {
  font-size: 0.875rem;
  line-height: 1.65;
  color: var(--text-primary);
  margin: 0 0 0.625rem;
  letter-spacing: -0.01em;
}

.summary-text:last-child {
  margin-bottom: 0;
}

.summary-detail-list {
  margin-bottom: 0.5rem;
  border-top: 1px solid var(--border-light);
  padding-top: 0.5rem;
}

.summary-detail-list:first-of-type {
  margin-top: 0.25rem;
}

.summary-detail-list:last-child {
  margin-bottom: 0;
}

.summary-list-toggle {
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.8rem;
  color: var(--text-secondary);
  padding: 0.25rem 0;
}

.summary-list-toggle strong {
  font-weight: 600;
  color: var(--text-primary);
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.list-count {
  background: var(--bg-muted);
  color: var(--text-muted);
  font-size: 0.7rem;
  font-weight: 600;
  padding: 0.1rem 0.4rem;
  border-radius: var(--radius-full);
}

.summary-detail-list ul {
  margin: 0.375rem 0 0.25rem 1.25rem;
  padding: 0;
  font-size: 0.825rem;
  line-height: 1.55;
  color: var(--text-secondary);
}

.summary-detail-list li {
  margin-bottom: 0.3rem;
  padding-left: 0.125rem;
}

.summary-detail-list li:last-child {
  margin-bottom: 0;
}

.needs-review ul {
  color: var(--text-muted);
}

/* Field empty / enum badge */
.field-empty {
  color: var(--text-muted);
  font-style: italic;
  font-size: 0.8rem;
}

.enum-badge {
  display: inline-block;
  background: var(--primary-bg);
  color: var(--primary);
  padding: 0.1rem 0.5rem;
  border-radius: var(--radius-full);
  font-size: 0.8rem;
  font-weight: 500;
}

/* Inline editing */
.inline-edit-input {
  width: 100%;
  padding: 0.25rem 0.5rem;
  border: 1px solid var(--primary);
  border-radius: var(--radius-sm);
  font-size: inherit;
  font-family: inherit;
  outline: none;
  box-shadow: 0 0 0 2px rgba(59, 117, 88, 0.13);
}

/* Question card */
.question-card {
  background: var(--color-amber-bg);
  border: 1px solid var(--color-amber);
  border-radius: var(--radius-md);
  padding: 1rem 1.25rem;
  margin-bottom: 1rem;
}

.question-header {
  font-weight: 700;
  font-size: 0.9rem;
  color: var(--color-amber-text);
  margin-bottom: 0.5rem;
}

.question-text {
  font-size: 0.9rem;
  margin-bottom: 0.5rem;
}

.question-context {
  font-size: 0.8rem;
  color: var(--text-muted);
  margin-bottom: 0.75rem;
}

.question-options {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 0.75rem;
}

.question-option-btn {
  font-size: 0.8rem;
}

.question-input-row {
  display: flex;
  gap: 0.5rem;
}

.question-input {
  flex: 1;
  padding: 0.4rem 0.75rem;
  border: 1px solid var(--border-medium);
  border-radius: var(--radius-sm);
  font-size: 0.85rem;
}

.question-submit-btn {
  white-space: nowrap;
}

.question-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
  margin-bottom: 0.5rem;
}

.question-meta-tag {
  font-size: 0.7rem;
  font-weight: 600;
  padding: 0.15rem 0.5rem;
  border-radius: var(--radius-sm);
  background: var(--color-amber);
  color: var(--color-amber-text);
  opacity: 0.8;
}

.question-tried {
  font-size: 0.8rem;
  color: var(--text-muted);
  margin-bottom: 0.75rem;
}

.question-tried summary {
  cursor: pointer;
  font-weight: 600;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--text-muted);
}

.question-tried-text {
  margin-top: 0.375rem;
  padding: 0.5rem 0.75rem;
  background: var(--bg-secondary);
  border-radius: var(--radius-sm);
  font-size: 0.8rem;
  line-height: 1.4;
}

/* Space card CTA variant */
.space-card--cta {
  border: 2px dashed var(--border-medium);
  background: transparent;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100px;
}

.space-card--cta:hover {
  border-color: var(--primary);
  background: var(--primary-bg);
}

.space-card-cta-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  color: var(--text-muted);
  font-weight: 500;
}

.space-card-cta-icon {
  font-size: 2rem;
  line-height: 1;
  color: var(--primary-light);
}

.space-card-body {
  flex: 1;
  min-width: 0;
}



.data-table-total-label {
  font-weight: 700;
  color: var(--text-secondary);
}

/* --------------------------------------------------------------------------
   22. Responsive Design
   -------------------------------------------------------------------------- */
@media (max-width: 1024px) {
  .doc-detail {
    grid-template-columns: 1fr;
  }

  .pdf-panel {
    position: relative;
    top: auto;
    max-height: 500px;
  }

}

@media (max-width: 768px) {
  /* Sidebar drawer — width shared between closed/open states so the
     slide-in never reflows; bottom padding clears the home indicator.
     .sidebar.collapsed included so a desktop-collapsed user still gets a
     full-width drawer (the rail width would otherwise win on specificity). */
  .sidebar,
  .sidebar.collapsed {
    width: min(85vw, 320px);
    transform: translateX(-100%);
    /* Off-canvas is also hidden (once the slide-out finishes) — a closed
       drawer must not keep invisible links in the tab order. The sidebar
       island mirrors this with inert; visibility covers pre-hydration. */
    visibility: hidden;
    transition: transform var(--duration-slow) var(--ease-out),
                visibility 0s linear var(--duration-slow);
    padding-bottom: env(safe-area-inset-bottom, 0);
  }

  .sidebar.mobile-open {
    transform: translateX(0);
    visibility: visible;
    transition: transform var(--duration-slow) var(--ease-out),
                visibility 0s;
    width: min(85vw, 320px);
  }

  /* Hide collapse button on mobile — hamburger menu handles open/close */
  .sidebar-collapse-btn {
    display: none;
  }

  /* Show close button on mobile */
  .sidebar-close-btn {
    display: flex;
  }

  /* Topbar adjustments */
  .topbar {
    margin-left: 0;
  }

  body.sidebar-collapsed .topbar {
    margin-left: 0;
  }

  .topbar-mobile-menu {
    display: flex;
  }

  .topbar-search {
    display: none;
  }

  .topbar-filter {
    display: none;
  }

  /* Main content */
  #app {
    margin-left: 0;
    padding: 1rem;
    padding-bottom: calc(var(--mobile-tab-height) + 1rem);
  }

  #app:has(.architect-page) {
    padding: 0;
    min-height: 0;
  }

  body.sidebar-collapsed #app {
    margin-left: 0;
  }

  /* Show mobile tab bar */
  .mobile-tab-bar {
    display: flex;
  }

  /* Chat FAB position above tab bar */
  .chat-fab {
    bottom: calc(var(--mobile-tab-height) + 1rem);
  }

  /* Chat drawer: full width on mobile */
  .chat-drawer {
    right: 0;
    width: 100%;
    height: calc(100vh - var(--mobile-tab-height));
    border-radius: var(--radius-xl) var(--radius-xl) 0 0;
  }

  /* Footer */
  .privacy-footer {
    margin-left: 0;
    padding-bottom: calc(var(--mobile-tab-height) + 0.75rem);
  }

  body.sidebar-collapsed .privacy-footer {
    margin-left: 0;
  }

  /* Document list: switch to cards */
  .doc-table {
    display: none;
  }

  .doc-card-list {
    display: flex;
  }

  /* Document detail stacked */
  .doc-detail {
    grid-template-columns: 1fr;
  }

  /* Architect page: account for mobile tab bar */
  .architect-page {
    height: calc(100vh - var(--topbar-height) - var(--mobile-tab-height, 56px));
  }

  /* Font adjustments */
  .topbar-title {
    font-size: 1.05rem;
  }

  /* Mobile sidebar overlay background */
  .sidebar-overlay {
    display: block;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0);
    z-index: calc(var(--z-sidebar) - 1);
    pointer-events: none;
    transition: background 0.3s ease;
  }

  .sidebar-overlay.visible {
    background: rgba(0, 0, 0, 0.4);
    pointer-events: auto;
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
  }

  /* Inbox */
  .inbox-table {
    font-size: 0.8rem;
  }

  .inbox-table th,
  .inbox-table td {
    padding: 0.5rem 0.625rem;
  }

  .inbox-answer-input {
    width: 100%;
    min-width: 0;
  }

  /* Icon nav items are fixed 44px squares — no extra padding needed on
     mobile (the old stacked-row padding override distorted the row). */

  /* Space rows are the primary tap targets — 48px per WCAG 2.5.8/HIG
     (the nav-item fix above previously skipped them) */
  .sidebar-space-item {
    min-height: 48px;
    padding-left: var(--ri-space-3, var(--space-3, 12px));
    padding-right: var(--ri-space-3, var(--space-3, 12px));
  }
}

@media (max-width: 480px) {
  .modal-dialog {
    margin: 0.5rem;
  }

  .metrics-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  /* Static fallback stepper — responsive (React island handles its own) */
  .phase-stepper { padding: 8px 12px 10px; }
  .phase-label { font-size: 0.65rem; }
  .phase-connector { width: 12px; min-width: 8px; }
}


/* --------------------------------------------------------------------------
   23. Utility Classes
   -------------------------------------------------------------------------- */
.text-primary { color: var(--primary); }
.text-accent { color: var(--primary); }
.text-muted { color: var(--text-muted); }
.text-danger { color: var(--color-red); }
.text-success { color: var(--color-green-text); }
.text-warning { color: var(--color-amber); }

.bg-primary { background: var(--primary); }
.bg-accent { background: var(--primary); }
.bg-muted { background: var(--bg-muted); }

.font-mono {
  font-family: var(--font-mono);
}

.truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

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

.flex { display: flex; }
.flex-col { flex-direction: column; }
.items-center { align-items: center; }
.justify-between { justify-content: space-between; }
.gap-sm { gap: 0.375rem; }
.gap-md { gap: 0.75rem; }
.gap-lg { gap: 1.25rem; }
.mt-sm { margin-top: 0.5rem; }
.mt-md { margin-top: 1rem; }
.mt-lg { margin-top: 1.5rem; }
.mb-sm { margin-bottom: 0.5rem; }
.mb-md { margin-bottom: 1rem; }
.mb-lg { margin-bottom: 1.5rem; }

/* Breadcrumb navigation */
.doc-breadcrumb {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.85rem;
  padding: 0.25rem 0;
}

.breadcrumb-link {
  color: var(--primary);
  text-decoration: none;
}

.breadcrumb-link:hover {
  text-decoration: underline;
}

.breadcrumb-sep {
  color: var(--text-muted);
}

.breadcrumb-current {
  color: var(--text-secondary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Validation compact layout */
.confidence-bar--inline {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-width: 120px;
}

.confidence-bar--inline .confidence-bar-track {
  flex: 1;
}

.validation-details {
  margin: 0;
}

.validation-details-toggle {
  cursor: pointer;
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--text-secondary);
  padding: 0.25rem 0;
}

.validation-details-toggle:hover {
  color: var(--text-primary);
}

.validation-details-body {
  padding-top: 0.5rem;
}


/* --------------------------------------------------------------------------
   Progressive Document Analysis — Live View
   -------------------------------------------------------------------------- */
.analysis-live {
  padding: 1rem;
}

.al-scanning {
  position: relative;
  height: 3px;
  border-radius: 2px;
  background: var(--border-light);
  margin-bottom: 0.75rem;
  overflow: hidden;
}

.al-scanning::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 30%;
  height: 100%;
  border-radius: 2px;
  background: linear-gradient(90deg, transparent, var(--primary), transparent);
  will-change: transform;
  animation: al-scan-sweep 2s ease-in-out infinite;
}

@keyframes al-scan-sweep {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(433%); }
}

.al-reading {
  font-size: 0.85rem;
  color: var(--text-secondary);
  margin-bottom: 0.75rem;
  animation: al-reading-pulse 2s ease-in-out infinite;
}

@keyframes al-reading-pulse {
  0%, 100% { opacity: 0.7; }
  50% { opacity: 1; }
}

.al-classification {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-bottom: 0.625rem;
}

.al-doc-type-badge {
  display: inline-flex;
  align-items: center;
  padding: 0.2rem 0.625rem;
  border-radius: var(--radius-full);
  background: var(--primary-bg);
  color: var(--primary);
  font-size: 0.82rem;
  font-weight: 700;
  animation: al-badge-in 0.4s ease-out;
}

@keyframes al-badge-in {
  from { opacity: 0; transform: scale(0.9); }
  to { opacity: 1; transform: scale(1); }
}

.al-domain-badge {
  display: inline-flex;
  align-items: center;
  padding: 0.15rem 0.5rem;
  border-radius: var(--radius-full);
  background: var(--bg-muted);
  color: var(--text-secondary);
  font-size: 0.72rem;
  font-weight: 600;
  animation: al-badge-in 0.4s ease-out 0.1s both;
}

.al-space-name {
  border-left: 3px solid var(--primary-bg);
  padding: 0.375rem 0.75rem;
  font-size: 0.82rem;
  color: var(--text-primary);
  font-weight: 600;
  margin-bottom: 0.75rem;
}

.al-structure {
  display: flex;
  flex-direction: column;
  gap: 0;
  padding-left: 0.25rem;
}

.al-structure-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.375rem 0.5rem 0.375rem 1.25rem;
  font-size: 0.82rem;
}

/* Vertical connector line */
.al-structure-item::before {
  content: '';
  position: absolute;
  left: 4px;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--border-light);
}

.al-structure-item:first-child::before {
  top: 50%;
}

.al-structure-item:last-child::before {
  bottom: 50%;
}

/* Horizontal tick from connector to content */
.al-structure-item::after {
  content: '';
  position: absolute;
  left: 4px;
  top: 50%;
  width: 0.625rem;
  height: 2px;
  background: var(--border-light);
}

.al-structure-enter {
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.35s ease, transform 0.35s ease;
}
.al-structure-enter:not(.al-structure-visible) {
  will-change: opacity, transform;
}

.al-structure-visible {
  opacity: 1;
  transform: translateY(0);
}

.al-section-name {
  font-weight: 600;
  color: var(--text-primary);
}

.al-section-desc {
  font-size: 0.72rem;
  color: var(--text-secondary);
  font-weight: 400;
  margin-left: 0.25rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 240px;
}

.al-complexity-note {
  font-size: 0.72rem;
  color: var(--status-warning);
  background: var(--status-warning-bg);
  padding: 0.15rem 0.5rem;
  border-radius: var(--radius-sm);
  margin: 0.125rem 0 0.25rem 1.25rem;
}

/* (Old .analysis-summary base styles removed — new version in chat components section) */

/* Make analysis-live scrollable in preview panel */
.preview-tab-panel > .analysis-live {
  flex: 1;
  overflow-y: auto;
  min-height: 0;
  max-height: none;
  border: none;
  background: none;
  font-family: inherit;
}


/* --------------------------------------------------------------------------
   Demo Extraction — Peek Cards (data previews)
   -------------------------------------------------------------------------- */
.pl-section-data {
  margin: 0.25rem 0 0.5rem 2rem;
}

.pl-data-enter {
  opacity: 0;
  transition: opacity 0.25s ease;
}

.pl-data-visible {
  opacity: 1;
}

.pl-data-preview {
  padding: 0.375rem 0.625rem;
  background: var(--bg-muted);
  border-left: 2px solid var(--primary-bg);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  font-size: 0.72rem;
  color: var(--text-secondary);
  max-height: 5rem;
  overflow: hidden;
  position: relative;
}

.pl-data-preview::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 1.5rem;
  background: linear-gradient(transparent, var(--bg-muted));
  pointer-events: none;
}

.pl-data-preview.expanded {
  max-height: none;
}

.pl-data-preview.expanded::after {
  display: none;
}

.pl-data-row {
  display: flex;
  gap: 0.5rem;
  padding: 0.1rem 0;
  line-height: 1.3;
}

.pl-data-key {
  color: var(--text-muted);
  font-weight: 500;
  white-space: nowrap;
  flex-shrink: 0;
  max-width: 40%;
  overflow: hidden;
  text-overflow: ellipsis;
}

.pl-data-value {
  color: var(--text-secondary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.pl-data-more {
  display: block;
  margin-top: 0.125rem;
  font-size: 0.68rem;
  color: var(--primary);
  cursor: pointer;
  font-weight: 500;
}

.pl-data-more:hover {
  text-decoration: underline;
}

.pl-data-text {
  font-style: italic;
  line-height: 1.3;
}

.pl-data-table-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  font-size: 0.68rem;
  color: var(--text-muted);
  font-weight: 500;
}


/* --------------------------------------------------------------------------
   Panel Transitions — Pure Dissolve (opacity only, no translateY)
   -------------------------------------------------------------------------- */
.panel-transition-out {
  opacity: 0.3;
  transition: opacity 0.15s ease-out;
}

.panel-transition-in {
  animation: panel-dissolve-in 0.25s cubic-bezier(0.22, 1, 0.36, 1);
}

@keyframes panel-dissolve-in {
  from { opacity: 0; }
  to { opacity: 1; }
}


/* --------------------------------------------------------------------------
   Micro-Animation Delight Pass
   --------------------------------------------------------------------------
   Brand vocabulary:
     Spring bounce: cubic-bezier(0.34, 1.56, 0.64, 1)
     Smooth enter:  cubic-bezier(0.22, 1, 0.36, 1)
   All animations auto-respect prefers-reduced-motion via the global rule.
   -------------------------------------------------------------------------- */

/* --- 1. New Space Button — "Plus Draws Itself" --- */
.sidebar-new-space-btn svg line {
  transform-box: fill-box;
  transform-origin: center;
  transition: transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
}
/* Vertical line stretches first */
.sidebar-new-space-btn:hover svg line:first-child {
  transform: scaleY(1.3);
}
/* Horizontal line follows 60ms later */
.sidebar-new-space-btn:hover svg line:last-child {
  transform: scaleX(1.3);
  transition-delay: 60ms;
}
/* Border gray → green */
.sidebar-new-space-btn {
  transition: background var(--transition-fast), border-color 0.2s ease;
}
.sidebar-new-space-btn:hover {
  border-color: var(--color-action);
}
/* Label nudges 2px right */
.sidebar-new-space-btn .sidebar-label {
  transition: transform 0.2s cubic-bezier(0.22, 1, 0.36, 1);
}
.sidebar-new-space-btn:hover .sidebar-label {
  transform: translateX(2px);
}

/* --- 2. Inbox Nav — "Items Land in Tray" --- */
/* The polyline is the tray opening/lip — it dips as if receiving something.
   The path (tray body) stays anchored. */
#sidebar-inbox-link svg polyline {
  transform-box: fill-box;
  transform-origin: center bottom;
  transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}
#sidebar-inbox-link:hover svg polyline {
  transform: translateY(1.5px);
}

/* --- 3. Settings Nav — "Gear Tick" --- */
/* Entire gear rotates exactly 30° (one tooth) with spring overshoot —
   a single mechanical click, not a decorative spin. */
#sidebar-settings-link svg {
  transition: transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
}
#sidebar-settings-link:hover svg {
  transform: rotate(30deg);
}


/* --- 3b. Activity Nav — "Signal Traces" --- */
/* The pulse line redraws itself — a live heartbeat writing across the
   icon, not a bounce. Unique from the tray-dip (Dashboard) and the
   gear-tick (Settings). */
#sidebar-activity-link svg {
  overflow: visible;
}
#sidebar-activity-link svg polyline {
  stroke-dasharray: 52;
  stroke-dashoffset: 0;
}
#sidebar-activity-link:hover svg polyline,
#sidebar-activity-link:focus-visible svg polyline {
  animation: nav-activity-trace 0.55s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
@keyframes nav-activity-trace {
  0%   { stroke-dashoffset: 52; }
  100% { stroke-dashoffset: 0; }
}

/* --- 3c. What's New Nav — "Star Catches Light" --- */
/* A glint: the sparkle turns a little and lifts, like a gem catching
   a window. Playful, not a mechanical click (that's Settings). */
#sidebar-whats-new-link svg {
  overflow: visible;
  transform-box: fill-box;
  transform-origin: center;
  transition: transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
}
#sidebar-whats-new-link:hover svg,
#sidebar-whats-new-link:focus-visible svg {
  transform: rotate(18deg) scale(1.14);
}

/* --- 3d. Developers Nav — "Brackets Close" --- */
/* The two chevrons squeeze inward — code pairing / a fold — then
   spring back. Distinct from every other rail motion. */
#sidebar-developers-link svg {
  overflow: visible;
}
#sidebar-developers-link svg polyline {
  transform-box: fill-box;
  transform-origin: center;
  transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}
#sidebar-developers-link:hover svg polyline:first-of-type,
#sidebar-developers-link:focus-visible svg polyline:first-of-type {
  transform: translateX(-2.5px);
}
#sidebar-developers-link:hover svg polyline:last-of-type,
#sidebar-developers-link:focus-visible svg polyline:last-of-type {
  transform: translateX(2.5px);
}

/* --- 4. Send Buttons — "Paper Plane Launch" --- */
/* SVG icon: 3px right + 2px up + -12° rotation, then spring back.
   Button: simultaneous ring-pulse radiates outward. */
@keyframes send-launch {
  0%   { transform: translate(0, 0) rotate(0deg); }
  40%  { transform: translate(3px, -2px) rotate(-12deg); }
  100% { transform: translate(0, 0) rotate(0deg); }
}
@keyframes send-ring-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(59, 117, 88, 0.31); }
  100% { box-shadow: 0 0 0 10px rgba(59, 117, 88, 0); }
}
.btn-sending svg {
  animation: send-launch 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.btn-sending {
  animation: send-ring-pulse 0.5s ease-out;
}

/* --- 5. Create Button — "Plus Assembles" --- */
/* The + lines assemble independently on hover:
   vertical scaleY 0.5 → 1.15 → 1 (overshoot settle),
   horizontal scaleX follows 80ms later with the same curve.
   When disabled→enabled, a one-shot ring pulse draws the eye. */
.architect-create-btn .plus-v,
.architect-create-btn .plus-h {
  transform-box: fill-box;
  transform-origin: center;
}
@keyframes plus-assemble-v {
  0%   { transform: scaleY(0.5); }
  60%  { transform: scaleY(1.15); }
  100% { transform: scaleY(1); }
}
@keyframes plus-assemble-h {
  0%   { transform: scaleX(0.5); }
  60%  { transform: scaleX(1.15); }
  100% { transform: scaleX(1); }
}
.architect-create-btn:not(:disabled):hover .plus-v {
  animation: plus-assemble-v 0.35s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
.architect-create-btn:not(:disabled):hover .plus-h {
  animation: plus-assemble-h 0.35s cubic-bezier(0.34, 1.56, 0.64, 1) 80ms both;
}
/* Ring pulse when button becomes enabled */
@keyframes ready-ring-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(59, 117, 88, 0.265); }
  100% { box-shadow: 0 0 0 8px rgba(59, 117, 88, 0); }
}
.btn-ready-pulse {
  animation: ready-ring-pulse 0.6s ease-out;
}

/* --- 6. Start Over / Cancel — "Destructive Warning" --- */
/* Text color → red, faint red ring shadow appears — gentle "are you sure?" */
#architect-reset-btn {
  transition: color 0.2s ease, box-shadow 0.2s ease;
}
#architect-reset-btn:hover {
  color: var(--color-red);
  box-shadow: 0 0 0 3px rgba(227, 66, 52, 0.08);
}
#architect-cancel-btn {
  transition: color 0.2s ease, box-shadow 0.2s ease, background var(--transition-fast);
}
#architect-cancel-btn:hover {
  color: var(--color-red);
  box-shadow: 0 0 0 3px rgba(227, 66, 52, 0.08);
}

/* --- 7. Upload Button — "Arrow Lifts from Tray" --- */
/* Arrow bounces on hover — micro-animation for delight */
#upload-trigger-btn svg polyline,
#upload-trigger-btn svg line {
  transition: transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
}
#upload-trigger-btn:hover svg polyline,
#upload-trigger-btn:hover svg line {
  animation: upload-arrow-micro 0.6s ease-in-out;
}
#upload-trigger-btn svg path {
  transition: none;
}

/* --- 8. Chat Messages — "Bubble Slide In" --- */
/* Reuses existing architect-msg-in keyframe (fade + 6px slide up) */
.chat-drawer-messages > .chat-msg {
  animation: architect-msg-in 0.25s cubic-bezier(0.22, 1, 0.36, 1);
}

/* --- 9. Badge Pop-In --- */
/* Scales from 0 → 1 with spring overshoot when badge appears */
@keyframes badge-pop {
  0%   { transform: scale(0); }
  60%  { transform: scale(1.15); }
  100% { transform: scale(1); }
}
.sidebar-badge:not(.hidden),
.chat-fab-badge:not(.hidden) {
  animation: badge-pop 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* --- 10. Copy Confirm — "Button Press" --- */
/* Brief physical press: scale(0.93) → scale(1) with spring */
@keyframes copy-press {
  0%   { transform: scale(0.93); }
  100% { transform: scale(1); }
}
.copy-section-btn.copied {
  animation: copy-press 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* --- 11. Drop Zone — "Distill Invitation" --- */
/* Idle: border gently breathes between gray and faint blue — invites interaction */
@keyframes upload-zone-breathe {
  0%, 100% { border-color: var(--border-medium); }
  50%      { border-color: rgba(59, 117, 88, 0.22); }
}
/* Drag-active: arrow bobs up and down as if eager to receive */
@keyframes upload-arrow-bob {
  0%   { transform: translateY(-2px); }
  100% { transform: translateY(-5px); }
}

/* Rotating gradient border */
@keyframes rotate-border {
  to { --border-angle: 360deg; }
}

/* Shimmer sweep left-to-right */
@keyframes shimmer-sweep {
  0%   { left: -60%; }
  100% { left: 120%; }
}

/* Scatter dots float and fade during drag */
@keyframes scatter-in {
  0%   { opacity: 0; transform: scale(0) translateY(0); }
  20%  { opacity: 0.25; transform: scale(1) translateY(0); }
  80%  { opacity: 0.15; transform: scale(0.8) translateY(4px); }
  100% { opacity: 0; transform: scale(0) translateY(8px); }
}

/* Arrow bounce on hover */
@keyframes arrow-bounce {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-3px); }
}

/* Faster arrow bounce during drag */
@keyframes arrow-bounce-fast {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-4px); }
}

/* Drag overlay pulse */
@keyframes drag-pulse {
  0%, 100% { opacity: 0.5; }
  50%      { opacity: 1; }
}

/* Progress bar glow */
@keyframes progress-glow {
  0%, 100% { opacity: 0.5; }
  50%      { opacity: 1; }
}

/* Success checkmark circle pop */
@keyframes success-pop {
  0%   { transform: scale(0); opacity: 0; }
  60%  { transform: scale(1.15); }
  100% { transform: scale(1); opacity: 1; }
}

/* Success checkmark stroke draw */
@keyframes draw-check {
  to { stroke-dashoffset: 0; }
}

/* Table row scan-line for processing */
@keyframes scan-line {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(100%); }
}

/* New row slide-in with clip-path wipe */
@keyframes row-slide-in {
  0% {
    opacity: 0;
    transform: translateY(-10px) scaleY(0.8);
    clip-path: inset(0 0 100% 0);
  }
  100% {
    opacity: 1;
    transform: translateY(0) scaleY(1);
    clip-path: inset(0 0 0% 0);
  }
}

/* New row glow fade */
@keyframes row-glow {
  0%   { background: var(--color-action-soft); }
  100% { background: transparent; }
}

/* Upload button micro-bounce */
@keyframes upload-arrow-micro {
  0%, 100% { transform: translateY(0); }
  40%      { transform: translateY(-3px); }
}

/* File list items slide in from left with fade */
@keyframes file-list-enter {
  from { opacity: 0; transform: translateX(-8px); }
  to   { opacity: 1; transform: translateX(0); }
}


/* --------------------------------------------------------------------------
   Performance — GPU Compositing Hints
   -------------------------------------------------------------------------- */
.architect-phase-pill.active { will-change: width, padding, background; }
.panel-transition-out { will-change: opacity; }
.architect-activity-spinner { will-change: transform; }
.logo-spinner, .logo-inline { will-change: transform, opacity; }
.agent-log-card:not(.collapsed) { will-change: max-height; }


/* --------------------------------------------------------------------------
   Accessibility — Reduced Motion
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}


/* --------------------------------------------------------------------------
   Mobile Responsive — New Components
   -------------------------------------------------------------------------- */
@media (max-width: 768px) {
  /* Analysis live: tighter padding, compact badges, hide field counts */
  .analysis-live {
    padding: 0.5rem;
  }

  .al-doc-type-badge {
    font-size: 0.75rem;
    padding: 0.15rem 0.5rem;
  }

  .al-domain-badge {
    font-size: 0.68rem;
  }

  .al-structure-item {
    padding: 0.25rem 0.375rem 0.25rem 1rem;
    font-size: 0.78rem;
  }

  .al-complexity-note {
    font-size: 0.68rem;
    margin-left: 1rem;
  }

  /* Demo data previews: hidden on mobile */
  .pl-section-data {
    display: none;

  }

}


/* ==========================================================================
   Phase 2: Vanilla Enhancements
   ========================================================================== */

/* --------------------------------------------------------------------------
   Sections Grid Layout
   -------------------------------------------------------------------------- */
.sections-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-4);
}

@media (max-width: 768px) {
  .sections-grid {
    gap: var(--space-3);
  }
}

/* --------------------------------------------------------------------------
   Collapsible Sections
   -------------------------------------------------------------------------- */
.section-card-header {
  cursor: pointer;
  user-select: none;
  transition: background var(--duration-fast) var(--ease-out);
}

.section-card-header:hover {
  background: color-mix(in srgb, var(--bg-muted) 90%, var(--color-action-soft));
}

.section-collapse-chevron {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  color: var(--color-ink-300);
  transition: transform var(--duration-normal) var(--ease-out);
}

.section-card--collapsed .section-collapse-chevron {
  transform: rotate(-90deg);
}

.section-card-body {
  overflow: hidden;
  transition: max-height var(--duration-slow) var(--ease-out),
              opacity var(--duration-normal) var(--ease-out);
}

.section-card--collapsed .section-card-body {
  max-height: 0 !important;
  opacity: 0;
  padding-top: 0;
  padding-bottom: 0;
}

.section-card-body:not(.section-card--collapsed .section-card-body) {
  opacity: 1;
}

/* Empty section auto-collapsed label */
.section-empty {
  color: var(--color-ink-300);
  font-style: italic;
  font-size: var(--text-sm);
  padding: var(--space-2) 0;
}

/* --------------------------------------------------------------------------
   Progressive Section Reveal Animation
   -------------------------------------------------------------------------- */
.section-card--entering {
  animation: sectionReveal 300ms var(--ease-out);
}

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

@media (prefers-reduced-motion: reduce) {
  .section-card--entering {
    animation: none;
  }
}

/* --------------------------------------------------------------------------
   Streaming Field Animations — real-time field-by-field extraction reveal
   -------------------------------------------------------------------------- */
.section-card--streaming {
  animation: sectionReveal 300ms var(--ease-out);
}

.field-streamed {
  animation: fieldAppear 350ms var(--ease-out);
}

@keyframes fieldAppear {
  from {
    opacity: 0.3;
    transform: translateY(3px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.cell-streamed {
  animation: cellAppear 250ms ease-out;
}

@keyframes cellAppear {
  from { opacity: 0.3; }
  to { opacity: 1; }
}

.row-streamed {
  animation: rowAppear 300ms var(--ease-out);
}

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

@media (prefers-reduced-motion: reduce) {
  .field-streamed,
  .cell-streamed,
  .row-streamed,
  .section-card--streaming {
    animation: none;
  }
}

/* Skeleton Section Cards removed in Sprint 4.3 — used by the legacy stepper
   skeleton, now replaced by the PipelineStepper React island (its own CSS
   lives in pipeline-stepper.css). */

/* --------------------------------------------------------------------------
   Toast Notification System
   -------------------------------------------------------------------------- */
.toast-container {
  position: fixed;
  top: var(--topbar-height, 56px);
  right: var(--space-4);
  z-index: 9999;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  pointer-events: none;
  padding-top: var(--space-3);
}

.toast {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--bg-card);
  border: 1px solid var(--border-light);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  min-width: 280px;
  max-width: 420px;
  pointer-events: auto;
  animation: toastIn 300ms var(--ease-out);
  transition: opacity var(--duration-normal) var(--ease-out),
              transform var(--duration-normal) var(--ease-out);
}

.toast--exiting {
  opacity: 0;
  transform: translateX(20px);
}

.toast-icon {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-full);
  font-size: 12px;
  font-weight: 600;
  line-height: 1;
}

.toast--error .toast-icon {
  background: var(--color-red-100);
  color: var(--color-red-600);
}

.toast--success .toast-icon {
  background: var(--color-green-100);
  color: var(--color-green-600);
}

.toast--warning .toast-icon {
  background: var(--color-amber-100);
  color: var(--color-amber-600);
}

.toast--info .toast-icon {
  background: var(--color-blue-100);
  color: var(--color-blue-600);
}

.toast-content {
  flex: 1;
  min-width: 0;
}

.toast-title {
  font-weight: 600;
  font-size: var(--text-sm);
  color: var(--color-ink-900);
  margin-bottom: 2px;
}

.toast-message {
  font-size: var(--text-xs);
  color: var(--color-ink-500);
  line-height: 1.4;
  word-break: break-word;
}

.toast-action {
  color: var(--color-action);
  text-decoration: none;
  font-size: 13px;
  margin-top: var(--space-1);
  display: inline-block;
  cursor: pointer;
}
.toast-action:hover {
  text-decoration: underline;
}

.toast-close {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border: none;
  background: none;
  color: var(--color-ink-300);
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition: background var(--duration-fast), color var(--duration-fast);
  padding: 0;
  font-size: 16px;
  line-height: 1;
}

.toast-close:hover {
  background: var(--color-ink-50);
  color: var(--color-ink-700);
}

.toast-action:focus-visible,
.toast-close:focus-visible {
  outline: 2px solid var(--color-action);
  outline-offset: 2px;
  border-radius: var(--radius-sm, 4px);
}

@keyframes toastIn {
  from {
    opacity: 0;
    transform: translateX(20px) translateY(-4px);
  }
  to {
    opacity: 1;
    transform: translateX(0) translateY(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .toast { animation: none; }
  .toast--exiting { transition: none; }
}

/* --------------------------------------------------------------------------
   Inline Field Validation Indicators (during extraction)
   -------------------------------------------------------------------------- */
.field-status-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 14px;
  font-size: 10px;
  vertical-align: middle;
  margin-left: 4px;
  border-radius: var(--radius-full);
  animation: fieldStatusIn 200ms var(--ease-out);
}

.field-status-icon--checking {
  width: 12px;
  height: 12px;
  border: 2px solid var(--color-action-soft);
  border-top-color: var(--color-action);
  border-radius: 50%;
  animation: spin 600ms linear infinite;
}

.field-status-icon--passed {
  color: var(--color-green-600);
  opacity: 1;
  transition: opacity 1.5s var(--ease-out) 1s;
}

.field-status-icon--passed.faded {
  opacity: 0.3;
}

.field-status-icon--failed {
  color: var(--color-red-600);
  font-weight: 700;
}

.field-status-icon--corrected {
  color: var(--color-amber-600);
}

@keyframes fieldStatusIn {
  from { opacity: 0; transform: scale(0.5); }
  to { opacity: 1; transform: scale(1); }
}


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

@media (max-width: 640px) {
  .inbox-card__head {
    flex-wrap: wrap;
    gap: 8px;
    min-height: 44px;
  }

  .inbox-card__subject {
    flex-basis: 100%;
    order: 1;
  }

  .inbox-card__space-tag,
  .inbox-card__time {
    order: 2;
  }
}

/* ==========================================================================
   Authentication Screens
   ========================================================================== */

.hidden {
  display: none !important;
}

/* ---- Container ---- */
.auth-container {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  min-height: 100dvh;
  background: var(--color-warm-bg);
  padding: var(--space-6);
  position: fixed;
  inset: 0;
  z-index: 500;
}

/* ---- Card ---- */
.auth-card {
  background: var(--color-white);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-lg);
  padding: var(--space-10) var(--space-8);
  width: 100%;
  max-width: 420px;
  animation: authCardIn 300ms var(--ease-out);
}

@keyframes authCardIn {
  from {
    opacity: 0;
    transform: translateY(12px) scale(0.98);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

/* ---- Logo ---- */
.auth-logo {
  text-align: center;
  margin-bottom: var(--space-8);
}

.auth-logo-icon {
  display: block;
  margin: 0 auto var(--space-3);
}

.auth-app-name {
  font-family: var(--font-display);
  font-size: var(--text-h2);
  font-weight: 500;
  color: var(--color-ink);
  margin: 0;
}

.auth-tagline {
  font-family: var(--font-body);
  font-size: var(--text-small);
  color: var(--color-ink-40);
  margin-top: var(--space-1);
}

/* ---- Form ---- */
.auth-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.auth-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.auth-field label {
  font-family: var(--font-body);
  font-size: var(--text-small);
  font-weight: 500;
  color: var(--color-ink-60);
}

.auth-field input {
  font-family: var(--font-body);
  font-size: var(--text-body);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-ink-10);
  border-radius: var(--radius-md);
  background: var(--color-white);
  color: var(--color-ink);
  outline: none;
  transition: border-color var(--duration-fast), box-shadow var(--duration-fast);
}

.auth-field input::placeholder {
  color: var(--color-ink-20);
}

.auth-field input:focus {
  border-color: var(--color-action);
  box-shadow: 0 0 0 3px rgba(59, 117, 88, 0.105);
}

.auth-field-hint {
  font-size: var(--text-label);
  color: var(--color-ink-40);
}

/* ---- Error ---- */
.auth-error {
  font-family: var(--font-body);
  font-size: var(--text-small);
  color: var(--color-red);
  background: var(--color-red-bg);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  display: none;
}

.auth-error.visible {
  display: block;
}

/* ---- Submit button ---- */
.auth-submit {
  margin-top: var(--space-2);
  width: 100%;
  padding: var(--space-3) var(--space-4);
  font-size: var(--text-body);
  font-weight: 600;
}

.auth-submit:disabled {
  opacity: 0.7;
  cursor: not-allowed;
}

/* ---- Divider ---- */
.auth-divider {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin: var(--space-5) 0;
  color: var(--color-ink-20);
  font-size: var(--text-small);
}

.auth-divider::before,
.auth-divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--color-ink-10);
}

/* ---- Google button ---- */
.auth-google-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  width: 100%;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-ink-10);
  border-radius: var(--radius-md);
  background: var(--color-white);
  font-family: var(--font-body);
  font-size: var(--text-small);
  font-weight: 500;
  color: var(--color-ink-80);
  cursor: pointer;
  transition: border-color var(--duration-fast), box-shadow var(--duration-fast);
}

.auth-google-btn:hover {
  border-color: var(--color-ink-20);
  box-shadow: var(--shadow-sm);
}

.auth-google-btn svg {
  flex-shrink: 0;
}

.auth-forgot-link {
  display: block;
  text-align: right;
  margin-top: var(--space-2);
  font-size: var(--text-small);
  color: var(--color-ink-40);
  text-decoration: none;
}
.auth-forgot-link:hover { color: var(--color-action); }

/* ---- Link row ---- */
.auth-link-row {
  text-align: center;
  margin-top: var(--space-5);
  font-size: var(--text-small);
  color: var(--color-ink-40);
}

.auth-link {
  color: var(--color-action);
  text-decoration: none;
  font-weight: 500;
  cursor: pointer;
}

.auth-link:hover {
  text-decoration: underline;
}

.auth-link-center {
  display: block;
  text-align: center;
}

/* ---- Org picker ---- */
.auth-org-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.auth-org-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-ink-10);
  border-radius: var(--radius-md);
  background: var(--color-white);
  cursor: pointer;
  transition: border-color var(--duration-fast), box-shadow var(--duration-fast), background var(--duration-fast);
  text-align: left;
  width: 100%;
  font-family: var(--font-body);
}

.auth-org-item:hover {
  border-color: var(--color-action);
  background: var(--color-action-soft);
  box-shadow: var(--shadow-sm);
}

.auth-org-item.loading {
  opacity: 0.6;
  pointer-events: none;
}

.auth-org-avatar {
  width: 36px;
  height: 36px;
  border-radius: var(--radius-md);
  background: var(--color-action);
  color: var(--color-white);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 600;
  font-size: var(--text-body);
  flex-shrink: 0;
}

.auth-org-info {
  flex: 1;
  min-width: 0;
}

.auth-org-name {
  display: block;
  font-size: var(--text-small);
  font-weight: 600;
  color: var(--color-ink);
}

.auth-org-slug {
  display: block;
  font-size: var(--text-caption);
  color: var(--color-ink-40);
}

.auth-org-arrow {
  flex-shrink: 0;
  color: var(--color-ink-20);
}

/* ==========================================================================
   User Menu (Sidebar)
   ========================================================================== */

/* ---- Sidebar User Menu Container ---- */

.sidebar-user-menu {
  flex-shrink: 0;
  display: flex;
  align-items: center;
}

.sidebar.collapsed .sidebar-user-menu {
  padding: 0;
}

.user-menu {
  position: relative;
}

.user-menu-trigger {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-full);
  border: none;
  background: var(--color-action);
  color: var(--color-white);
  font-family: var(--font-body);
  font-size: var(--text-small);
  font-weight: 600;
  cursor: pointer;
  transition: transform var(--duration-fast), box-shadow var(--duration-fast);
}

.user-menu-trigger:hover {
  transform: scale(1.05);
  box-shadow: var(--shadow-sm);
}

.user-menu-dropdown {
  position: absolute;
  bottom: calc(100% + var(--space-2));
  left: 0;
  width: 240px;
  background: var(--color-white);
  border: 1px solid var(--color-ink-10);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: var(--space-2) 0;
  z-index: var(--z-dropdown);
  animation: dropdownIn 150ms var(--ease-out);
}

/* Let the user menu fly out over the main canvas when open */
.sidebar:has(.user-menu-dropdown:not(.hidden)),
.sidebar-inner:has(.user-menu-dropdown:not(.hidden)) {
  overflow: visible;
}

.sidebar-user-menu:has(.user-menu-dropdown:not(.hidden)),
.user-menu:has(.user-menu-dropdown:not(.hidden)) {
  z-index: var(--z-dropdown);
}

@keyframes dropdownIn {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: translateY(0); }
}

.user-menu-header {
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--color-ink-05);
}

.user-menu-name {
  font-size: var(--text-small);
  font-weight: 600;
  color: var(--color-ink);
}

.user-menu-email {
  font-size: var(--text-caption);
  color: var(--color-ink-40);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.user-menu-item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  padding: var(--space-2) var(--space-4);
  border: none;
  background: none;
  font-family: var(--font-body);
  font-size: var(--text-small);
  color: var(--color-ink-60);
  cursor: pointer;
  text-align: left;
  transition: background var(--duration-fast), color var(--duration-fast);
}

.user-menu-item:hover {
  background: var(--color-ink-05);
  color: var(--color-ink);
}

.user-menu-item--danger:hover {
  background: var(--color-red-bg);
  color: var(--color-red);
}

.user-menu-divider {
  height: 1px;
  background: var(--color-ink-05);
  margin: var(--space-1) 0;
}

/* ==========================================================================
   Org Switcher (Sidebar)
   ========================================================================== */

/* ---- Org Switcher ---- */
.org-switcher-wrap {
  position: relative;
  margin: 0 var(--space-2) var(--space-1);
}

.org-switcher {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 6px 10px;
  border: 1px solid var(--color-ink-10);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: border-color var(--duration-fast), background var(--duration-fast), box-shadow var(--duration-fast);
  background: transparent;
  font-family: var(--font-body);
  width: 100%;
  text-align: left;
}

.org-switcher:hover {
  border-color: var(--color-ink-20);
  background: var(--color-ink-05);
}

.org-switcher.open {
  border-color: var(--color-action);
  background: var(--color-action-soft);
  box-shadow: 0 0 0 2px rgba(59, 117, 88, 0.13);
}

.org-switcher.impersonating {
  border-color: var(--color-amber-300, #fcd34d);
  background: rgba(252, 211, 77, 0.08);
}

.org-switcher-avatar.admin {
  background: var(--color-ink-40);
}

.org-switcher-avatar {
  width: 22px;
  height: 22px;
  border-radius: 6px;
  background: var(--color-action);
  color: var(--color-white);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 700;
  flex-shrink: 0;
}

.org-switcher-name {
  flex: 1;
  font-size: 13px;
  font-weight: 600;
  color: var(--color-ink-700);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.org-switcher-chevron {
  flex-shrink: 0;
  color: var(--color-ink-30);
  transition: transform var(--duration-fast);
}

.org-switcher.open .org-switcher-chevron {
  transform: rotate(180deg);
}

.sidebar.collapsed .org-switcher-wrap {
  margin: 0 auto var(--space-1);
  width: 40px;
}

.sidebar.collapsed .org-switcher {
  justify-content: center;
  padding: 6px;
}

.sidebar.collapsed .org-switcher-name,
.sidebar.collapsed .org-switcher-chevron {
  display: none;
}

/* ---- Org Dropdown ---- */
/* Sidebar + sidebar-inner use overflow:hidden for collapse. When the menu is
 * open, lift that clip so the card (and collapsed flyout) isn't cut off. */
.sidebar:has(.org-dropdown.visible),
.sidebar:has(.org-switcher.open) {
  overflow: visible;
}

.sidebar-inner:has(.org-dropdown.visible),
.sidebar-inner:has(.org-switcher.open) {
  overflow: visible;
}

.org-switcher-wrap:has(.org-dropdown.visible),
.org-switcher-wrap:has(.org-switcher.open) {
  z-index: var(--z-dropdown);
}

.org-dropdown {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: auto;
  /* Prefer a readable width; may extend into the main canvas over the page */
  width: max(100%, 260px);
  min-width: 0;
  box-sizing: border-box;
  background: var(--bg-white);
  border: 1px solid var(--color-ink-10);
  border-radius: var(--radius-lg);
  box-shadow: 0 4px 24px rgba(0,0,0,0.10), 0 1px 4px rgba(0,0,0,0.06);
  z-index: var(--z-dropdown);
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity var(--duration-enter) var(--ease-out),
              transform var(--duration-enter) var(--spring);
  /* Do not clip box-shadow / rounded corners — list scrolls itself */
  overflow: visible;
}

/* Collapsed sidebar: fly out to the right into the main canvas */
.sidebar.collapsed .org-dropdown {
  left: 0;
  right: auto;
  width: max-content;
  min-width: 220px;
}

.org-dropdown.visible {
  opacity: 1;
  transform: translateY(0);
}

/* Org dropdown item stagger */
@keyframes dropdownItemIn {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: translateY(0); }
}

.org-dd-item {
  animation: dropdownItemIn var(--duration-enter) var(--ease-out) both;
}
.org-dd-item:nth-child(1) { animation-delay: 40ms; }
.org-dd-item:nth-child(2) { animation-delay: 80ms; }
.org-dd-item:nth-child(3) { animation-delay: 120ms; }
.org-dd-item:nth-child(4) { animation-delay: 160ms; }
.org-dd-item:nth-child(n+5) { animation-delay: 200ms; }

.org-dd-search-wrap {
  position: relative;
  padding: 8px 8px 4px;
  border-bottom: 1px solid var(--color-ink-05);
}

.org-dd-search-icon {
  position: absolute;
  left: 16px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--color-ink-30);
  pointer-events: none;
}

.org-dd-search {
  width: 100%;
  padding: 7px 8px 7px 30px;
  border: 1px solid var(--color-ink-10);
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-family: var(--font-body);
  outline: none;
  background: var(--color-ink-05);
  color: var(--color-ink);
  transition: border-color var(--duration-fast), background var(--duration-fast);
}

.org-dd-search:focus {
  border-color: var(--color-action);
  background: var(--bg-white);
}

.org-dd-search::placeholder {
  color: var(--color-ink-30);
}

.org-dd-section {
  padding: 4px 0;
}

.org-dd-label {
  padding: 6px 12px 4px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-ink-40);
}

.org-dd-list {
  display: flex;
  flex-direction: column;
  max-height: 200px;
  overflow-y: auto;
}

.org-dd-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 12px;
  border: none;
  background: none;
  width: 100%;
  font-family: var(--font-body);
  text-align: left;
  cursor: pointer;
  transition: background 80ms;
}

.org-dd-item:hover {
  background: var(--color-ink-05);
}

.org-dd-item.active {
  background: var(--color-action-soft);
}

.org-dd-item.switching {
  opacity: 0.5;
  pointer-events: none;
}

.org-dd-item-avatar {
  width: 24px;
  height: 24px;
  border-radius: 6px;
  background: var(--color-action);
  color: var(--color-white);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 11px;
  flex-shrink: 0;
}

.org-dd-item-avatar.admin {
  background: var(--color-ink-40);
}

.org-dd-item-name {
  flex: 1;
  font-size: 13px;
  font-weight: 500;
  color: var(--color-ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.org-dd-item-details {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.org-dd-item-details .org-dd-item-name {
  flex: none;
}

.org-dd-item-owner {
  font-size: 11px;
  font-weight: 400;
  color: var(--color-ink-400);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.org-dd-item-badge {
  flex-shrink: 0;
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 2px 6px;
  border-radius: var(--radius-sm);
  background: var(--color-ink-05);
  color: var(--color-ink-400);
}

.org-dd-check {
  flex-shrink: 0;
  color: var(--color-action);
}

.org-dd-item-meta {
  flex-shrink: 0;
  font-size: 11px;
  color: var(--color-ink-30);
  font-variant-numeric: tabular-nums;
}

.org-dd-searching,
.org-dd-empty {
  padding: 8px 12px;
  font-size: 12px;
  color: var(--color-ink-40);
}

.org-dd-admin-section {
  border-top: 1px solid var(--color-ink-05);
}

.org-dd-footer {
  border-top: 1px solid var(--color-ink-05);
  padding: 4px;
}

.org-dd-create {
  display: flex;
  align-items: center;
  gap: 8px;
  justify-content: center;
  width: 100%;
  padding: 8px 12px;
  border: none;
  background: none;
  font-family: var(--font-body);
  font-size: 13px;
  /* Explicit readable ink — never use surface tokens (ink-50) for text */
  color: var(--color-ink-600, #655D53);
  font-weight: 500;
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition: background 80ms, color 80ms;
}

.org-dd-create:hover {
  background: var(--color-ink-05);
  color: var(--color-ink-800, var(--color-ink-700, #3D3730));
}

.org-dd-create svg {
  color: currentColor;
  opacity: 0.7;
}

.org-dd-impersonation-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 8px 12px;
  background: rgba(252, 211, 77, 0.12);
  border-bottom: 1px solid rgba(252, 211, 77, 0.25);
  font-size: 11px;
  color: var(--color-ink-60);
}

.org-dd-end-imp {
  border: none;
  background: none;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  color: var(--color-action);
  cursor: pointer;
  padding: 2px 6px;
  border-radius: var(--radius-sm);
  transition: background 80ms;
  white-space: nowrap;
}

.org-dd-end-imp:hover {
  background: var(--color-action-soft);
}

/* ---- Responsive auth ---- */
@media (max-width: 480px) {
  .auth-card {
    padding: var(--space-8) var(--space-5);
  }
  .auth-container {
    padding: var(--space-3);
  }
}


/* Doc-detail page styles extracted to doc-detail.css */

/* --------------------------------------------------------------------------
   Route Transition Skeletons
   -------------------------------------------------------------------------- */
.skeleton-page {
  padding: var(--space-8) var(--space-6);
  max-width: 1100px;
  margin: 0 auto;
  position: relative;
  overflow: hidden;
}
.skeleton-line {
  background: var(--color-ink-05, #F1F3F4);
  border-radius: var(--radius-sm);
}
.skeleton-card {
  background: var(--color-ink-05, #F1F3F4);
  border-radius: var(--radius-md);
}
.skeleton-shimmer {
  position: absolute;
  top: 0; left: 0; right: 0; bottom: 0;
  background: linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.5) 50%, transparent 100%);
  animation: skeletonShimmer 1.5s ease-in-out infinite;
  pointer-events: none;
}
@keyframes skeletonShimmer {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(100%); }
}

/* --------------------------------------------------------------------------
   Phase 6: Delight Layer — Animations & Micro-Interactions
   -------------------------------------------------------------------------- */

/* 6.1 Page enter animation */
.page-enter {
  animation: pageEnter 300ms var(--ease-out) both;
}
@keyframes pageEnter {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: none; }
}

/* 6.1b Page exit animation */
.page-exit {
  animation: pageExit var(--duration-exit) var(--ease-in) both;
}
@keyframes pageExit {
  from { opacity: 1; transform: none; }
  to { opacity: 0; transform: translateY(-4px); }
}

/* 6.3 Health strip bar entrance animation */
.hs-bar {
  animation: hsBarEnter 600ms var(--ease-out) both;
  transform-origin: left;
}
@keyframes hsBarEnter {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}

/* 6.4 Sidebar collapse smoothing */
.sidebar.collapsed .sidebar-label,
.sidebar.collapsed .sidebar-section-title,
.sidebar.collapsed .sidebar-logo-text {
  opacity: 0;
  max-width: 0;
  overflow: hidden;
  transition: opacity var(--duration-slow) var(--ease-out),
              max-width var(--duration-slow) var(--ease-out);
}
.sidebar-label,
.sidebar-section-title,
.sidebar-logo-text {
  opacity: 1;
  max-width: 200px;
  overflow: hidden;
  transition: opacity var(--duration-slow) var(--ease-out),
              max-width var(--duration-slow) var(--ease-out);
}

/* 6.5 Empty state entrance */
.empty-state {
  animation: emptyStateFadeIn 400ms var(--ease-out) both;
}
@keyframes emptyStateFadeIn {
  from { opacity: 0; transform: translateY(12px); }
  to { opacity: 1; transform: translateY(0); }
}

/* 6.7 Reduced motion coverage */
@media (prefers-reduced-motion: reduce) {
  .sidebar-space-item,
  .page-enter,
  .page-exit,
  .hs-bar,
  .empty-state,
  .skeleton-shimmer,
  .architect-thinking-dots span,
  .bq-dot,
  .cta-glow,
  .btn-ready-pulse,
  .al-scan-spin,
  .section-card--entering,
  .settings-animate-in,
  .space-provisioning-banner,
  .btn--loading::before,
  .btn--success,
  .btn--copied,
  .admin-metric-enter,
  .modal-body > *,
  .org-dd-item {
    animation: none !important;
    transition: none !important;
  }
  .btn--loading::before { display: none; }
  .btn--success { opacity: 1 !important; }
  .admin-metric-enter { opacity: 1 !important; }
}

/* ── Provisioning Banner (Space Page) ── */

.space-provisioning-banner {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  padding: 20px 24px;
  background: var(--color-action-soft);
  border: 1px solid var(--color-action-glow);
  border-radius: var(--radius-lg, 12px);
  margin-bottom: 24px;
  animation: fadeSlideIn 250ms ease-out;
}
@keyframes fadeSlideIn {
  from { opacity: 0; transform: translateY(-8px); }
  to { opacity: 1; transform: translateY(0); }
}
.space-provisioning-banner h4 {
  margin: 0 0 4px;
  font-size: 14px;
  font-weight: 600;
  color: var(--text-primary);
}
.space-provisioning-banner p {
  margin: 0;
  font-size: 13px;
  color: var(--text-secondary, var(--text-muted));
  line-height: 1.5;
}
.space-provisioning-banner .dash-space-provisioning-bar {
  margin-top: 10px;
  height: 3px;
}

/* ── Space Architect Chat (Settings) ── */

.ss-architect-loading {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 16px 0;
}

.ss-architect-empty {
  text-align: center;
  padding: 32px 16px;
}
.ss-architect-empty svg {
  margin-bottom: 12px;
}
.ss-architect-empty-title {
  font-family: var(--font-body, 'DM Sans', sans-serif);
  font-weight: 600;
  font-size: 14px;
  color: var(--text-primary);
  margin-bottom: 4px;
}
.ss-architect-empty-desc {
  font-size: 13px;
  color: var(--text-muted);
  line-height: 1.5;
  max-width: 320px;
  margin: 0 auto;
}

.ss-architect-messages {
  max-height: 400px;
  overflow-y: auto;
  padding: 8px 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.ss-architect-messages .chat-msg {
  font-size: 13px;
  line-height: 1.5;
}
.ss-architect-messages .chat-msg.assistant {
  display: flex;
  align-items: flex-start;
  gap: 8px;
}
.ss-architect-messages .chat-msg.user {
  background: var(--bg-warm, #f9f9f7);
  padding: 8px 12px;
  border-radius: var(--radius-md, 8px);
  font-size: 13px;
  align-self: flex-end;
  max-width: 80%;
}
.ss-architect-messages .msg-bubble {
  background: var(--bg-white);
  border: 1px solid var(--border-light);
  padding: 8px 12px;
  border-radius: var(--radius-md, 8px);
  font-size: 13px;
  line-height: 1.5;
}

.ss-architect-streaming::after {
  content: '\25CF';
  animation: blink 1s step-end infinite;
  margin-left: 2px;
  color: var(--color-purple, #7b61ff);
}
@keyframes blink {
  50% { opacity: 0; }
}

.ss-architect-show-all {
  background: none;
  border: none;
  color: var(--primary, #2383e2);
  font-size: 12px;
  cursor: pointer;
  padding: 4px 0;
  margin-bottom: 8px;
}
.ss-architect-show-all:hover {
  text-decoration: underline;
}

.ss-architect-composer {
  display: flex;
  gap: 8px;
  align-items: flex-end;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--border-light);
}
.ss-architect-composer textarea {
  flex: 1;
  min-height: 40px;
}
.ss-architect-composer .btn {
  flex-shrink: 0;
}

.badge-purple {
  background: var(--color-purple-bg, #f0ebff);
  color: var(--color-purple, #7b61ff);
  font-size: 11px;
  font-weight: 600;
  padding: 2px 6px;
  border-radius: 4px;
}
.badge-blue {
  background: var(--color-blue-100, #E8F2FC);
  color: var(--color-blue-600, #1F7AD4);
  font-size: var(--text-label, 11px);
  font-weight: 600;
  padding: 2px 6px;
  border-radius: var(--radius-sm, 6px);
}
.badge-green {
  background: var(--color-green-bg, #E6F4EA);
  color: var(--color-green-text, #1E7E34);
  font-size: var(--text-label, 11px);
  font-weight: 600;
  padding: 2px 6px;
  border-radius: var(--radius-sm, 6px);
}
.badge-default {
  background: var(--color-ink-05, #F2F0ED);
  color: var(--color-ink-60, #655D53);
  font-size: var(--text-label, 11px);
  font-weight: 600;
  padding: 2px 6px;
  border-radius: var(--radius-sm, 6px);
}

/* Team tabs in org settings */
.settings-team-tabs {
  display: flex;
  gap: 0;
  border-bottom: 1px solid var(--color-ink-05);
  margin: -12px -20px 0;
  padding: 0 20px;
}
.settings-team-tab {
  padding: 10px 16px;
  font-size: var(--text-small);
  font-weight: 500;
  color: var(--color-ink-40);
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  cursor: pointer;
  transition: color 120ms, border-color 120ms;
}
.settings-team-tab:hover { color: var(--color-ink-80); }
.settings-team-tab.active { color: var(--color-ink-90); border-bottom-color: var(--color-action); }

/* Access popover */
.add-access-popover {
  position: absolute;
  right: 0;
  top: calc(100% + 4px);
  width: 320px;
  background: var(--bg-white, #fff);
  border: 1px solid var(--color-ink-10);
  border-radius: var(--radius-lg, 12px);
  box-shadow: 0 4px 24px rgba(0,0,0,0.10);
  z-index: var(--z-dropdown);
  padding: 8px;
}
.access-search-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px;
  border: none;
  background: none;
  border-radius: var(--radius-sm, 6px);
  cursor: pointer;
  font-family: inherit;
  text-align: left;
  transition: background 80ms;
}
.access-search-item:hover {
  background: var(--color-ink-05, rgba(0,0,0,0.03));
}

/* ── Limit Banners ─────────────────────────────────────────────────── */

.limit-banner {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 16px;
  border-radius: 10px;
  font-size: 13px;
  line-height: 1.4;
  margin-bottom: 12px;
}
.limit-banner span { flex: 1; }
.limit-banner .btn { flex-shrink: 0; }

.limit-banner-critical {
  background: var(--color-amber-bg, #FEF3CD);
  border: 1px solid var(--color-amber-400, #FBBF24);
  color: var(--color-amber-text, #8B6914);
}
.limit-banner-warning {
  background: var(--color-ink-05);
  border: 1px solid var(--color-ink-100);
  color: var(--color-ink-600, #655D53);
}

/* ── Upload Zone At-Limit State ──────────────────────────────────── */

.inline-upload-at-limit {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 20px;
  font-size: var(--text-caption, 13px);
  color: var(--color-ink-600, #655D53);
}
.inline-upload-at-limit svg {
  flex-shrink: 0;
  color: var(--color-amber, #E8A830);
}
.inline-upload-at-limit span { flex: 1; }
.inline-upload-at-limit .btn { flex-shrink: 0; }

/* ── Upgrade Prompt (global 402 handler) ─────────────────────────── */

.upgrade-prompt {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: linear-gradient(135deg, var(--color-action-soft) 0%, var(--color-purple-bg) 100%);
  border: 1px solid var(--color-action-glow);
  border-radius: var(--radius-md);
  margin: 0 0 var(--space-3);
  font-family: var(--font-body);
  font-size: var(--text-caption);
  color: var(--color-ink-900);
  animation: fade-slide-in var(--duration-slow) var(--ease-out);
}
.upgrade-prompt svg { flex-shrink: 0; color: var(--color-action); }
.upgrade-prompt span { flex: 1; }
.upgrade-prompt .btn { flex-shrink: 0; }
.upgrade-prompt-dismiss {
  background: none; border: none; cursor: pointer;
  color: var(--color-ink-400); font-size: 18px; padding: 0 var(--space-1);
  opacity: 0.6; transition: opacity var(--duration-fast) var(--ease-default);
  border-radius: var(--radius-sm);
  min-width: 28px;
  min-height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.upgrade-prompt-dismiss:hover { opacity: 1; }
.upgrade-prompt-dismiss:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px rgba(59, 117, 88, 0.265);
  opacity: 1;
}

/* ── Downgrade Alert ─────────────────────────────────────────────── */

.downgrade-alert {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--color-amber-bg);
  border: 1px solid var(--color-amber-400);
  border-radius: var(--radius-md);
  margin: 0 0 var(--space-3);
  font-family: var(--font-body);
  font-size: var(--text-caption);
  color: var(--color-amber-text);
  animation: fade-slide-in var(--duration-slow) var(--ease-out);
}
.downgrade-alert span { flex: 1; }
.downgrade-alert .btn { flex-shrink: 0; }
.downgrade-alert-dismiss {
  background: none; border: none; cursor: pointer;
  color: var(--color-amber-text); font-size: 18px; padding: 0 var(--space-1);
  opacity: 0.6; transition: opacity var(--duration-fast) var(--ease-default);
  border-radius: var(--radius-sm);
  min-width: 28px;
  min-height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.downgrade-alert-dismiss:hover { opacity: 1; }
.downgrade-alert-dismiss:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px rgba(59, 117, 88, 0.265);
  opacity: 1;
}

/* ── Feature Discovery Callout ───────────────────────────────────── */

.feature-callout {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  background: linear-gradient(135deg, var(--color-action-soft) 0%, var(--color-purple-bg, #f5f0ff) 100%);
  border: 1px solid var(--color-action-glow);
  border-radius: 10px;
  font-size: 13px;
  animation: fade-slide-in 0.3s ease;
  grid-column: 1 / -1;
  margin: 4px 0;
}
.feature-callout-body { flex: 1; }
.feature-callout-body strong { display: block; margin-bottom: 2px; color: var(--color-text-primary); }
.feature-callout-body p { margin: 0; color: var(--color-text-secondary); line-height: 1.4; }
.feature-callout-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}
.feature-callout-dismiss {
  background: none; border: none; cursor: pointer;
  color: var(--color-text-tertiary); font-size: 18px; padding: 0;
  opacity: 0.5; transition: opacity 0.15s;
}
.feature-callout-dismiss:hover { opacity: 1; }

/* ── Soft-Gate Field Q&A Panel ───────────────────────────────────── */

.fqa-gate-message {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 24px 16px;
  text-align: center;
  color: var(--color-text-secondary);
  font-size: 13px;
  line-height: 1.5;
}
.fqa-gate-message a {
  color: var(--color-action);
  cursor: pointer;
  font-weight: 500;
}
.fqa-gate-message a:hover { text-decoration: underline; }

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

/* ── Status Banners (inline error/warning/info) ────────────────────── */

.status-banner {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3, 12px);
  padding: var(--space-3, 12px) var(--space-4, 16px);
  border-radius: var(--radius-md, 8px);
  font-size: var(--text-small, 13px);
  line-height: 1.5;
  animation: emptyStateFadeIn 300ms var(--ease-out) both;
}
.status-banner--error {
  background: var(--color-red-bg, #FCE8E6);
  border: 1px solid rgba(227, 66, 52, 0.15);
  color: var(--color-red, #E34234);
}
.status-banner--warning {
  background: var(--color-amber-100, #FEF3C7);
  border: 1px solid rgba(217, 119, 6, 0.15);
  color: var(--color-amber-text, #8B6914);
}
.status-banner--info {
  background: var(--color-blue-100, #E8F2FC);
  border: 1px solid rgba(31, 122, 212, 0.15);
  color: var(--color-blue-600, #1F7AD4);
}
.status-banner__icon { flex-shrink: 0; margin-top: 1px; }
.status-banner__content { flex: 1; }
.status-banner__title { font-weight: 600; margin-bottom: 2px; }
.status-banner__action {
  flex-shrink: 0;
  padding: var(--space-1, 4px) var(--space-3, 12px);
  font-size: 12px;
  font-weight: 500;
  border-radius: 6px;
  cursor: pointer;
  border: 1px solid currentColor;
  background: transparent;
  color: inherit;
  transition: opacity 0.15s;
}
.status-banner__action:hover { opacity: 0.8; }

/* ── Connection Banner ─────────────────────────────────────────────── */

.connection-banner {
  position: fixed;
  top: var(--topbar-height, 48px);
  left: 0; right: 0;
  z-index: 180;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2, 8px);
  padding: var(--space-2, 8px) var(--space-4, 16px);
  font-size: 13px;
  font-weight: 500;
  transform: translateY(-100%);
  transition: transform 300ms var(--ease-out, cubic-bezier(0, 0, 0.2, 1));
}
.connection-banner--visible { transform: translateY(0); }
.connection-banner__dismiss {
  background: none; border: none; cursor: pointer;
  color: inherit; opacity: 0.6; padding: 2px;
  border-radius: var(--radius-sm, 4px);
  transition: opacity 0.15s;
  flex-shrink: 0;
}
.connection-banner__dismiss:hover { opacity: 1; }
.connection-banner--offline {
  background: var(--color-amber-100, #FEF3C7);
  color: var(--color-amber-text, #8B6914);
  border-bottom: 1px solid rgba(217, 119, 6, 0.2);
}
.connection-banner--online {
  background: var(--color-green-100, #DCFCE7);
  color: var(--color-green-700, #1E7E34);
  border-bottom: 1px solid rgba(30, 126, 52, 0.2);
}
.connection-banner--reconnecting {
  background: var(--color-blue-100, #E8F2FC);
  color: var(--color-blue-600, #1F7AD4);
  border-bottom: 1px solid rgba(31, 122, 212, 0.2);
}

/* ── Sidebar Skeleton / Error / Empty ──────────────────────────────── */

.sidebar-skeleton-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 12px;
}
.sidebar-skeleton-dot {
  width: 26px; height: 26px;
  border-radius: var(--radius-full, 9999px);
  flex-shrink: 0;
  background: linear-gradient(90deg, var(--color-ink-05, #F1F3F4) 25%, var(--color-ink-10, #E3E6E9) 50%, var(--color-ink-05, #F1F3F4) 75%);
  background-size: 200% 100%;
  animation: skeletonShimmer 1.5s ease-in-out infinite;
}
.sidebar-skeleton-name {
  height: 12px; width: 70%;
  border-radius: var(--radius-sm, 4px);
  background: linear-gradient(90deg, var(--color-ink-05, #F1F3F4) 25%, var(--color-ink-10, #E3E6E9) 50%, var(--color-ink-05, #F1F3F4) 75%);
  background-size: 200% 100%;
  animation: skeletonShimmer 1.5s ease-in-out infinite;
}
.sidebar-error {
  padding: 16px 12px;
  text-align: center;
}
.sidebar-error-text {
  font-size: 12px;
  color: var(--color-ink-40, #9B9289);
  display: block;
  margin-bottom: 8px;
}
.sidebar-error-retry {
  font-size: 11px;
  padding: 4px 12px;
  border-radius: 6px;
  border: 1px solid var(--color-ink-20, #CFC9C2);
  background: transparent;
  color: var(--color-ink-60, #655D53);
  cursor: pointer;
  transition: background 0.15s;
}
.sidebar-error-retry:hover { background: var(--color-ink-05, #F1F3F4); }
.sidebar-empty {
  padding: 20px 12px;
  text-align: center;
}
.sidebar-empty-text {
  font-size: 12px;
  color: var(--color-ink-30, #B5ADA5);
  font-style: italic;
}

/* ── SSE Status Indicator ──────────────────────────────────────────── */

.sse-indicator {
  width: 6px; height: 6px;
  border-radius: var(--radius-full, 9999px);
  display: inline-block;
  margin-left: 6px;
  vertical-align: middle;
  transition: background 300ms;
}
.sse-indicator--connected { background: var(--color-green-600, #34A853); }
.sse-indicator--disconnected { background: var(--color-amber-500, #F59E0B); animation: sse-pulse 2s infinite; }
.sse-indicator--error { background: var(--color-red, #E34234); }

@keyframes sse-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}

/* ── Doc Row Skeleton ──────────────────────────────────────────────── */

.doc-row-skeleton td {
  padding: 12px 8px;
}
.doc-row-skeleton .skeleton-line {
  background: linear-gradient(90deg, var(--color-ink-05, #F1F3F4) 25%, var(--color-ink-10, #E3E6E9) 50%, var(--color-ink-05, #F1F3F4) 75%);
  background-size: 200% 100%;
  animation: skeletonShimmer 1.5s ease-in-out infinite;
  border-radius: var(--radius-sm, 4px);
}

/* ── New Space Drop Zone ───────────────────────────────────────────── */

/* Hint state: files are being dragged anywhere on the page */
.sidebar-new-space-btn.drop-hint {
  border-color: var(--color-action);
  background: var(--color-action-soft);
  animation: drop-hint-pulse 1.5s ease-in-out infinite;
}

@keyframes drop-hint-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(59, 117, 88, 0); }
  50% { box-shadow: 0 0 0 4px rgba(59, 117, 88, 0.13); }
}

/* Active state: files are directly over the button */
.sidebar-new-space-btn.drop-active {
  border-color: var(--color-action);
  border-style: dashed;
  background: var(--color-action-soft);
  box-shadow: 0 0 0 3px rgba(59, 117, 88, 0.105);
}

.sidebar-new-space-btn.drop-active .sidebar-label {
  color: var(--color-action);
}

.sidebar-new-space-btn.drop-active svg {
  color: var(--color-action);
}

/* Upload zone expanded state */
.sidebar-new-space-btn.upload-expanded {
  height: auto;
  min-height: 100px;
  flex-direction: column;
  align-items: stretch;
  padding: var(--space-3);
  border: 2px dashed var(--color-ink-200);
  border-radius: var(--radius-lg);
  background: var(--color-white);
  gap: var(--space-2);
  transition: border-color var(--duration-fast) var(--ease-default),
              background var(--duration-fast) var(--ease-default);
}

.sidebar-new-space-btn.upload-expanded:hover,
.sidebar-new-space-btn.upload-expanded.drop-active {
  border-color: var(--color-action);
  background: var(--color-action-soft);
}

.upload-zone-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) 0;
  cursor: pointer;
}

.upload-zone-label {
  font-family: var(--font-body);
  font-size: var(--text-caption);
  color: var(--color-ink-400);
  text-align: center;
  line-height: 1.4;
}

.upload-zone-label strong {
  color: var(--color-action);
}

.upload-zone-cancel {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  background: none;
  border: none;
  font-family: var(--font-body);
  font-size: var(--text-caption);
  color: var(--color-ink-400);
  cursor: pointer;
  padding: var(--space-1) 0;
}

.upload-zone-cancel:hover {
  color: var(--color-ink-600);
}

.sidebar-new-space-btn.uploading .upload-zone-content {
  opacity: 0.6;
  pointer-events: none;
}

/* Collapsed sidebar: keep the expanded drop zone VISIBLE as a compact
   target. The old `display: none` here made drag-over expand an invisible
   zone that still caught the drop (Creation Spine S1 fix). */
.sidebar.collapsed .sidebar-new-space-btn.upload-expanded {
  min-height: 72px;
  padding: var(--space-2);
}

.sidebar.collapsed .sidebar-new-space-btn.upload-expanded .upload-zone-label,
.sidebar.collapsed .sidebar-new-space-btn.upload-expanded .upload-zone-cancel {
  display: none;
}

/* ── upload-spinner-sm — compact inline spinner ─────────────────── */

.upload-spinner-sm {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 2px solid var(--color-ink-200);
  border-top-color: var(--color-action);
  animation: upload-spinner-spin 0.7s cubic-bezier(0.4, 0, 0.6, 1) infinite;
  flex-shrink: 0;
}

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

/* ── Phase: accepted — file received, timer running ─────────────── */

.nsb-accepted {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  width: 100%;
  padding: var(--space-2) 0 var(--space-1);
}

.nsb-accepted__row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
}

/* Spring-pop entrance for the check mark */
.nsb-accepted__check {
  flex-shrink: 0;
  animation: nsb-check-pop 0.4s var(--spring, cubic-bezier(0.34, 1.56, 0.64, 1)) both;
}

@keyframes nsb-check-pop {
  from { transform: scale(0); opacity: 0; }
  to   { transform: scale(1); opacity: 1; }
}

.nsb-accepted__filename {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--text-caption, 12px);
  font-family: var(--font-body);
  color: var(--color-ink-700, var(--text-primary));
}

.nsb-accepted__context-link {
  flex-shrink: 0;
  background: none;
  border: none;
  padding: 0;
  font-family: var(--font-body);
  font-size: var(--text-caption, 12px);
  color: var(--color-action);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
  white-space: nowrap;
}

.nsb-accepted__context-link:hover {
  color: var(--color-action-hover);
}

.nsb-accepted__verbs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-3);
  padding: 0 var(--space-1) var(--space-1);
}

/* Progress track — full width bar that drains over AUTO_PROCEED_MS */
.nsb-accepted__progress-track {
  width: 100%;
  height: 2px;
  background: var(--color-ink-100, var(--border-default));
  border-radius: var(--radius-full);
  overflow: hidden;
}

.nsb-accepted__progress-bar {
  height: 100%;
  background: var(--color-action);
  border-radius: var(--radius-full);
  /* Width and transition are set inline by the component */
}

/* ── Phase: context — timer paused, goal input visible ──────────── */

.nsb-context {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  width: 100%;
  padding: var(--space-2) 0 var(--space-1);
}

/* ── Typed path — describe the space, no document required ──────── */

.nsb-prompt {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  width: 100%;
  margin-top: var(--space-3);
}

/* The typed path is a peer of the drop zone, not its caption. The rule holds
   the instruction that used to live in the placeholder and disappear on the
   first keystroke. */
.nsb-prompt__rule {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-body);
  font-size: var(--text-caption);
  color: var(--color-ink-400);
  margin-bottom: var(--space-1);
}

.nsb-prompt__rule::before,
.nsb-prompt__rule::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border-default, var(--color-ink-100));
}

.nsb-prompt__hint {
  font-family: var(--font-body);
  font-size: var(--text-caption);
  color: var(--color-ink-400);
  margin: 0;
  text-align: center;
}

.nsb-prompt__verbs {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--space-1);
  width: 100%;
}

/* Hide the typed path when the collapsed sidebar shows the compact zone */
.sidebar.collapsed .nsb-prompt {
  display: none;
}

.nsb-context__header {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
}

.nsb-context__filename {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--text-caption, 12px);
  font-family: var(--font-body);
  color: var(--color-ink-600, var(--text-secondary));
}

.nsb-context__input {
  width: 100%;
  padding: var(--space-1) var(--space-2);
  font-family: var(--font-body);
  font-size: var(--text-caption, 12px);
  color: var(--color-ink);
  background: var(--color-ink-05);
  border: 1px solid var(--color-ink-200);
  border-radius: var(--radius-md);
  caret-color: var(--color-action);
  outline: none;
  transition: border-color var(--duration-fast) var(--ease-default),
              box-shadow var(--duration-fast) var(--ease-default);
  box-sizing: border-box;
}

.nsb-context__input:focus {
  border-color: var(--color-action);
  box-shadow: 0 0 0 2px var(--color-action-glow);
}

.nsb-context__input::placeholder {
  color: var(--color-ink-60);
  opacity: 1;
}

.nsb-context__actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.nsb-context__skip {
  background: none;
  border: none;
  padding: 0;
  font-family: var(--font-body);
  font-size: var(--text-caption, 12px);
  color: var(--color-ink-400);
  cursor: pointer;
}

.nsb-context__skip:hover {
  color: var(--color-ink-600);
}

/* ── D1: a link in the typed idea is a question, not an assumption ─ */
/* "build from this recipe site: <url>" and "track invoices, our portal is
   at <url>" are the same string shape and opposite intents. The composer
   asks; the server only fetches on the explicit answer. */

.nsb-link {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  width: 100%;
  margin-top: var(--space-2);
  padding: var(--space-2);
  border: 1px solid var(--color-ink-200);
  border-radius: var(--radius-md);
  background: var(--color-ink-50);
}

.nsb-link__ask {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--text-caption, 12px);
  line-height: 1.45;
  color: var(--color-ink-600, var(--text-secondary));
  overflow-wrap: anywhere;
}

.nsb-link__ask b {
  font-weight: 600;
  color: var(--color-ink-700, var(--text-primary));
}

.nsb-link__actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
}

/* ── Phase: error ────────────────────────────────────────────────── */

.nsb-error {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  padding: var(--space-2) 0;
  min-width: 0;
}

.nsb-error__msg {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--text-caption, 12px);
  font-family: var(--font-body);
  color: var(--color-red-text, #C5221F);
}

.nsb-error__retry {
  flex-shrink: 0;
  background: none;
  border: none;
  padding: 0;
  font-family: var(--font-body);
  font-size: var(--text-caption, 12px);
  color: var(--color-action);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
  white-space: nowrap;
}

.nsb-error__retry:hover {
  color: var(--color-action-hover);
}

/* Dark mode — token cascade handles color-ink-*, color-white, color-red-text, color-action.
   Only overrides that can't be handled by token redefinition are listed here. */
[data-theme="dark"] .nsb-context__input {
  /* --color-white inverts to #1F1C18 in dark mode — correct panel bg */
  background: var(--color-white);
  /* --color-ink-200 inverts to #302A24 in dark mode — correct subtle border */
  border-color: var(--color-ink-200);
}

[data-theme="dark"] .nsb-accepted__context-link,
[data-theme="dark"] .nsb-context__skip,
[data-theme="dark"] .nsb-error__retry {
  color: var(--color-action);
}

/* Compact sizing — nsb phases reduce zone to minimum needed height */
.sidebar-new-space-btn.upload-accepted,
.sidebar-new-space-btn.upload-context,
.sidebar-new-space-btn.upload-error {
  min-height: unset;
}

/* ── Provisioning sidebar item ────────────────────────────────────── */

.sidebar-space-item--provisioning {
  cursor: default;
  position: relative;
}

.sidebar-space-item--provisioning:hover {
  background: rgba(0,0,0,0.03);
}

/* Build info block — name + phase/elapsed below */
.sidebar-build-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.sidebar-build-meta {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.sidebar-build-phase {
  font-family: var(--font-mono);
  font-size: 0.65rem;
  color: var(--color-action);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sidebar-build-elapsed {
  font-family: var(--font-mono);
  font-size: 0.62rem;
  color: var(--color-ink-400);
  white-space: nowrap;
  flex-shrink: 0;
  margin-left: auto;
}

/* ═══════════════════════════════════════════════════════════════════
   Sidebar signal — the single trailing slot on every space row.
   One declarative family (.sidebar-signal*) renders whichever signal the
   row resolves to: creation chip (Review/Finalizing/Choose/Input), error
   actions (Retry + dismiss), needs-you count, working pulse, or the
   hover-revealed doc count. Rendered by
   react-islands/src/islands/sidebar/components/SpaceSignal.tsx.
   ═══════════════════════════════════════════════════════════════════ */

.sidebar-signal {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  margin-left: auto;
  flex-shrink: 0;
}

/* ── Creation lifecycle chips ────────────────────────────────────── */

.sidebar-signal-chip {
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  padding: 2px 6px;
  border-radius: var(--radius-sm);
  white-space: nowrap;
  line-height: 1.3;
}

/* Review is a user-blocking state — the build is waiting on YOU. It wears
   the amber attention family (same as Input/Choose and the needs-you badge):
   the old green read "all good" on a row whose glyph was already amber, and
   seven identical green chips carried no signal at all (2026-07-16 review).
   Green stays reserved for Finalizing — the AI at work after you confirm. */
.sidebar-signal-chip--review {
  background: var(--color-amber-bg);
  color: var(--color-amber-text);
}

.sidebar-signal-chip--finalizing {
  background: var(--color-action-soft);
  color: var(--color-action);
}

.sidebar-signal-chip--input {
  background: var(--color-amber-bg);
  color: var(--color-amber-text);
}

/* ── Needs-you count chip (amber, tooltip carries the breakdown) ─── */

.sidebar-signal-needs-you {
  box-sizing: border-box;
  min-width: 18px;
  padding: 2px 6px;
  border-radius: var(--radius-full);
  background: var(--color-amber-bg);
  color: var(--color-amber-text);
  font-family: var(--font-mono);
  font-size: 0.65rem;
  font-weight: 600;
  line-height: 1.3;
  text-align: center;
  white-space: nowrap;
}

/* ── Working pulse — quiet 2s breathe, no number ─────────────────── */

.sidebar-signal-working {
  width: 6px;
  height: 6px;
  border-radius: var(--radius-full);
  background: var(--color-action);
  animation: sidebar-signal-breathe 2s var(--ease-in-out) infinite;
}

@keyframes sidebar-signal-breathe {
  0%, 100% { opacity: 0.45; transform: scale(1); }
  50% { opacity: 1; transform: scale(1.25); }
}

/* ── Quiet: doc count, revealed on row hover/active ──────────────── */

.sidebar-signal-count {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  color: var(--text-muted);
  background: var(--color-ink-05);
  padding: 2px 7px;
  border-radius: var(--radius-sm);
  opacity: 0;
  transform: translateX(4px);
  transition:
    opacity var(--duration-normal, 0.2s) var(--ease-out, ease-out),
    transform var(--duration-normal, 0.2s) var(--ease-out, ease-out);
}

.sidebar-space-item:hover .sidebar-signal-count,
.sidebar-space-item.active .sidebar-signal-count {
  opacity: 1;
  transform: translateX(0);
}

/* ── Error actions (retry + dismiss) ─────────────────────────────── */

.sidebar-signal-actions {
  display: flex;
  align-items: center;
  gap: var(--space-1);
}

.sidebar-signal-retry {
  font-family: var(--font-body);
  font-size: 11px;
  color: var(--color-action);
  background: none;
  border: none;
  cursor: pointer;
  padding: 2px 6px;
  border-radius: var(--radius-sm);
  position: relative;
}

/* 44px hit area without growing the visual — anchored to the button's own
   box and biased left, away from the adjacent cancel control. */
.sidebar-signal-retry::after {
  content: "";
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  left: -8px;
  right: -2px;
  height: 44px;
}

.sidebar-signal-retry:hover {
  background: var(--color-action-soft);
}

/* A space whose setup failed is the row that MOST needs the user — it sits at
   the top of Needs-you and carries a Retry. It must not be dimmed or struck
   through: line-through reads "deleted", opacity reads "inactive", and both
   contradict the action sitting next to them. The error dot and the Retry
   control carry the state; the name stays fully legible. */
.sidebar-space-item--error .sidebar-space-name {
  color: var(--text-primary);
}

/* ── Cancel control (two-step delete) ────────────────────────────── */

/* Base cancel "x" button — hidden by default, appears on row hover;
   always visible inside error actions. */
.sidebar-signal-cancel {
  font-size: 14px;
  color: var(--color-ink-300);
  background: none;
  border: none;
  cursor: pointer;
  padding: 0 4px;
  border-radius: var(--radius-sm);
  line-height: 1;
  opacity: 0;
  transition:
    opacity var(--duration-fast, 0.15s) var(--ease-out, ease-out),
    color var(--duration-fast, 0.15s) var(--ease-out, ease-out),
    background var(--duration-fast, 0.15s) var(--ease-out, ease-out);
  flex-shrink: 0;
  position: relative;
}

/* 44px hit area on ALL pointer types — this destructive control sits next
   to the row's navigation area, so a fat-finger must land on the two-step
   confirm, not the space. Pseudo-element keeps the visual size intact. */
.sidebar-signal-cancel::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 44px;
  height: 44px;
  transform: translate(-50%, -50%);
}

.sidebar-space-item:hover .sidebar-signal-cancel,
.sidebar-signal-actions .sidebar-signal-cancel {
  opacity: 1;
}

.sidebar-signal-cancel:hover {
  color: var(--color-red-text);
  background: var(--color-red-bg);
}

/* Confirming state — inline "Delete? Yes / No" */
.sidebar-signal-cancel-confirm {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  flex-shrink: 0;
  animation: sidebar-signal-fade-in 0.15s var(--ease-out, ease-out);
}

@keyframes sidebar-signal-fade-in {
  from { opacity: 0; transform: translateX(4px); }
  to { opacity: 1; transform: translateX(0); }
}

.sidebar-signal-cancel-label {
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 600;
  color: var(--color-red-text);
  white-space: nowrap;
}

.sidebar-signal-cancel-yes {
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 600;
  color: var(--color-red-text);
  background: var(--color-red-bg);
  border: none;
  cursor: pointer;
  padding: 1px 6px;
  border-radius: var(--radius-sm);
  line-height: 1.4;
}

.sidebar-signal-cancel-yes:hover {
  background: var(--color-red-text);
  color: var(--color-white);
}

.sidebar-signal-cancel-no {
  font-family: var(--font-body);
  font-size: 10px;
  color: var(--color-ink-400);
  background: none;
  border: none;
  cursor: pointer;
  padding: 1px 4px;
  border-radius: var(--radius-sm);
  line-height: 1.4;
}

.sidebar-signal-cancel-no:hover {
  color: var(--color-ink);
  background: var(--color-ink-100);
}

/* ── Collapsed sidebar: signals and build meta hide entirely ─────── */

.sidebar.collapsed .sidebar-signal,
.sidebar.collapsed .sidebar-build-meta {
  display: none;
}

/* ── Reduced motion: pulse settles, fades snap ───────────────────── */

@media (prefers-reduced-motion: reduce) {
  .sidebar-signal-working {
    animation: none;
    opacity: 0.6;
  }
  .sidebar-signal-cancel-confirm {
    animation: none;
  }
  .sidebar-signal-count {
    transition: none;
    transform: none;
  }
}

/* ── Touch: hover-revealed signals render always-visible ─────────── */
/* Hover doesn't exist on touch — the quiet doc count (opacity 0 until row
   hover) and the creation cancel × would otherwise be invisible (the ×
   invisibly tappable). Desktop hover behavior is untouched. */

@media (hover: none) {
  .sidebar-signal-count {
    opacity: 1;
    transform: none;
  }
  .sidebar-signal-cancel {
    opacity: 1;
  }
}

/* ── Build progress card (floating next to sidebar) ──────────────── */

.build-card {
  position: fixed;
  z-index: 200;
  background: var(--color-white);
  border: 1px solid var(--color-ink-100);
  border-radius: var(--radius-xl);
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.08), 0 1px 4px rgba(0, 0, 0, 0.04);
  width: 280px;
  font-family: var(--font-body);
  opacity: 0;
  transform: translateX(-4px);
  animation: build-card-enter 200ms var(--ease-out) forwards;
  pointer-events: auto;
  overflow: hidden;
}

.build-card--review {
  border-color: var(--color-action-soft, rgba(59, 117, 88, 0.07));
}

.build-card--ready {
  border-color: var(--color-green-600);
}

@keyframes build-card-enter {
  to { opacity: 1; transform: translateX(0); }
}

/* Invisible hover bridge — fills gap between sidebar and card */
.build-card-bridge {
  pointer-events: auto;
}

/* Header: lattice + space info */
.build-card-header {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-4) var(--space-2);
}

.build-card-lattice {
  width: 48px;
  height: 48px;
  flex-shrink: 0;
  border-radius: 18px;
  overflow: hidden;
}

.build-card-lattice canvas {
  border-radius: 18px !important;
}

.build-card-titles {
  flex: 1;
  min-width: 0;
}

.build-card-name {
  font-size: var(--text-small);
  font-weight: 600;
  color: var(--color-ink);
  line-height: 1.3;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.build-card-doc {
  font-size: var(--text-caption);
  color: var(--color-ink-400);
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Current status line */
.build-card-status {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-4) var(--space-3);
}

.build-card-status-label {
  font-size: 13px;
  color: var(--color-action);
  font-weight: 500;
}

.build-card--review .build-card-status-label {
  color: var(--color-amber-text, #8B6914);
}

.build-card--ready .build-card-status-label {
  color: var(--color-green-text);
}

.build-card-status-elapsed {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--color-ink-300);
  white-space: nowrap;
  flex-shrink: 0;
}

/* Phase timeline */
.build-card-timeline {
  display: flex;
  flex-direction: column;
  gap: 0;
  padding: 0 var(--space-4) var(--space-3);
  position: relative;
}

/* Vertical line connecting dots */
.build-card-timeline::before {
  content: '';
  position: absolute;
  left: calc(var(--space-4) + 5px);
  top: 6px;
  bottom: 6px;
  width: 1px;
  background: var(--color-ink-100);
}

.build-card-step {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 3px 0;
  font-size: 12px;
  color: var(--color-ink-200);
  position: relative;
}

.build-card-step-dot {
  width: 11px;
  height: 11px;
  border-radius: 50%;
  flex-shrink: 0;
  border: 1.5px solid var(--color-ink-200);
  background: var(--color-white);
  position: relative;
  z-index: 1;
}

/* Completed step */
.build-card-step--completed {
  color: var(--color-ink-400);
}

.build-card-step--completed .build-card-step-dot {
  background: var(--color-action);
  border-color: var(--color-action);
}

/* Active step */
.build-card-step--active {
  color: var(--color-ink);
  font-weight: 500;
}

.build-card-step--active .build-card-step-dot {
  border-color: var(--color-action);
  background: var(--color-white);
  box-shadow: 0 0 0 3px rgba(59, 117, 88, 0.13);
}

/* Pending step */
.build-card-step--pending .build-card-step-dot {
  border-color: var(--color-ink-100);
}

/* Interactive review link */
.build-card-step-link {
  color: var(--color-action);
  text-decoration: none;
  font-weight: 500;
}

.build-card-step-link:hover {
  text-decoration: underline;
}

/* Progress bar */
.build-card-progress {
  height: 2px;
  background: var(--color-ink-50);
  margin: 0 var(--space-4) var(--space-3);
  border-radius: 1px;
  overflow: hidden;
}

.build-card-progress-fill {
  height: 100%;
  background: var(--color-action);
  border-radius: 1px;
  transition: width 0.6s var(--ease-out);
}

.build-card--ready .build-card-progress-fill {
  background: var(--color-green-600);
}

/* Error state */
.build-card-error {
  font-size: var(--text-caption);
  color: var(--color-red-text);
  background: var(--color-red-bg);
  padding: var(--space-2) var(--space-3);
  margin: 0 var(--space-3) var(--space-2);
  border-radius: var(--radius-sm);
  line-height: 1.4;
}

/* ── Cancel button in build card ────────────────────────────────────── */

.build-card-cancel {
  padding: var(--space-2) var(--space-4) var(--space-3);
  text-align: center;
}

.build-card-cancel-btn {
  background: none;
  border: none;
  color: var(--color-ink-300);
  font-size: 11px;
  cursor: pointer;
  font-family: inherit;
  padding: 2px 0;
  transition: color 0.15s;
}
.build-card-cancel-btn:hover {
  color: var(--color-red-text, #b5453c);
}

.build-card-cancel-confirm {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  animation: build-card-enter 150ms ease-out;
}

.build-card-cancel-label {
  font-size: 11px;
  color: var(--color-ink-400);
}

.build-card-cancel-yes {
  background: none;
  border: 1px solid var(--color-red-text, #b5453c);
  color: var(--color-red-text, #b5453c);
  font-size: 10px;
  font-family: inherit;
  padding: 2px 8px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.build-card-cancel-yes:hover {
  background: var(--color-red-text, #b5453c);
  color: var(--color-white);
}

.build-card-cancel-no {
  background: none;
  border: none;
  color: var(--color-ink-300);
  font-size: 10px;
  font-family: inherit;
  padding: 2px 4px;
  cursor: pointer;
}
.build-card-cancel-no:hover {
  color: var(--color-ink);
}

/* ── Disambiguation mode ───────────────────────────────────────────── */

.build-card--disambiguation {
  width: 380px;
  border-color: rgba(59, 117, 88, 0.22);
  box-shadow:
    0 4px 24px rgba(0, 0, 0, 0.08),
    0 1px 4px rgba(0, 0, 0, 0.04),
    0 0 20px rgba(59, 117, 88, 0.05);
}

.build-card--resolved {
  border-color: rgba(59, 117, 88, 0.175);
}

/* Close X button — top-right corner */
.build-card-close {
  position: absolute;
  top: 12px;
  right: 12px;
  background: none;
  border: none;
  color: var(--color-ink-300);
  cursor: pointer;
  padding: 4px;
  font-size: 14px;
  line-height: 1;
  opacity: 0.6;
  transition: opacity 0.15s var(--ease-out);
  z-index: 2;
}
.build-card-close:hover {
  opacity: 1;
}

/* Disambiguation content wrapper */
.build-card-disambiguation {
  padding: 0 var(--space-4) var(--space-3);
}

/* Question text — DISTLR's voice */
.build-card-question {
  font-size: 13px;
  color: var(--color-ink-300);
  line-height: 1.5;
  margin-bottom: var(--space-3);
}

/* Choice cards container */
.build-card-choices {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 14px;
}

/* Individual choice button */
.build-card-choice {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  text-align: left;
  background: var(--color-ink-50, rgba(0, 0, 0, 0.03));
  border: 1px solid var(--color-ink-100);
  border-radius: var(--radius-sm);
  padding: 10px 14px;
  color: var(--color-ink);
  cursor: pointer;
  transition: border-color 0.15s var(--ease-out),
              background 0.15s var(--ease-out),
              opacity 0.2s var(--ease-out);
  font-family: var(--font-body);
}
.build-card-choice:hover:not(:disabled):not(.build-card-choice--faded) {
  border-color: rgba(59, 117, 88, 0.355);
  background: rgba(59, 117, 88, 0.07);
}
.build-card-choice:focus-visible {
  outline: 2px solid var(--color-action);
  outline-offset: 1px;
}

/* Selected choice */
.build-card-choice--selected {
  border-color: rgba(59, 117, 88, 0.44);
  background: rgba(59, 117, 88, 0.09);
}

/* Non-selected choices fade when one is picked */
.build-card-choice--faded {
  opacity: 0.4;
  pointer-events: none;
}

/* Dot indicator inside choice */
.build-card-choice-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-ink-200);
  flex-shrink: 0;
  transition: background 0.2s var(--ease-out), box-shadow 0.2s var(--ease-out);
}
.build-card-choice--selected .build-card-choice-dot {
  background: var(--color-action);
  box-shadow: 0 0 6px rgba(59, 117, 88, 0.355);
}

/* Choice text content */
.build-card-choice-content {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
}
.build-card-choice-label {
  font-size: 12px;
  font-weight: 500;
  line-height: 1.3;
}
.build-card-choice-desc {
  font-size: 11px;
  color: var(--color-ink-300);
  margin-top: 2px;
  line-height: 1.4;
}

/* Checkmark on selected choice */
.build-card-choice-check {
  color: var(--color-action);
  flex-shrink: 0;
}

/* Free-text input */
.build-card-freetext {
  position: relative;
  margin-bottom: 12px;
}
.build-card-freetext-input {
  width: 100%;
  background: var(--color-ink-50, rgba(0, 0, 0, 0.02));
  border: 1px solid var(--color-ink-100);
  border-radius: var(--radius-sm);
  padding: 9px 36px 9px 12px;
  color: var(--color-ink);
  font-size: 12px;
  font-family: var(--font-body);
  outline: none;
  box-sizing: border-box;
  transition: border-color 0.15s var(--ease-out);
}
.build-card-freetext-input::placeholder {
  color: var(--color-ink-300);
}
.build-card-freetext-input:focus {
  border-color: rgba(59, 117, 88, 0.355);
}
.build-card-freetext-hint {
  position: absolute;
  right: 10px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--color-ink-300);
  font-size: 11px;
  pointer-events: none;
  opacity: 0.6;
}

/* Footer: countdown + DISTLR link */
.build-card-disambiguation-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

/* Countdown bar + text */
.build-card-countdown {
  display: flex;
  align-items: center;
  gap: 6px;
}
.build-card-countdown-bar {
  width: 60px;
  height: 2px;
  background: var(--color-ink-100);
  border-radius: 1px;
  overflow: hidden;
}
.build-card-countdown-fill {
  height: 100%;
  background: rgba(59, 117, 88, 0.265);
  border-radius: 1px;
  transition: width 1s linear;
}
.build-card-countdown-text {
  font-size: 11px;
  color: var(--color-ink-300);
  opacity: 0.7;
}

/* DISTLR escape link */
.build-card-distlr-link {
  background: none;
  border: none;
  color: var(--color-action);
  font-size: 11px;
  cursor: pointer;
  padding: 2px 0;
  font-family: var(--font-body);
  opacity: 0.8;
  transition: opacity 0.15s var(--ease-out);
}
.build-card-distlr-link:hover {
  opacity: 1;
}
.build-card-distlr-link:disabled {
  opacity: 0.4;
  cursor: default;
}

/* Resolved acknowledgment */
.build-card-resolved {
  font-size: 12px;
  font-weight: 500;
  color: var(--color-action);
}

/* Trailing chips/badges/counts: see the consolidated ".sidebar-signal"
   family (search: "Sidebar signal") — one block, one component. */

/* ── Reduced Motion ────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  .connection-banner { transition: none; }
  .status-banner { animation: none; }
  .sidebar-skeleton-dot,
  .sidebar-skeleton-name,
  .doc-row-skeleton .skeleton-line,
  .sse-indicator--disconnected { animation: none; }
  .build-card { animation: none; opacity: 1; transform: none; }
  .build-card-progress-fill { transition: none; }
}

/* ── Skeleton Loading ── */
.skeleton { position: relative; overflow: hidden; background: var(--color-ink-50); border-radius: 6px; }
.skeleton::after {
  content: ''; position: absolute; top: 0; left: -60%; width: 60%; height: 100%;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.6), transparent);
  animation: skeletonShimmer 2.2s ease-in-out infinite;
}
.skeleton-text { height: 12px; border-radius: 6px; }
.skeleton-avatar { width: 32px; height: 32px; border-radius: 50%; }

/* ── btn-text variant ── */
.btn-text {
  background: transparent; border: none; color: var(--color-ink-400);
  font-family: var(--font-body); font-size: 13px; font-weight: 500;
  padding: 8px 12px; border-radius: var(--radius-md); cursor: pointer;
  transition: color 0.15s;
}
.btn-text:hover { color: var(--color-ink-600); }
.btn-text.danger:hover { color: var(--color-red); }

/* ── Tooltips ── */
.tooltip { position: relative; }
.tooltip::after {
  content: attr(data-tooltip);
  position: absolute;
  font-family: var(--font-body); font-size: 12px;
  color: var(--color-white); background: var(--color-ink);
  padding: 6px 10px; border-radius: var(--radius-sm);
  white-space: nowrap; pointer-events: none;
  opacity: 0; transform: translateY(4px);
  transition: opacity 0.15s, transform 0.15s;
  z-index: 1000;
}
.tooltip:hover::after { opacity: 1; transform: translateY(0); }
.tooltip-top::after { bottom: calc(100% + 6px); left: 50%; transform: translateX(-50%) translateY(4px); }
.tooltip-top:hover::after { transform: translateX(-50%) translateY(0); }
.tooltip-bottom::after { top: calc(100% + 6px); left: 50%; transform: translateX(-50%) translateY(-4px); }
.tooltip-bottom:hover::after { transform: translateX(-50%) translateY(0); }
/* Dashboard Island — Scoped styles
   Extracted from public/style.css during React migration.
   Uses --ri-* design tokens via the .ri-root wrapper. */

/* Dashboard container */
.dashboard {
  padding: 0 1.5rem 1.5rem;
}

/* ==========================================================================
   Dashboard v2 — Conversational AI Home
   ========================================================================== */

.dash-v2 {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 var(--space-12) var(--space-16);
}

/* ---- Hero row: DISTLR avatar + greeting ---- */
.dash-hero {
  display: flex;
  align-items: center;
  /* Duplicated in react-islands/src/islands/dashboard/dashboard.css. This
     file loads LATER, so on equal specificity it wins — which is how an edit
     to the component copy alone left the old ring and the old gap on screen.
     Change both, or delete this one. */
  gap: var(--space-10);
  padding: var(--space-10) 0 var(--space-8);
  border-bottom: 1px solid var(--color-ink-20);
  margin-bottom: var(--space-8);
}
.dash-hero-avatar {
  flex-shrink: 0;
  position: relative;
  width: 128px;
  height: 128px;
  animation: distlr-hello var(--duration-slow) var(--spring) both;
  animation-delay: var(--duration-enter);
}
@keyframes distlr-hello {
  0%   { opacity: 0; transform: scale(0.3) rotate(-12deg); }
  50%  { opacity: 1; transform: scale(1.1) rotate(3deg); }
  70%  { transform: scale(0.96) rotate(-1deg); }
  100% { transform: scale(1) rotate(0deg); }
}
.dash-hero-avatar canvas {
  width: 128px;
  height: 128px;
  /* No enclosing shape — the lattice IS the mark. See the matching block in
     react-islands/src/islands/dashboard/dashboard.css: these rules exist in
     BOTH files, this one loads globally and wins on the dashboard, so editing
     only the component copy left the ring on screen. */
  border-radius: 0 !important;
  transition: filter var(--duration-slow) var(--ease-out);
}
.dash-hero--clear .dash-hero-avatar canvas {
  filter: drop-shadow(0 0 10px var(--color-green-50));
}
.dash-hero--attention .dash-hero-avatar canvas {
  filter: drop-shadow(0 0 10px var(--color-amber-50));
}
.dash-hero--working .dash-hero-avatar canvas {
  filter: drop-shadow(0 0 10px var(--color-action-soft));
}
.dash-hero-text {
  flex: 1;
  min-width: 0;
}

.dash-greeting {
  font-family: var(--font-display);
  font-size: var(--text-h1);
  font-weight: 400;
  font-style: italic;
  color: var(--text-primary);
  line-height: 1.2;
  margin-bottom: var(--space-1);
  animation: dashFadeUp var(--duration-slow) var(--ease-out) both;
  animation-delay: calc(var(--duration-enter) + var(--duration-fast));
}

.dash-greeting-sub {
  font-family: var(--font-body);
  font-size: var(--text-small);
  color: var(--color-ink-500);
  line-height: 1.5;
  margin-bottom: 0;
  animation: dashFadeUp var(--duration-slow) var(--ease-out) both;
  animation-delay: calc(var(--duration-enter) + var(--duration-normal));
}
.dash-greeting-sub a {
  color: var(--color-amber-600);
  font-weight: 500;
  text-decoration: none;
}
.dash-greeting-sub a:hover { text-decoration: underline; }

.dash-hero-meta {
  display: flex;
  gap: var(--space-5);
  margin-top: var(--space-3);
  font-family: var(--font-mono);
  font-size: var(--text-label);
  color: var(--color-ink-400);
  animation: dashFadeUp var(--duration-slow) var(--ease-out) both;
  animation-delay: calc(var(--duration-enter) + var(--duration-slow));
}
.dash-hero-meta strong { color: var(--color-ink-600); font-weight: 600; }
.dash-hero-meta .separator { color: var(--color-ink-200); }

.dash-hero-actions {
  display: flex;
  gap: var(--space-3);
  margin-top: var(--space-4);
  animation: dashFadeUp var(--duration-slow) var(--ease-out) both;
  animation-delay: calc(var(--duration-enter) + var(--duration-slow) + var(--duration-fast));
}

@keyframes dashFadeUp {
  from { opacity: 0; transform: translateY(var(--space-2)); }
  to { opacity: 1; transform: translateY(0); }
}

/* ---- Responsive: hero avatar scales down on smaller screens ---- */
@media (max-width: 768px) {
  .dash-hero-avatar,
  .dash-hero-avatar canvas {
    width: 80px;
    height: 80px;
  }
  .dash-hero { gap: var(--space-4); }
  .dash-greeting { font-size: 24px; }
}
@media (max-width: 480px) {
  .dash-hero-avatar,
  .dash-hero-avatar canvas {
    width: 56px;
    height: 56px;
  }
  .dash-hero { gap: var(--space-3); padding: var(--space-6) 0 var(--space-4); }
}

/* ---- Secondary grid: spaces + activity side-by-side ---- */
.dash-secondary {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-6);
  animation: dashFadeUp var(--duration-slow) var(--ease-out) both;
  animation-delay: calc(var(--duration-enter) * 3);
}
.dash-panel {
  background: var(--bg-card);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-xl);
  padding: var(--space-6);
}
.dash-panel-title {
  font-family: var(--font-display);
  font-size: var(--text-h3);
  font-weight: 500;
  color: var(--text-primary);
  margin-bottom: var(--space-4);
}

/* ---- Stats row (hidden — replaced by hero meta) ---- */
.dash-stats {
  display: none;
}

.dash-stat {
  display: flex;
  flex-direction: column;
  gap: 4px;
  background: var(--color-white, #FFF);
  border: 1px solid var(--color-ink-10);
  border-radius: 12px;
  padding: 16px 20px;
  min-width: 120px;
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}

.dash-stat:hover {
  transform: translateY(-2px);
  border-color: var(--color-ink-100);
  box-shadow: 0 4px 16px rgba(59, 117, 88, 0.07);
}

.dash-stat-num {
  font-family: var(--font-mono);
  font-size: 24px;
  font-weight: 600;
  color: var(--text-primary);
  line-height: 1;
}

.dash-stat-label {
  font-size: 12px;
  color: var(--color-ink-40);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.dash-stat-warn {
  color: var(--color-amber);
}

/* ---- Dashboard Usage Bar ---- */
.dash-usage-bar {
  display: flex;
  gap: var(--space-4);
  padding: var(--space-3) var(--space-4);
  background: var(--color-ink-05);
  border-radius: var(--radius-md);
  margin-bottom: var(--space-4);
  font-size: var(--text-caption);
  color: var(--color-ink-600);
  align-items: center;
  flex-wrap: wrap;
  animation: fade-slide-in var(--duration-slow) var(--ease-out);
}
.dash-usage-bar-plan {
  font-weight: 600;
  color: var(--color-ink-900, #16130E);
}
.dash-usage-bar-track {
  flex: 1;
  min-width: 80px;
  max-width: 160px;
  height: 6px;
  background: var(--color-ink-100);
  border-radius: var(--radius-full);
  overflow: hidden;
}
.dash-usage-bar-fill {
  height: 100%;
  border-radius: var(--radius-full);
  transition: width var(--duration-slow) var(--ease-default);
}
.dash-usage-bar-fill.level-ok { background: var(--color-green-600, #34A853); }
.dash-usage-bar-fill.level-warn { background: var(--color-amber, #E8A830); }
.dash-usage-bar-fill.level-danger { background: var(--color-red, #E34234); }
.dash-usage-bar-included {
  font-family: var(--font-mono, monospace);
  font-size: var(--text-label, 11px);
}
.dash-usage-bar-projection {
  font-family: var(--font-mono, monospace);
  font-size: var(--text-label, 11px);
  color: var(--color-amber, #E8A830);
}

/* ---- Quick actions ---- */
.dash-actions {
  display: flex;
  gap: var(--space-3);
  margin-bottom: var(--space-8);
}

/* PLG value reinforcement strip */
.dash-value-strip {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-4);
  border-radius: var(--radius-md);
  background: var(--color-ink-05);
  font-family: var(--font-body);
  font-size: var(--text-caption);
  color: var(--color-ink-600);
  flex-wrap: wrap;
  animation: fadeInUp var(--duration-slow) var(--ease-out);
}
.dash-value-item strong {
  font-family: var(--font-mono);
  font-weight: 600;
  color: var(--color-ink-900);
  font-size: var(--text-small);
  font-variant-numeric: tabular-nums;
}
.dash-value-period {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: var(--text-label);
  color: var(--color-ink-40);
}
@keyframes fadeInUp {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}

.dash-action-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-md);
  font-family: var(--font-body);
  font-size: var(--text-caption);
  font-weight: 500;
  cursor: pointer;
  transition: all var(--duration-enter) var(--ease-default);
  border: none;
}

.dash-action-btn.primary {
  background: var(--color-action);
  color: var(--color-white, #FFF);
  position: relative;
  overflow: hidden;
  border: 1px solid var(--color-action-hover);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.15), 0 1px 2px rgba(0,0,0,0.06);
}

.dash-action-btn.primary::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at var(--ripple-x, 50%) var(--ripple-y, 50%), rgba(255, 255, 255, 0.25) 0%, transparent 60%);
  opacity: 0;
  transition: opacity 0.3s;
  pointer-events: none;
}

.dash-action-btn.primary:active::after {
  opacity: 1;
}

.dash-action-btn.primary:hover {
  background: var(--color-action-hover);
  transform: translateY(-1px) scale(1.02);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.2), 0 3px 10px var(--color-action-glow);
}

.dash-action-btn.secondary {
  background: var(--color-white, #FFF);
  color: var(--color-ink-80);
  border: 1px solid var(--color-ink-10);
}

.dash-action-btn.secondary:hover {
  border-color: var(--color-ink-20);
  transform: translateY(-1px);
}

/* Space picker dropdown */
.dash-space-picker {
  position: absolute;
  top: 100%;
  left: 0;
  margin-top: 4px;
  background: var(--color-white, #FFF);
  border: 1px solid var(--color-ink-10);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  min-width: 200px;
  max-height: 240px;
  overflow-y: auto;
  z-index: var(--z-dropdown);
  padding: 4px;
}
.dash-space-picker-item {
  display: block;
  width: 100%;
  text-align: left;
  padding: 8px 12px;
  border: none;
  background: none;
  font-size: var(--text-small);
  color: var(--color-ink-80);
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.dash-space-picker-item:hover {
  background: var(--color-action-soft);
  color: var(--color-action);
}

/* ---- Section heads ---- */
.dash-section {
  margin-bottom: 36px;
  animation: sectionFadeIn 0.4s cubic-bezier(0.4, 0, 0.2, 1) both;
}

.dash-section:nth-child(2) { animation-delay: 80ms; }
.dash-section:nth-child(3) { animation-delay: 160ms; }
.dash-section:nth-child(4) { animation-delay: 240ms; }

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

.dash-section-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 14px;
}

.dash-section-title {
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 500;
  color: var(--text-primary);
}

.dash-section-badge {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  background: var(--color-action-soft);
  color: var(--color-action);
  padding: 2px 8px;
  border-radius: 5px;
}

.dash-section-badge.warn {
  background: var(--color-amber-bg);
  color: var(--color-amber-text);
}

.dash-section-link {
  margin-left: auto;
  font-size: 12px;
  font-weight: 500;
  color: var(--primary);
  cursor: pointer;
}

.dash-section-link:hover {
  text-decoration: underline;
}

/* ---- Pinned spaces grid ---- */
.dash-spaces-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
}

.dash-space-card {
  border: 1px solid var(--color-ink-10);
  border-radius: 14px;
  padding: 18px 20px;
  cursor: pointer;
  transition: all 0.2s;
  text-decoration: none;
  color: inherit;
  display: block;
}

.dash-space-card:hover {
  border-color: var(--primary-light);
  transform: translateY(-2px);
  box-shadow: 0 6px 20px rgba(0,0,0,0.06);
}

.dash-space-card-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
}

.dash-space-icon {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  font-weight: 700;
  color: var(--color-white, #FFF);
  flex-shrink: 0;
}

.dash-space-name {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-primary);
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.dash-space-desc {
  font-size: 12px;
  color: var(--color-ink-40);
  line-height: 1.5;
  margin-bottom: 12px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.dash-space-footer {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 12px;
  color: var(--color-ink-40);
}

.dash-space-stat {
  font-family: var(--font-mono);
  font-size: 11px;
}

.dash-space-stat strong {
  color: var(--color-ink-60);
  font-weight: 600;
}

.dash-space-health {
  flex: 1;
  height: 4px;
  background: var(--color-ink-05);
  border-radius: 2px;
  overflow: hidden;
}

.dash-space-health-fill {
  height: 100%;
  border-radius: 2px;
}

.dash-space-health-fill.good { background: var(--color-green); }
.dash-space-health-fill.ok { background: var(--color-amber); }
.dash-space-health-fill.low { background: var(--color-red); }

.dash-space-time {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--color-ink-20);
  white-space: nowrap;
}

/* ---- Other spaces (compact rows) ---- */
.dash-spaces-list {
  display: flex;
  flex-direction: column;
}

.dash-space-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--color-ink-05);
  cursor: pointer;
  transition: all 0.15s;
  text-decoration: none;
  color: inherit;
}

.dash-space-row:hover {
  background: var(--color-ink-05);
  margin: 0 -8px;
  padding: 10px 8px;
  border-radius: 6px;
}

.dash-space-row:last-child { border: none; }

.dash-space-row-icon {
  width: 24px;
  height: 24px;
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  font-weight: 700;
  color: var(--color-white, #FFF);
  flex-shrink: 0;
}

.dash-space-row-name {
  font-size: 14px;
  font-weight: 500;
  color: var(--text-primary);
  flex: 1;
}

.dash-space-row-stat {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--color-ink-40);
  flex-shrink: 0;
}

.dash-space-row-health {
  width: 60px;
  height: 3px;
  background: var(--color-ink-05);
  border-radius: 2px;
  overflow: hidden;
  flex-shrink: 0;
}

.dash-space-row-health-fill {
  height: 100%;
  border-radius: 2px;
}

.dash-space-row-time {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--color-ink-20);
  flex-shrink: 0;
  width: 50px;
  text-align: right;
}

/* ---- Space outcome chips ---- */
.dash-space-row-outcomes {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--text-label);
  font-weight: 500;
  flex-shrink: 0;
}
.dash-outcome-chip { white-space: nowrap; }
.dash-outcome-chip.approved { color: var(--color-green-700); }
.dash-outcome-chip.in-review { color: var(--color-amber-600); }
.dash-outcome-chip.error { color: var(--color-red); }
.dash-outcome-dot { color: var(--color-ink-300); }
.dash-space-row-action {
  font-family: var(--font-body);
  font-size: var(--text-mono-sm);
  font-weight: 600;
  color: var(--primary);
  opacity: 0;
  transition: opacity var(--duration-normal) var(--ease-default);
  flex-shrink: 0;
}
.dash-space-row:hover .dash-space-row-action { opacity: 1; }

.dash-space-card-outcomes {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--text-label);
  font-weight: 500;
  margin-bottom: var(--space-3);
}

/* ---- Activity feed ---- */
.dash-activity-item {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--color-ink-05);
  animation: activityItemIn 0.3s ease-out both;
}

.dash-activity-item:nth-child(1) { animation-delay: 0ms; }
.dash-activity-item:nth-child(2) { animation-delay: 40ms; }
.dash-activity-item:nth-child(3) { animation-delay: 80ms; }
.dash-activity-item:nth-child(4) { animation-delay: 120ms; }
.dash-activity-item:nth-child(5) { animation-delay: 160ms; }
.dash-activity-item:nth-child(6) { animation-delay: 200ms; }
.dash-activity-item:nth-child(7) { animation-delay: 240ms; }
.dash-activity-item:nth-child(8) { animation-delay: 280ms; }
.dash-activity-item:nth-child(9) { animation-delay: 320ms; }
.dash-activity-item:nth-child(10) { animation-delay: 360ms; }

@keyframes activityItemIn {
  from { opacity: 0; transform: translateX(-8px); }
  to { opacity: 1; transform: translateX(0); }
}

.dash-activity-item:last-child { border: none; }

.dash-activity-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
  margin-top: 5px;
}

.dash-activity-dot.extract { background: var(--color-green); }
.dash-activity-dot.error { background: var(--color-red); }
.dash-activity-dot.review { background: var(--color-amber); }
.dash-activity-dot.new { background: var(--primary); }

.dash-activity-text {
  flex: 1;
  font-size: 13px;
  color: var(--color-ink-60);
  line-height: 1.5;
}

.dash-activity-text strong {
  color: var(--color-ink-80);
  font-weight: 500;
}

.dash-activity-time {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--color-ink-20);
  flex-shrink: 0;
  margin-top: 3px;
}

.dash-activity-link {
  cursor: pointer;
  border-radius: 8px;
  margin: 0 -8px;
  padding: 10px 8px;
  transition: background 0.15s ease;
}

.dash-activity-link:hover {
  background: var(--color-ink-05);
}

.dash-activity-link:hover .dash-activity-text {
  color: var(--primary);
}

/* ---- Impact panel ---- */
.dash-impact-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2px;
  background: var(--color-ink-50);
  border-radius: var(--radius-lg);
  overflow: hidden;
  margin-bottom: var(--space-4);
}
.dash-impact-stat {
  background: var(--bg-card);
  padding: var(--space-5) var(--space-4);
  cursor: pointer;
  transition: background var(--duration-normal) var(--ease-default);
  position: relative;
}
.dash-impact-stat:hover { background: var(--color-ink-50); }
.dash-impact-stat::after {
  content: '\2192';
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
  font-size: var(--text-mono-sm);
  color: var(--color-ink-300);
  opacity: 0;
  transform: translateX(calc(var(--space-1) * -1));
  transition: all var(--duration-enter) var(--ease-out);
}
.dash-impact-stat:hover::after { opacity: 1; transform: translateX(0); }
.dash-impact-value {
  font-family: var(--font-display);
  font-size: var(--text-h2);
  font-weight: 400;
  line-height: 1;
  color: var(--text-primary);
  letter-spacing: -0.5px;
  margin-bottom: var(--space-1);
}
.dash-impact-value.green { color: var(--color-green-600); }
.dash-impact-value.blue { color: var(--primary); }
.dash-impact-label {
  font-size: var(--text-label);
  font-weight: 500;
  color: var(--color-ink-400);
  text-transform: uppercase;
  letter-spacing: 1px;
}
.dash-impact-detail {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--color-ink-50);
  font-family: var(--font-body);
  font-size: var(--text-caption);
  color: var(--color-ink-600);
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-default);
}
.dash-impact-detail:hover { background: var(--color-ink-50); }
.dash-impact-detail:last-child { border: none; }
.dash-impact-detail-icon {
  width: var(--space-5);
  height: var(--space-5);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  font-size: var(--text-small);
}
.dash-impact-detail-text { flex: 1; }
.dash-impact-detail-meta {
  font-family: var(--font-mono);
  font-size: var(--text-label);
  color: var(--color-ink-400);
  flex-shrink: 0;
}
.dash-impact-detail-action {
  font-size: var(--text-mono-sm);
  font-weight: 600;
  color: var(--primary);
  opacity: 0;
  transition: opacity var(--duration-normal) var(--ease-default);
}
.dash-impact-detail:hover .dash-impact-detail-action { opacity: 1; }
.dash-impact-empty {
  font-family: var(--font-body);
  font-size: var(--text-caption);
  font-style: italic;
  color: var(--color-ink-400);
  text-align: center;
  padding: var(--space-8) var(--space-4);
}

/* ---- Empty / all-clear ---- */
.dash-empty {
  text-align: center;
  padding: 24px 20px;
  color: var(--color-ink-40);
  font-size: 14px;
}

.dash-empty-rich {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 36px 20px;
  text-align: center;
}

.dash-empty-rich svg {
  opacity: 0.5;
}

.dash-empty-rich-text {
  font-size: 13px;
  color: var(--color-ink-40);
  max-width: 280px;
  line-height: 1.5;
}

/* ---- Welcome card (empty state) ---- */
.dash-welcome-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  background: linear-gradient(180deg, var(--alembic-wash) 0%, var(--alembic-ghost) 100%);
  border: 1px solid var(--color-action-soft);
  border-radius: 16px;
  padding: 48px 32px;
  margin-bottom: 36px;
  animation: welcomeEntry 0.5s cubic-bezier(0.4, 0, 0.2, 1) both;
}

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

.dash-welcome-icon {
  margin-bottom: 16px;
}

.dash-welcome-title {
  font-family: var(--font-display);
  font-style: italic;
  font-size: 22px;
  font-weight: 400;
  color: var(--text-primary);
  margin-bottom: 8px;
  line-height: 1.3;
}

.dash-welcome-desc {
  font-size: 14px;
  color: var(--color-ink-40);
  max-width: 380px;
  line-height: 1.6;
  margin-bottom: 24px;
}

/* ---- Elevated stat card (needs input) ---- */
.dash-stat--elevated {
  background: linear-gradient(135deg, var(--color-amber-50, #FFFDF7), var(--color-white, #FFF));
  border-color: var(--color-amber-100, #EDE3C8);
}
.dash-stat--elevated .dash-stat-num {
  color: var(--color-amber-600, #D97706);
}

/* ---- DISTLR Intelligence header ---- */
.dash-intel-header { margin-bottom: 16px; }
.dash-intel-row { display: flex; align-items: center; gap: 14px; margin-bottom: 10px; }
.dash-intel-lattice { width: 28px; height: 28px; }
.dash-intel-title { font-family: var(--font-display); font-size: 19px; font-weight: 500; flex: 1; }
.dash-intel-badge {
  font-family: var(--font-mono); font-size: 11px; font-weight: 500;
  padding: 4px 14px; border-radius: 20px;
  display: flex; align-items: center; gap: 6px;
}
.dash-intel-badge.active { color: var(--color-purple); background: var(--color-purple-bg); }
.dash-intel-badge.clear { color: var(--color-green-text); background: var(--color-green-100); }
.dash-intel-dot {
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--color-purple);
  animation: dashIntelPulse 3s ease-in-out infinite;
}
@keyframes dashIntelPulse { 0%,100% { opacity: 0.4; } 50% { opacity: 1; } }
.dash-intel-stats {
  display: flex; gap: 24px;
  font-family: var(--font-mono); font-size: 11px; color: var(--color-ink-400);
}
.dash-intel-stats strong { color: var(--color-ink-600); font-weight: 600; }
.dash-intel-activity-link {
  font-family: var(--font-mono); font-size: 11px; color: var(--color-ink-400);
  text-decoration: none; margin-left: auto;
}
.dash-intel-activity-link:hover { color: var(--color-ink-600); }
.dash-greeting-link {
  color: inherit; text-decoration: none; cursor: pointer;
}
.dash-greeting-link:hover { text-decoration: underline; }

/* ---- Activity feed time groups ---- */
.dash-activity-group-label {
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-ink-300, var(--color-ink-30));
  padding: 12px 0 4px;
}
.dash-activity-group-label:first-child {
  padding-top: 0;
}

/* ---- Responsive ---- */
@media (max-width: 768px) {
  .dash-v2 {
    padding: 20px 16px 48px;
  }

  .dash-stats {
    gap: 8px;
  }

  .dash-stat {
    flex: 1;
    min-width: 0;
    padding: 12px 14px;
  }

  .dash-stat-num {
    font-size: 20px;
  }

  .dash-secondary {
    grid-template-columns: 1fr;
  }

  .dash-spaces-grid {
    grid-template-columns: 1fr;
  }

  .dash-actions {
    flex-wrap: wrap;
  }

  .dash-welcome-card {
    padding: 32px 20px;
  }

  .dash-welcome-title {
    font-size: 18px;
  }
}

@media (max-width: 640px) {
  .dash-greeting {
    font-size: 22px;
  }

  .dash-stat-num {
    font-size: 18px;
  }

  .dash-space-row-health {
    display: none;
  }
}

/* ---- Stagger animations ---- */

/* Dashboard stat card stagger */
.dash-stat {
  animation: sectionFadeIn 400ms var(--ease-out) both;
}
.dash-stats .dash-stat:nth-child(1) { animation-delay: 80ms; }
.dash-stats .dash-stat:nth-child(2) { animation-delay: 140ms; }
.dash-stats .dash-stat:nth-child(3) { animation-delay: 200ms; }
.dash-stats .dash-stat:nth-child(4) { animation-delay: 260ms; }

/* Dashboard space card stagger */
.dash-space-card {
  animation: sectionFadeIn 400ms var(--ease-out) both;
}
.dash-spaces-grid .dash-space-card:nth-child(1) { animation-delay: 200ms; }
.dash-spaces-grid .dash-space-card:nth-child(2) { animation-delay: 260ms; }
.dash-spaces-grid .dash-space-card:nth-child(3) { animation-delay: 320ms; }
.dash-spaces-grid .dash-space-card:nth-child(n+4) { animation-delay: 380ms; }

/* Dashboard space row stagger */
.dash-space-row {
  animation: activityItemIn 300ms var(--ease-out) both;
}
.dash-spaces-list .dash-space-row:nth-child(1) { animation-delay: 300ms; }
.dash-spaces-list .dash-space-row:nth-child(2) { animation-delay: 360ms; }
.dash-spaces-list .dash-space-row:nth-child(3) { animation-delay: 420ms; }
.dash-spaces-list .dash-space-row:nth-child(n+4) { animation-delay: 480ms; }

/* ---- Provisioning/Error States (Dashboard) ---- */

.dash-space-card--provisioning {
  border: 1px dashed var(--border-light);
  cursor: default;
  opacity: 0.85;
}
.dash-space-card--provisioning:hover {
  transform: none;
  box-shadow: none;
}

.dash-space-provisioning {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: auto;
  padding-top: 8px;
}
.dash-space-provisioning-bar {
  height: 3px;
  background: var(--border-light);
  border-radius: 99px;
  overflow: hidden;
}
.dash-space-provisioning-fill {
  height: 100%;
  background: var(--primary, #2383e2);
  border-radius: 99px;
  animation: provision-slide 2s ease-in-out infinite;
}
@keyframes provision-slide {
  0%   { width: 10%; margin-left: 0; }
  50%  { width: 40%; margin-left: 30%; }
  100% { width: 10%; margin-left: 90%; }
}
.dash-space-provisioning-text {
  font-size: 12px;
  color: var(--primary, #2383e2);
  font-weight: 500;
}

.dash-space-card--error {
  border: 1px solid var(--color-red-bg, #fde8e6);
}
.dash-space-error {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 10px 12px;
  background: var(--color-red-bg, #fde8e6);
  border-radius: var(--radius-sm, 6px);
  font-size: 13px;
  color: var(--color-red, #e34234);
  margin-top: auto;
}

.dash-space-card--ready-flash {
  animation: readyCelebrate 800ms var(--spring);
}
@keyframes readyCelebrate {
  /* rgba(52, 168, 83, ...) = --color-green-600 (#34A853) */
  0%   { box-shadow: 0 0 0 0 rgba(52, 168, 83, 0.4); transform: scale(1); }
  30%  { box-shadow: 0 0 0 8px rgba(52, 168, 83, 0.2); transform: scale(1.02); }
  60%  { box-shadow: 0 0 0 4px rgba(52, 168, 83, 0.1); transform: scale(1); }
  100% { box-shadow: 0 0 0 0 rgba(52, 168, 83, 0); border-color: var(--color-green-200); }
}

.dash-space-row--provisioning {
  opacity: 0.7;
  cursor: default;
}
.dash-space-row--error {
  background: var(--color-red-bg);
  border-left: none;
}

/* ---- Dark mode overrides ---- */
[data-theme="dark"] .dash-stat {
  border-color: var(--color-ink-100);
  box-shadow: none;
}
[data-theme="dark"] .dash-stat:hover {
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
  border-color: var(--color-ink-200);
}

/* ---- Reduced motion ---- */
@media (prefers-reduced-motion: reduce) {
  .dash-stat,
  .dash-space-card,
  .dash-space-row,
  .dash-space-provisioning-fill,
  .dash-intel-dot {
    animation: none !important;
    transition: none !important;
  }
}
