/* =========================================================================
 * Design tokens — §4.1 of vantage-spec-v1.1-part1
 * ========================================================================= */
:root {
  --color-primary: #2A9D8F;
  --color-danger:  #E76F51;
  --color-warning: #E9C46A;
  --color-success: #57CC99;
  --color-surface: #FFFFFF;
  --color-bg:      #F4F1EE;
  --color-text:    #2D2D2D;
  /* --color-muted bumped from #9CA3AF (~2.5:1 on white, fails WCAG body)
     to a darker slate that meets 4.5:1 contrast on the white surface
     while staying clearly distinct from --color-text. No new colors. */
  --color-muted:   #6B7280;

  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 12px;

  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;

  --shadow-card: 0 1px 2px rgba(0,0,0,0.04), 0 4px 12px rgba(0,0,0,0.06);
  --shadow-pop:  0 4px 16px rgba(0,0,0,0.10), 0 2px 4px rgba(0,0,0,0.06);

  --font-sans:
    -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;

  /* Layout — top bar height referenced by setup-modal padding so the
     modal backdrop never overlaps the topbar visually. */
  --topbar-h: 56px;
}

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

html,
body {
  margin: 0;
  padding: 0;
  height: 100%;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

a {
  color: var(--color-primary);
  text-decoration: none;
}
a:hover {
  text-decoration: underline;
}

/* =========================================================================
 * View routing — controlled by [data-view] on #app
 * loading | auth | welcome | authed
 * (Setup is a modal overlay rendered inside #authed-view, NOT a top-level
 *  view, so the topbar + sign-out remain accessible behind it.)
 * ========================================================================= */
#app                              { min-height: 100%; }
#app .loading-screen,
#app #auth-view,
#app #welcome-view,
#app #authed-view,
#app #demo-view                   { display: none; }
#app[data-view="loading"] .loading-screen  { display: flex; }
#app[data-view="auth"]    #auth-view       { display: flex; }
#app[data-view="welcome"] #welcome-view    { display: flex; }
#app[data-view="authed"]  #authed-view     { display: flex; }
#app[data-view="demo"]    #demo-view       { display: block; }

/* =========================================================================
 * Loading
 * ========================================================================= */
.loading-screen {
  min-height: 100vh;
  align-items: center;
  justify-content: center;
}
.loading-spinner {
  width: 32px;
  height: 32px;
  border: 3px solid rgba(42, 157, 143, 0.2);
  border-top-color: var(--color-primary);
  border-radius: 50%;
  animation: spin 0.9s linear infinite;
}
@keyframes spin {
  to { transform: rotate(360deg); }
}

/* =========================================================================
 * Auth view (sign in / sign up card)
 * ========================================================================= */
#auth-view {
  min-height: 100vh;
  align-items: center;
  justify-content: center;
  padding: var(--space-5);
}

.auth-card {
  width: 100%;
  max-width: 440px;
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  padding: var(--space-7) var(--space-6);
}

.auth-card h1 {
  margin: 0 0 var(--space-2) 0;
  font-size: 30px;
  font-weight: 600;
  color: var(--color-primary);
  letter-spacing: -0.01em;
}

.auth-card .subtitle {
  margin: 0 0 var(--space-6) 0;
  color: var(--color-muted);
  font-size: 15px;
  line-height: 1.5;
}

.auth-card label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: var(--color-text);
  margin: var(--space-5) 0 var(--space-2) 0;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

.auth-card input[type="email"],
.auth-card input[type="password"],
.auth-card input[type="text"] {
  width: 100%;
  padding: 12px 14px;
  font-size: 15px;
  font-family: inherit;
  color: var(--color-text);
  background: var(--color-bg);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  outline: none;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.auth-card input:focus {
  border-color: var(--color-primary);
  background: var(--color-surface);
}

/* Two-column name row, shown only in signup mode. The grid provides
   horizontal rhythm; individual labels keep their default vertical
   spacing so they align with the email label below. The [hidden]
   override is required because `.name-fields-row { display: grid }`
   has equal specificity to the UA `[hidden] { display: none }` rule
   and source-order would otherwise let `display:grid` win. */
.name-fields-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-3);
}
.name-fields-row[hidden] {
  display: none;
}
.name-fields-row label:first-child {
  margin-top: var(--space-4);
}

.auth-card button.btn-primary {
  width: 100%;
  margin-top: var(--space-6);
  padding: 13px 18px;
  font-size: 15px;
  font-weight: 600;
  font-family: inherit;
  color: var(--color-surface);
  background: var(--color-primary);
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: opacity 0.15s ease;
}
.auth-card button.btn-primary:hover:not(:disabled) {
  opacity: 0.9;
}
.auth-card button.btn-primary:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

.auth-message {
  margin-top: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-sm);
  font-size: 14px;
  line-height: 1.5;
}
.auth-message[data-kind="error"] {
  background: rgba(231, 111, 81, 0.10);
  color: var(--color-danger);
}
.auth-message[data-kind="success"] {
  background: rgba(87, 204, 153, 0.12);
  color: #2f8a64;
}
.auth-message[data-kind="info"] {
  background: rgba(42, 157, 143, 0.10);
  color: var(--color-primary);
}

.auth-toggle {
  margin: var(--space-6) 0 0 0;
  text-align: center;
  color: var(--color-muted);
  font-size: 14px;
}
.auth-toggle a {
  margin-left: var(--space-1);
  font-weight: 600;
}

/* =========================================================================
 * Welcome view — card-sized footprint, centered like the auth card.
 * One unified visual style for both "new" (You're in) and "returning"
 * (Welcome back) modes: 380×380 ink card with canvas bloom, 4s.
 * Only the heading text differs between modes (set in showWelcome).
 * Ported from crm-index-v12-reference.html (lines ~446–456, ~2360–2450),
 * adapted so the animation is contained — never a fullscreen takeover.
 * ========================================================================= */
#welcome-view {
  min-height: 100vh;
  align-items: center;
  justify-content: center;
  padding: var(--space-5);
}
.welcome-card {
  position: relative;
  width: 100%;
  max-width: 380px;
  height: 380px;
  background: #2F4F4F;                /* deep ink — canvas drops bloom over this */
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  overflow: hidden;
}
.welcome-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}
.welcome-content {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: var(--space-6);
  text-align: center;
}
.welcome-heading {
  margin: 0 0 var(--space-3) 0;
  font-size: 28px;
  font-weight: 300;
  letter-spacing: -0.01em;
  color: #F5F1EA;                     /* paper-on-ink contrast */
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 0.7s ease 0.5s, transform 0.7s ease 0.5s;
}
.welcome-sub {
  margin: 0;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(245, 241, 234, 0.6);
  opacity: 0;
  transition: opacity 0.7s ease 1s;
}
.welcome-card.show .welcome-heading {
  opacity: 1;
  transform: translateY(0);
}
.welcome-card.show .welcome-sub {
  opacity: 1;
}

/* =========================================================================
 * Authed view — dashboard shell
 * Layout:
 *   ┌────────────────────────────────────────────────────────────────┐
 *   │  top-bar (z=200, sticky-feel)                                  │
 *   │   Vantage  ·  [org name | tool name]    [avatar ▾ dropdown]    │
 *   ├────────────────────────────────────────────────────────────────┤
 *   │  authed-main                                                   │
 *   │   (placeholder card; tab nav + tools land in Step 4)           │
 *   └────────────────────────────────────────────────────────────────┘
 *
 * The setup-overlay is rendered INSIDE this view as a modal sitting
 * below the topbar (so sign-out is always reachable). z-index discipline:
 *   topbar      = 200
 *   setup modal = 100
 *   dropdown    = 250 (above both)
 * ========================================================================= */
#authed-view {
  flex-direction: column;
  min-height: 100vh;
}

.top-bar {
  position: relative;       /* establishes stacking context */
  z-index: 200;
  display: flex;
  align-items: center;
  gap: var(--space-5);
  height: var(--topbar-h);
  padding: 0 var(--space-5);
  background: var(--color-surface);
  border-bottom: 1px solid rgba(0, 0, 0, 0.06);
  flex-shrink: 0;
}
.top-bar .brand {
  font-size: 16px;
  font-weight: 700;
  color: var(--color-primary);
  letter-spacing: -0.01em;
}
.top-bar .brand-sep {
  color: var(--color-muted);
  font-weight: 400;
  margin: 0 var(--space-2);
}
/* Context slot — shows org name on shell pages, tool name when inside
   a tool. Hidden visually when no value is set so the brand sits clean. */
.top-bar .context {
  font-size: 14px;
  font-weight: 500;
  color: var(--color-text);
  letter-spacing: -0.005em;
}
.top-bar .context:empty {
  display: none;
}
.top-bar-spacer {
  flex: 1;
}
.top-bar-actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

/* Signed-in user display — sits to the left of the avatar. Name shares
   the org-context size/weight; email is the muted secondary line. The
   block collapses entirely (no stray gap) until renderShellChrome
   fills the name in. Email hides below 768px per §4.2 mobile rules. */
.top-bar-user {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: center;
  line-height: 1.2;
  text-align: right;
  min-width: 0;
}
.top-bar-user:empty {
  display: none;
}
.top-bar-user-name {
  font-size: 14px;
  font-weight: 500;
  color: var(--color-text);
  letter-spacing: -0.005em;
  margin: 0;
  max-width: 240px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.top-bar-user-email {
  font-size: 12px;
  color: var(--color-muted);
  margin: 2px 0 0 0;
  max-width: 240px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.top-bar-user-name:empty,
.top-bar-user-email:empty {
  display: none;
}
@media (max-width: 768px) {
  .top-bar-user-email {
    display: none;
  }
}

/* Avatar + dropdown. Click avatar to toggle; click outside closes. */
.user-menu {
  position: relative;
}
.user-avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--color-primary);
  color: var(--color-surface);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  border: none;
  outline: none;
  transition: opacity 0.15s ease;
}
.user-avatar:hover {
  opacity: 0.88;
}
.user-dropdown {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  min-width: 220px;
  background: var(--color-surface);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-pop);
  padding: var(--space-2) 0;
  z-index: 250;
  opacity: 0;
  pointer-events: none;
  transform: translateY(-4px);
  transition: opacity 0.15s ease, transform 0.15s ease;
}
.user-dropdown.open {
  opacity: 1;
  pointer-events: all;
  transform: translateY(0);
}
.user-dropdown-header {
  padding: var(--space-2) var(--space-4) var(--space-3);
  border-bottom: 1px solid rgba(0, 0, 0, 0.06);
  margin-bottom: var(--space-2);
}
.user-dropdown-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--color-text);
  margin: 0;
}
.user-dropdown-email {
  font-size: 12px;
  color: var(--color-muted);
  margin: 2px 0 0 0;
  word-break: break-all;
}
.user-dropdown-item {
  display: block;
  width: 100%;
  padding: var(--space-2) var(--space-4);
  font-size: 13px;
  font-family: inherit;
  color: var(--color-text);
  background: transparent;
  border: none;
  text-align: left;
  cursor: pointer;
}
.user-dropdown-item:hover {
  background: var(--color-bg);
}
.user-dropdown-item.danger {
  color: var(--color-danger);
}

.authed-main {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6) var(--space-5);
}

.placeholder-card {
  max-width: 520px;
  width: 100%;
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  padding: var(--space-6);
}
.placeholder-card h2 {
  margin: 0 0 var(--space-3) 0;
  font-size: 18px;
  font-weight: 600;
}
.placeholder-card p {
  margin: 0;
  color: var(--color-muted);
  font-size: 13px;
}

/* =========================================================================
 * Setup modal — 3-step org setup wizard.
 * Overlay rendered inside #authed-view. Backdrop starts BELOW the top bar
 * (top: var(--topbar-h)) so the topbar (z=200) stays clickable above it.
 * ========================================================================= */
.setup-overlay {
  position: fixed;
  top: var(--topbar-h);
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(27, 27, 27, 0.18);
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-5);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
}
.setup-overlay.open {
  opacity: 1;
  pointer-events: all;
}
.setup-modal {
  width: 100%;
  max-width: 620px;
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-pop);
  padding: var(--space-7) var(--space-7);
  transform: scale(0.97) translateY(8px);
  transition: transform 0.2s ease;
}
.setup-overlay.open .setup-modal {
  transform: scale(1) translateY(0);
}
.setup-modal-header {
  margin-bottom: var(--space-6);
}
.setup-modal-header h2 {
  margin: 0;
  font-size: 26px;
  font-weight: 600;
  color: var(--color-primary);
  letter-spacing: -0.01em;
}

/* Stepper — three dots with labels showing wizard progress. */
.setup-stepper {
  display: flex;
  gap: var(--space-3);
  list-style: none;
  padding: 0;
  margin: var(--space-5) 0 0 0;
}
.setup-step {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex: 1;
  min-width: 0;
}
.setup-step-dot {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--color-bg);
  color: var(--color-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  font-weight: 600;
  flex-shrink: 0;
  transition: background 0.2s ease, color 0.2s ease;
}
.setup-step.active .setup-step-dot,
.setup-step.done   .setup-step-dot {
  background: var(--color-primary);
  color: var(--color-surface);
}
.setup-step-label {
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--color-muted);
  font-weight: 600;
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.setup-step.active .setup-step-label {
  color: var(--color-text);
}

/* Wizard panels — only one visible at a time (driven by [hidden]). */
.setup-panel[hidden] {
  display: none;
}
.setup-blurb {
  margin: 0 0 var(--space-5) 0;
  color: var(--color-text);
  font-size: 15px;
  line-height: 1.6;
}
.setup-panel label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: var(--color-text);
  margin: 0 0 var(--space-2) 0;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.setup-panel input[type="text"],
.setup-panel input[type="email"] {
  width: 100%;
  padding: 12px 14px;
  font-size: 15px;
  font-family: inherit;
  color: var(--color-text);
  background: var(--color-bg);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  outline: none;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.setup-panel input:focus {
  border-color: var(--color-primary);
  background: var(--color-surface);
}
.setup-error {
  margin-top: var(--space-3);
  font-size: 13px;
  color: var(--color-danger);
}

/* Footer actions — Skip (disabled in dev) + Continue / Send invites. */
.setup-modal-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-3);
  margin-top: var(--space-6);
}
.btn-ghost {
  padding: 11px 18px;
  font-size: 14px;
  font-weight: 500;
  font-family: inherit;
  color: var(--color-muted);
  background: transparent;
  border: 1px solid rgba(0, 0, 0, 0.10);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.btn-ghost:not(:disabled):hover {
  background: var(--color-bg);
  color: var(--color-text);
}
.btn-ghost:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}
.setup-modal-footer .btn-primary {
  padding: 11px 26px;
  font-size: 14px;
  font-weight: 600;
  font-family: inherit;
  color: var(--color-surface);
  background: var(--color-primary);
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: opacity 0.15s ease;
}
.setup-modal-footer .btn-primary:hover:not(:disabled) {
  opacity: 0.9;
}
.setup-modal-footer .btn-primary:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

/* Chip input — Step 3 invite-team. Valid emails are bold blue chips,
   invalid (failing the email regex) are red. Press Enter or comma to
   add a chip; Backspace on an empty input removes the last chip. */
.chip-input-wrap {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 8px;
  background: var(--color-bg);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  min-height: 84px;
  align-items: flex-start;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.chip-input-wrap:focus-within {
  border-color: var(--color-primary);
  background: var(--color-surface);
}
.chip-input {
  flex: 1;
  min-width: 200px;
  background: transparent !important;
  border: none !important;
  outline: none;
  font-size: 15px;
  font-family: inherit;
  padding: 5px;
  color: var(--color-text);
}
.invite-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 5px 5px 12px;
  border-radius: 20px;
  font-size: 13px;
  line-height: 1;
}
/* Valid chips use the teal primary (bold) — the original spec called for
   "bold blue" but blue isn't in the Vantage palette. Teal keeps palette
   discipline. Invalid chips use --color-danger (coral). */
.invite-chip.valid {
  background: rgba(42, 157, 143, 0.10);
  color: var(--color-primary);
  font-weight: 700;
}
.invite-chip.invalid {
  background: rgba(231, 111, 81, 0.12);
  color: var(--color-danger);
  font-weight: 600;
}
.invite-chip-remove {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.10);
  border: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  line-height: 1;
  color: inherit;
  padding: 0;
}
.invite-chip-remove:hover {
  background: rgba(0, 0, 0, 0.18);
}
.chip-counter {
  margin-top: var(--space-3);
  font-size: 13px;
  color: var(--color-muted);
}
.chip-counter.over {
  color: var(--color-danger);
  font-weight: 600;
}

/* =========================================================================
 * Toast — slides up from bottom-center, auto-dismisses after 3.5s.
 * Ported from crm-index-v12-reference.html (~lines 358-361, 2253-2259).
 * Kinds: default (ink) | success (green) | warning (yellow) | error (red).
 * ========================================================================= */
.toast {
  position: fixed;
  bottom: 32px;
  left: 50%;
  transform: translateX(-50%) translateY(12px);
  background: var(--color-text);
  color: var(--color-surface);
  padding: 10px 18px;
  border-radius: var(--radius-md);
  font-size: 13px;
  font-weight: 500;
  box-shadow: var(--shadow-pop);
  z-index: 9999;
  opacity: 0;
  pointer-events: none;
  max-width: calc(100vw - 48px);
  text-align: center;
  transition: opacity 0.25s ease, transform 0.25s ease;
}
.toast.show {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
.toast[data-kind="success"] {
  background: var(--color-success);
  color: var(--color-text);
}
.toast[data-kind="warning"] {
  background: var(--color-warning);
  color: var(--color-text);
}
.toast[data-kind="error"] {
  background: var(--color-danger);
  color: var(--color-surface);
}

/* =========================================================================
 * Account settings modal (§7.4) — opened from the avatar dropdown.
 * Three independent sections (Email | Workspace | First fund), each with
 * its own Save button and inline status line. Backdrop covers the full
 * viewport (no topbar carve-out like the setup wizard) since the user
 * can dismiss with the close button or Escape.
 * z-index discipline: account modal = 300 (above setup-overlay=100, top-
 * bar=200, dropdown=250) so it sits on top regardless of state.
 * ========================================================================= */
.account-overlay {
  position: fixed;
  inset: 0;
  background: rgba(27, 27, 27, 0.32);
  z-index: 300;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6) var(--space-5);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s ease;
}
.account-overlay.open {
  opacity: 1;
  pointer-events: all;
}
/* The modal itself is the scroll container (not the overlay) so that
   the sticky header can pin to the modal's top edge as content scrolls
   beneath it. max-height leaves a margin for the overlay padding. */
.account-modal {
  width: 100%;
  max-width: 560px;
  max-height: calc(100vh - 96px);
  overflow-y: auto;
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-pop);
  padding: 0 var(--space-6) var(--space-5);
  transform: scale(0.97) translateY(8px);
  transition: transform 0.18s ease;
}
.account-overlay.open .account-modal {
  transform: scale(1) translateY(0);
}
/* Header is sticky-pinned to the modal's top so the X is always reachable
   while scrolling through the sections. background must be opaque so
   content scrolls cleanly behind it. The negative side padding extends
   the surface to the modal's edge despite the inner padding. */
.account-modal-header {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin: 0 calc(-1 * var(--space-6)) var(--space-3);
  padding: var(--space-5) var(--space-6) var(--space-3);
  background: var(--color-surface);
  border-bottom: 1px solid rgba(0, 0, 0, 0.06);
}
.account-modal-header h2 {
  margin: 0;
  font-size: 22px;
  font-weight: 600;
  color: var(--color-primary);
  letter-spacing: -0.01em;
}
.account-close {
  background: transparent;
  border: none;
  color: var(--color-muted);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: var(--radius-sm);
  transition: background 0.15s ease, color 0.15s ease;
}
.account-close:hover {
  background: var(--color-bg);
  color: var(--color-text);
}
.account-section {
  padding: var(--space-5) 0;
  border-top: 1px solid rgba(0, 0, 0, 0.06);
}
.account-section:first-of-type {
  border-top: none;
  padding-top: var(--space-3);
}
.account-section h3 {
  margin: 0 0 var(--space-2) 0;
  font-size: 14px;
  font-weight: 600;
  color: var(--color-text);
  letter-spacing: 0.01em;
  text-transform: uppercase;
}
.account-section-blurb {
  margin: 0 0 var(--space-3) 0;
  font-size: 13px;
  color: var(--color-muted);
  line-height: 1.55;
}
.account-section label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--color-text);
  margin: var(--space-3) 0 var(--space-2) 0;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.account-section input[type="email"],
.account-section input[type="password"],
.account-section input[type="text"] {
  width: 100%;
  padding: 11px 14px;
  font-size: 15px;
  font-family: inherit;
  color: var(--color-text);
  background: var(--color-bg);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  outline: none;
  transition: border-color 0.15s ease, background 0.15s ease, opacity 0.15s ease;
}
.account-section input:focus {
  border-color: var(--color-primary);
  background: var(--color-surface);
}
.account-section input:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}
.account-section-helper {
  margin: var(--space-2) 0 0 0;
  font-size: 12px;
  color: var(--color-muted);
  line-height: 1.45;
}
.account-section .btn-primary {
  margin-top: var(--space-3);
  padding: 10px 18px;
  font-size: 14px;
  font-weight: 600;
  font-family: inherit;
  color: var(--color-surface);
  background: var(--color-primary);
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: opacity 0.15s ease;
}
.account-section .btn-primary:hover:not(:disabled) {
  opacity: 0.9;
}
.account-section .btn-primary:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}
.account-msg {
  margin-top: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  font-size: 13px;
  line-height: 1.5;
}
.account-msg[data-kind="error"] {
  background: rgba(231, 111, 81, 0.10);
  color: var(--color-danger);
}
.account-msg[data-kind="success"] {
  background: rgba(87, 204, 153, 0.12);
  color: #2f8a64;
}
.account-msg[data-kind="info"] {
  background: rgba(42, 157, 143, 0.10);
  color: var(--color-primary);
}

/* =========================================================================
 * Terms & Privacy — nested modal. Always opens in-app, never a new tab.
 * Three parent surfaces: account-overlay (z=300), signup-overlay (z=310),
 * or the standalone auth view (no overlay). terms-overlay sits at z=320
 * so it always stacks above whichever parent is mounted.
 *
 * Close behaviour branches on parent context (wired in js/terms.js):
 *   account context:
 *     X-button       → close terms only; account modal remains open.
 *     Backdrop click → close BOTH (terms + account); return to dashboard.
 *     Escape         → close BOTH (one keystroke out of the whole stack).
 *   signup / auth context:
 *     X-button / Backdrop / Escape → close terms only; parent untouched.
 *     The signup form (or sign-in form) keeps every field the user typed.
 *
 * Width: defaults to 560px (matches account-modal). When opened over the
 * 480px signup-modal, .terms-overlay.over-signup shrinks the inner card
 * to match — CLAUDE.md modal sizing rule.
 *
 * Content is rendered via <iframe src="terms-and-privacy.html"> so the
 * standalone page stays the canonical document; the modal just frames
 * it. The iframe sits inside a beige content well below the sticky
 * header so the page's centered white card reads cleanly.
 * ========================================================================= */
.terms-overlay {
  position: fixed;
  inset: 0;
  background: rgba(27, 27, 27, 0.32);
  z-index: 320;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6) var(--space-5);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s ease;
}
/* When the parent is the 480px signup-modal, the nested terms modal
   shrinks to match so the two read as a clean stack rather than a
   wider overlay swallowing a narrower one. Per CLAUDE.md modal sizing
   rule: nested matches parent exactly. */
.terms-overlay.over-signup .terms-modal {
  max-width: 480px;
}
.terms-overlay.open {
  opacity: 1;
  pointer-events: all;
}
.terms-modal {
  width: 100%;
  /* Match .account-modal width + max-height so the terms modal
     reads as a swap of the account modal behind it.

     .account-modal has no `height` or `min-height` rule — it's
     content-driven and grows until it hits its max-height ceiling
     (which it does in practice once the email/workspace/fund
     sections populate). Terms-modal's content is an iframe, which
     doesn't push the flex column out on its own, so we set
     `height: calc(100vh - 96px)` — identical to max-height — and
     the modal always renders at its ceiling, matching what the
     account modal renders at in the common case.

     display:flex + flex-direction:column gives the inner
     .terms-iframe-wrap a concrete parent height to resolve its
     flex:1 1 0 against, which is what finally lets the iframe
     fill the modal. */
  max-width: 560px;
  max-height: calc(100vh - 96px);
  height: calc(100vh - 96px);
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-pop);
  transform: scale(0.97) translateY(8px);
  transition: transform 0.18s ease;
  display: flex;
  flex-direction: column;
  overflow: hidden;          /* clip iframe corners to the modal radius */
}
.terms-overlay.open .terms-modal {
  transform: scale(1) translateY(0);
}
/* Sticky header mirrors account-modal-header — same height + alignment
   so the X sits in the user's expected spot when transitioning between
   the two modals. */
.terms-modal-header {
  position: sticky;
  top: 0;
  background: var(--color-surface);
  padding: var(--space-4) var(--space-5);
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-bottom: 1px solid #ECECEC;
  flex-shrink: 0;
}
.terms-modal-header h2 {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
}
/* Two-line heading group: title on top, "Last updated" subline below.
   Lives inside the sticky modal header so the date is always visible
   regardless of scroll position, and so the iframe content can drop
   the duplicate H1/last-updated lines (handled via ?embedded=true).
   Flex column with a 2px gap keeps the two lines tight without
   breaking the modal-header's center vertical alignment with the
   X button on the right. */
.terms-modal-heading {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.terms-modal-subhead {
  margin: 0;
  font-size: 12px;
  line-height: 1.4;
  color: var(--color-muted);
}
.terms-close {
  background: none;
  border: none;
  color: var(--color-muted);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: var(--radius-sm);
}
.terms-close:hover {
  color: var(--color-text);
  background: rgba(0, 0, 0, 0.04);
}
/* The iframe area fills whatever vertical space is left below the
   sticky header. background=var(--color-bg) lets the embedded page's
   centered card sit naturally on the beige surface it was designed
   for, without introducing a third nested-card edge.

   The full chain that makes `height: 100%` on the iframe actually
   resolve to "fill the modal":
     1. .terms-modal has a concrete height (calc(100vh - 96px)).
     2. .terms-modal is display:flex / flex-direction:column.
     3. This wrap is flex:1 1 0 — take all remaining vertical
        space, basis zero so siblings (the sticky header) keep
        their natural size first.
     4. min-height:0 overrides the default flex item min-height of
        "auto" (which would clamp to the iframe's intrinsic 150px
        and prevent the iframe from filling beyond that on tall
        modals). Canonical fix.
     5. overflow:hidden clips any iframe edge cases (e.g. brief
        300x150 default while the page loads) to the wrap. */
.terms-iframe-wrap {
  flex: 1 1 0;
  min-height: 0;
  overflow: hidden;
  background: var(--color-bg);
}
.terms-iframe-wrap iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: none;
}
@media (max-width: 600px) {
  .terms-overlay { padding: var(--space-4) var(--space-3); }
  .terms-modal-header { padding: var(--space-3) var(--space-4); }
}

/* Legal footer row inside the account modal — sits below the last
   section, above the (sticky) confirm-bar. Same muted treatment as
   auth-forgot-row so the footer stays visually quiet. */
.account-legal-row {
  margin: var(--space-5) 0 0 0;
  padding-top: var(--space-4);
  border-top: 1px solid #ECECEC;
  text-align: center;
  font-size: 13px;
}
.account-legal-row a,
.account-legal-row button.link {
  color: var(--color-muted);
  font-weight: 500;
  background: none;
  border: none;
  padding: 0;
  font-family: inherit;
  font-size: inherit;
  cursor: pointer;
  text-decoration: none;
}
.account-legal-row a:hover,
.account-legal-row button.link:hover {
  color: var(--color-primary);
  text-decoration: underline;
}

/* Confirm strip — appears when user clicks the backdrop with unsaved
   edits. Sticks to the bottom of the modal so it's reachable however
   far they've scrolled. Green-tinted background signals "you've got
   work that needs a decision" without using the alarming error red. */
.account-confirm-bar {
  position: sticky;
  bottom: 0;
  margin: var(--space-4) calc(-1 * var(--space-6)) 0;
  padding: var(--space-3) var(--space-5);
  background: rgba(87, 204, 153, 0.18);
  border-top: 1px solid rgba(87, 204, 153, 0.42);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  flex-wrap: wrap;
}
.account-confirm-bar[hidden] {
  display: none;
}
.account-confirm-message {
  font-size: 13px;
  color: #2f8a64;
  font-weight: 500;
  flex: 1 1 200px;
}
.account-confirm-actions {
  display: flex;
  gap: var(--space-2);
}
.account-confirm-actions button {
  padding: 8px 14px;
  font-size: 13px;
  font-weight: 600;
  font-family: inherit;
  border-radius: var(--radius-sm);
  cursor: pointer;
  border: 1px solid transparent;
  transition: opacity 0.15s ease, background 0.15s ease;
}
.account-confirm-save {
  color: var(--color-surface);
  background: var(--color-primary);
}
.account-confirm-save:hover:not(:disabled) {
  opacity: 0.9;
}
.account-confirm-discard {
  color: var(--color-text);
  background: var(--color-surface);
  border-color: rgba(0, 0, 0, 0.10);
}
.account-confirm-discard:hover:not(:disabled) {
  background: var(--color-bg);
}
.account-confirm-save:disabled,
.account-confirm-discard:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

/* =========================================================================
 * Forgot-password / recovery panels — live inside the auth-card and swap
 * with the sign-in form via [hidden]. Visual style mirrors auth-card so
 * the user never feels they left the same surface.
 * ========================================================================= */
.auth-forgot-row {
  margin: var(--space-3) 0 0 0;
  text-align: center;
  font-size: 13px;
}
.auth-forgot-row a {
  color: var(--color-muted);
  font-weight: 500;
}
.auth-forgot-row a:hover {
  color: var(--color-primary);
}

/* =========================================================================
 * Responsive — §4.2: mobile-responsive below 768px
 * ========================================================================= */
@media (max-width: 480px) {
  .auth-card {
    padding: var(--space-5);
  }
  .top-bar {
    padding: 0 var(--space-4);
    gap: var(--space-3);
  }
  .welcome-heading {
    font-size: 24px;
  }
  .user-dropdown {
    min-width: 200px;
  }
  .account-modal {
    padding: var(--space-5) var(--space-4);
  }
}

/* =========================================================================
 * Feedback — small button bottom-left of the dashboard + modal.
 * Only rendered post-wizard (visibility controlled by JS). The trigger
 * sits below the top-bar (z=200) and below modals (account=300) so it's
 * never the topmost element when a modal is open.
 *
 * Z-index discipline:
 *   feedback-trigger  = 150 (above main content, below top-bar)
 *   feedback-overlay  = 290 (above setup-overlay=100, just below
 *                            account-overlay=300; account modal is the
 *                            highest UI surface by design)
 * ========================================================================= */
.feedback-trigger {
  position: fixed;
  left: var(--space-4);
  bottom: var(--space-4);
  z-index: 150;
  background: var(--color-surface);
  color: var(--color-muted);
  border: 1px solid rgba(0, 0, 0, 0.10);
  border-radius: 999px;
  padding: 6px 14px;
  font-size: 12px;
  font-family: var(--font-sans);
  font-weight: 500;
  cursor: pointer;
  box-shadow: var(--shadow-card);
  transition: color 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.feedback-trigger:hover {
  color: var(--color-primary);
  border-color: rgba(42, 157, 143, 0.5);
}
.feedback-trigger:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}
.feedback-trigger[hidden] {
  display: none;
}
/* Unread-reply badge on the feedback trigger. Same pattern we'd use
   for a notification bell: small teal pill carrying a count.
   hidden via [hidden] (set in JS when count=0) so it doesn't sit
   as an empty bubble next to the label. */
.feedback-trigger-badge {
  background: var(--color-primary);
  color: #FFFFFF;
  font-size: 10px;
  font-weight: 600;
  line-height: 1;
  padding: 3px 7px;
  border-radius: 999px;
  min-width: 18px;
  text-align: center;
}
.feedback-trigger-badge[hidden] {
  display: none;
}

.feedback-overlay {
  position: fixed;
  inset: 0;
  background: rgba(27, 27, 27, 0.32);
  z-index: 290;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6) var(--space-5);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s ease;
}
.feedback-overlay.open {
  opacity: 1;
  pointer-events: all;
}
/* The modal is now a flex column with a sticky header, a scrollable
   history pane in the middle, and a fixed composer at the bottom.
   max-width bumped to 680px to give the chat history room to breathe;
   max-height caps the modal so the composer stays on-screen even on
   short viewports. The modal's overflow stays hidden so the rounded
   corners clip the inner sections cleanly; the history pane is the
   actual scroll container. */
.feedback-modal {
  width: 100%;
  max-width: 680px;
  /* Cap total modal height at 600px so the modal NEVER grows past that
     regardless of thread length. Falls back to viewport-aware sizing
     on very short windows so the modal still fits. */
  max-height: min(600px, calc(100vh - 96px));
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-pop);
  transform: scale(0.97) translateY(8px);
  transition: transform 0.18s ease;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.feedback-overlay.open .feedback-modal {
  transform: scale(1) translateY(0);
}
/* Sticky-pinned header — same pattern as account-modal-header so the
   X is always reachable while the history scrolls. */
.feedback-modal-header {
  position: sticky;
  top: 0;
  background: var(--color-surface);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid #ECECEC;
  flex-shrink: 0;
}
.feedback-modal-header h2 {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
}
.feedback-close {
  background: none;
  border: none;
  color: var(--color-muted);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: var(--radius-sm);
}
.feedback-close:hover {
  color: var(--color-text);
  background: rgba(0, 0, 0, 0.04);
}
.feedback-blurb {
  margin: 0;
  padding: var(--space-3) var(--space-5) 0;
  color: var(--color-muted);
  font-size: 13px;
  flex-shrink: 0;
}

/* History pane — scrollable list of bubbles in chronological order
   (oldest at top, newest at bottom; the JS reverses the
   server-side DESC order before rendering). The pane sits BELOW the
   composer now, so its top border is the divider against the
   composer above (composer carries border-bottom). max-height is
   capped at 320px and overflow-y: auto so a long thread never
   stretches the modal past its 600px ceiling. */
.feedback-history {
  flex: 1 1 auto;
  min-height: 140px;
  max-height: 320px;
  overflow-y: auto;
  padding: var(--space-4) var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  background: var(--color-bg);
}
.feedback-history-empty,
.feedback-history-loading {
  color: var(--color-muted);
  font-size: 13px;
  text-align: center;
  padding: var(--space-4) 0;
}
/* Each bubble is a thin container so the timestamp and attribution
   can sit alongside the message text without breaking out of the
   bubble's max-width. Direction is governed by the .user / .vantage
   modifier; the parent .feedback-history is a column flex so
   align-self is the right tool. */
.feedback-bubble {
  max-width: 78%;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-lg);
  font-size: 13px;
  line-height: 1.45;
  white-space: pre-wrap;
  word-wrap: break-word;
}
.feedback-bubble.user {
  align-self: flex-end;
  background: rgba(42, 157, 143, 0.12);
  color: var(--color-text);
  border-bottom-right-radius: var(--radius-sm);
}
.feedback-bubble.vantage {
  align-self: flex-start;
  /* Warm grey - clearly distinct from the history pane's beige
     background and from the teal-tinted user bubbles. No border
     needed since the fill is itself the visual boundary. */
  background: #F0EDE8;
  color: var(--color-text);
  border-bottom-left-radius: var(--radius-sm);
}
.feedback-bubble-meta {
  font-size: 11px;
  color: var(--color-muted);
  margin-bottom: 4px;
}
.feedback-bubble.user .feedback-bubble-meta {
  text-align: right;
}
.feedback-bubble-time {
  font-size: 11px;
  color: var(--color-muted);
  margin-top: 4px;
}
.feedback-bubble.user .feedback-bubble-time {
  text-align: right;
}

/* Composer block sits ABOVE the history pane (reorder: header →
   blurb → composer → history). The bottom border is the divider
   between composer and history. flex-shrink:0 ensures the composer
   never collapses on short viewports — long threads scroll inside
   the history pane below instead. */
.feedback-composer {
  padding: var(--space-3) var(--space-5) var(--space-4);
  flex-shrink: 0;
  border-bottom: 1px solid #ECECEC;
  background: var(--color-surface);
}
.feedback-textarea {
  width: 100%;
  min-height: 120px;
  resize: vertical;
  padding: var(--space-3);
  border: 1px solid rgba(0, 0, 0, 0.12);
  border-radius: var(--radius-md);
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.5;
  color: var(--color-text);
  background: var(--color-surface);
}
.feedback-textarea:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px rgba(42, 157, 143, 0.15);
}
.feedback-counter {
  margin-top: var(--space-2);
  font-size: 12px;
  color: var(--color-muted);
  text-align: right;
}
.feedback-counter.near-limit {
  color: var(--color-warning);
}
.feedback-counter.over-limit {
  color: var(--color-danger);
}
.feedback-error {
  margin-top: var(--space-2);
  font-size: 13px;
  color: var(--color-danger);
}
.feedback-error[hidden] {
  display: none;
}
.feedback-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
  margin-top: var(--space-4);
}
.feedback-actions .btn-ghost,
.feedback-actions .btn-primary {
  padding: 8px 16px;
  border-radius: var(--radius-md);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  border: none;
  font-family: var(--font-sans);
}
.feedback-actions .btn-ghost {
  background: transparent;
  color: var(--color-muted);
  border: 1px solid rgba(0, 0, 0, 0.12);
}
.feedback-actions .btn-ghost:hover {
  color: var(--color-text);
  border-color: rgba(0, 0, 0, 0.24);
}
.feedback-actions .btn-primary {
  background: var(--color-primary);
  color: #FFFFFF;
}
.feedback-actions .btn-primary:hover:not(:disabled) {
  filter: brightness(0.94);
}
.feedback-actions .btn-primary:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

/* =========================================================================
 * === QUICK VAL ===
 * Spec §8. Two visual modes:
 *   - Form steps (Step 1, Step 2): Layers.to aesthetic — clean, minimal,
 *     generous whitespace, sharp typography, single centered card.
 *   - Library + Results: Visible.vc aesthetic — data-dense, structured,
 *     numbers as the hero, clear hierarchy.
 * No new tokens; every color/spacing/radius reuses an existing variable.
 * ========================================================================= */

/* ----- APP TOOLBAR (persistent, sits below top-bar) -----
 *
 * Single full-width strip that hosts the tab nav on the left and
 * tool-specific action buttons on the right. The toolbar's outer
 * dimensions never change - results-only buttons swap visibility,
 * not display, so the row height + tab-nav position stay constant
 * (avoids the left/right reflow that operator flagged when switching
 * tabs in v1.8).
 */
.app-toolbar {
  display: flex;
  align-items: stretch;
  justify-content: space-between;
  background: var(--color-surface);
  border-bottom: 1px solid rgba(0, 0, 0, 0.08);
  padding: 0 var(--space-5);
  height: 48px;
  position: sticky;
  top: 0;
  z-index: 50;
}
/* In the toolbar context the tab nav is just a flex item - no border
   (the toolbar owns the bottom border) and no margin. The active
   underline still works because the tab-btn carries its own
   border-bottom rule below. */
.tab-nav {
  display: flex;
  gap: var(--space-4);
  border-bottom: none;
  padding: 0;
  margin: 0;
}
.tab-btn {
  background: transparent;
  border: none;
  font-family: var(--font-sans);
  font-size: 14px;
  font-weight: 500;
  color: var(--color-muted);
  padding: 0 var(--space-2);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: color 120ms ease, border-color 120ms ease;
  display: inline-flex;
  align-items: center;
}
.tab-btn:hover {
  color: var(--color-text);
}
.tab-btn.active {
  color: var(--color-primary);
  border-bottom-color: var(--color-primary);
}
/* Right-side action cluster. Hidden entirely on tabs that don't own
   it (Portfolio, Companies) via display:none on .toolbar-right itself.
   Within the Valuation Tool tab, the inner .toolbar-results-group
   toggles visibility:hidden so its space is preserved and the
   New-Analysis button never shifts when entering/leaving Results. */
.toolbar-right {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.toolbar-right[hidden] {
  display: none;
}
.toolbar-results-group {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.toolbar-results-group.toolbar-results-hidden {
  visibility: hidden;
  pointer-events: none;
}
.toolbar-btn {
  background: var(--color-surface);
  border: 1px solid rgba(0, 0, 0, 0.10);
  border-radius: var(--radius-md);
  padding: 6px 12px;
  font-size: 13px;
  color: var(--color-text);
  cursor: pointer;
  font-family: var(--font-sans);
}
.toolbar-btn:hover:not(:disabled) {
  border-color: rgba(0, 0, 0, 0.24);
}
.toolbar-btn.on {
  background: var(--color-primary);
  color: #FFFFFF;
  border-color: var(--color-primary);
}
.toolbar-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
.toolbar-new-btn,
.toolbar-save-btn {
  background: var(--color-primary);
  color: #FFFFFF;
  border: none;
  border-radius: var(--radius-md);
  padding: 7px 14px;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  font-family: var(--font-sans);
}
.toolbar-new-btn:hover,
.toolbar-save-btn:hover {
  filter: brightness(0.94);
}
.toolbar-export-wrap {
  position: relative;
}
.toolbar-export-menu {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  background: var(--color-surface);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: var(--radius-md);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
  min-width: 180px;
  z-index: 60;
  padding: 4px;
}
.toolbar-export-menu button {
  display: block;
  width: 100%;
  padding: 8px 12px;
  border: none;
  background: transparent;
  text-align: left;
  font-family: var(--font-sans);
  font-size: 13px;
  color: var(--color-text);
  cursor: pointer;
  border-radius: var(--radius-sm);
}
.toolbar-export-menu button:hover { background: var(--color-bg); }

.tab-panels {
  padding: var(--space-5) var(--space-5) var(--space-7) var(--space-5);
}
.tab-panel {
  display: block;
}
.tab-panel[hidden] {
  display: none;
}

/* ----- AUTH CARD LINK CLUSTER -----
 *
 * Decluttered v1.9: the prominent pulsing demo link gets its own row;
 * forgot-password (left) and terms (right) share the next row via the
 * .auth-card-footer-row split layout. The old standalone .auth-legal-row
 * is folded into that split row. Sign-in / Sign-up toggle row stays
 * unchanged above (it's a separate concern - mode switcher, not a
 * navigation link).
 */
.auth-demo-row {
  text-align: center;
  margin-top: var(--space-4);
}
/* v1.10: color-cycle animation through the teal palette replaces the
   opacity pulse. 2s per cycle reads as a confident attractor rather
   than a hesitant fade. Hover pauses the animation so the user gets a
   stable color to click. */
.auth-demo-row a {
  color: var(--color-primary);
  font-weight: 600;
  text-decoration: none;
  font-size: 17px;
  letter-spacing: 0.01em;
  display: inline-block;
  animation: auth-demo-color 2s ease-in-out infinite;
}
.auth-demo-row a:hover {
  text-decoration: underline;
  animation-play-state: paused;
}
@keyframes auth-demo-color {
  0%   { color: #7EC8C0; }
  25%  { color: #2A9D8F; }
  50%  { color: #1A6B63; }
  75%  { color: #2A9D8F; }
  100% { color: #7EC8C0; }
}
.auth-card-footer-row {
  display: flex;
  align-items: center;
  margin-top: var(--space-3);
  font-size: 12px;
}
/* Terms link always anchored to the right, even when the left-side
   forgot-password span is hidden by auth.js in non-form modes. The
   margin-left:auto trick keeps the terms link in place without
   needing justify-content (which collapses when the left child has
   display:none). */
.auth-card-footer-row > a {
  margin-left: auto;
  color: var(--color-muted);
  text-decoration: none;
}
.auth-card-footer-row a {
  color: var(--color-muted);
  text-decoration: none;
}
.auth-card-footer-row a:hover {
  color: var(--color-text);
  text-decoration: underline;
}

/* ----- QUICK VAL ROOT ----- */
#quickval-root {
  width: 100%;
  max-width: 1280px;
  margin: 0 auto;
}

/* ----- LIBRARY ----- */
.qv-library {
  display: block;
}
.qv-library-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-5);
  flex-wrap: wrap;
}
.qv-h1 {
  margin: 0;
  font-size: 24px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--color-text);
}
.qv-library-tools {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}
.qv-view-toggle {
  display: inline-flex;
  background: var(--color-surface);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.qv-view-btn {
  background: transparent;
  border: none;
  padding: 6px 10px;
  cursor: pointer;
  color: var(--color-muted);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.qv-view-btn svg { fill: currentColor; }
.qv-view-btn.active {
  background: var(--color-bg);
  color: var(--color-primary);
}
.qv-library-controls {
  display: flex;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
  flex-wrap: wrap;
}
.qv-search {
  flex: 1 1 280px;
  min-width: 220px;
  padding: 10px 14px;
  border: 1px solid rgba(0, 0, 0, 0.10);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  font-family: var(--font-sans);
  font-size: 14px;
  color: var(--color-text);
}
.qv-search:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px rgba(42, 157, 143, 0.12);
}
.qv-sort {
  padding: 10px 14px;
  border: 1px solid rgba(0, 0, 0, 0.10);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  font-family: var(--font-sans);
  font-size: 14px;
  color: var(--color-text);
  cursor: pointer;
}
.qv-filter-chips {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
}
.qv-filter-label {
  font-size: 12px;
  color: var(--color-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-right: var(--space-2);
}
.qv-chip {
  background: var(--color-surface);
  border: 1px solid rgba(0, 0, 0, 0.10);
  border-radius: 999px;
  padding: 4px 12px;
  font-size: 12px;
  color: var(--color-text);
  cursor: pointer;
  font-family: var(--font-sans);
  transition: background 120ms ease, color 120ms ease;
}
.qv-chip:hover {
  border-color: var(--color-primary);
}
.qv-chip.active {
  background: var(--color-primary);
  color: #FFFFFF;
  border-color: var(--color-primary);
}
.qv-library-body {
  margin-top: var(--space-3);
}

/* Library grid + cards */
.qv-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-4);
}
@media (max-width: 900px) {
  .qv-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 600px) {
  .qv-grid { grid-template-columns: 1fr; }
}
.qv-card {
  background: var(--color-surface);
  border: 1px solid rgba(0, 0, 0, 0.06);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  text-align: left;
  cursor: pointer;
  font-family: var(--font-sans);
  transition: box-shadow 160ms ease, transform 160ms ease, border-color 160ms ease;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  min-height: 200px;
}
.qv-card:hover {
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.06);
  border-color: rgba(42, 157, 143, 0.3);
  transform: translateY(-1px);
}
.qv-card-top { display: flex; flex-direction: column; gap: var(--space-2); }
.qv-card-name {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  color: var(--color-text);
  letter-spacing: -0.01em;
}
.qv-card-meta { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.qv-card-chip {
  font-size: 11px;
  color: var(--color-muted);
  background: var(--color-bg);
  padding: 2px 8px;
  border-radius: 999px;
}
.qv-card-hero { margin-top: auto; }
.qv-card-hero-num {
  margin: 0;
  font-size: 28px;
  font-weight: 600;
  color: var(--color-primary);
  letter-spacing: -0.02em;
}
.qv-card-hero-label {
  margin: 2px 0 0 0;
  font-size: 11px;
  color: var(--color-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.qv-card-secondary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 13px;
  color: var(--color-text);
  border-top: 1px solid rgba(0, 0, 0, 0.05);
  padding-top: var(--space-3);
}
.qv-card-secondary-label { color: var(--color-muted); }
.qv-card-secondary-val { font-weight: 500; }
.qv-card-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.qv-card-date {
  font-size: 11px;
  color: var(--color-muted);
}
.qv-card-avatar {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--color-primary);
  color: #FFFFFF;
  font-size: 11px;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  letter-spacing: 0;
}
.qv-card-avatar.small {
  width: 20px;
  height: 20px;
  font-size: 10px;
  margin-right: 4px;
  vertical-align: middle;
}

/* Library table */
.qv-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--color-surface);
  border-radius: var(--radius-md);
  overflow: hidden;
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.04);
}
.qv-table th,
.qv-table td {
  padding: 12px 14px;
  text-align: left;
  font-size: 13px;
  border-bottom: 1px solid rgba(0, 0, 0, 0.04);
}
.qv-table th {
  font-weight: 600;
  color: var(--color-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: 11px;
  background: var(--color-bg);
  cursor: pointer;
  user-select: none;
}
.qv-table th.num,
.qv-table td.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.qv-table tbody tr { cursor: pointer; transition: background 120ms ease; }
.qv-table tbody tr:nth-child(even) { background: rgba(244, 241, 238, 0.5); }
.qv-table tbody tr:hover { background: rgba(42, 157, 143, 0.06); }

/* Skeletons */
.qv-skeleton {
  background: linear-gradient(90deg, rgba(0,0,0,0.04) 25%, rgba(0,0,0,0.08) 37%, rgba(0,0,0,0.04) 63%);
  background-size: 400% 100%;
  animation: qv-shimmer 1.4s ease infinite;
  border: none;
  min-height: 200px;
  border-radius: var(--radius-lg);
}
.qv-skeleton-row {
  height: 18px;
  background: linear-gradient(90deg, rgba(0,0,0,0.04) 25%, rgba(0,0,0,0.08) 37%, rgba(0,0,0,0.04) 63%);
  background-size: 400% 100%;
  animation: qv-shimmer 1.4s ease infinite;
  border-radius: var(--radius-sm);
}
@keyframes qv-shimmer {
  0%   { background-position: 100% 0; }
  100% { background-position: -100% 0; }
}

/* Empty state */
.qv-empty {
  background: var(--color-surface);
  border: 1px solid rgba(0, 0, 0, 0.06);
  border-radius: var(--radius-lg);
  padding: var(--space-7) var(--space-6);
  text-align: center;
  color: var(--color-text);
  max-width: 480px;
  margin: var(--space-6) auto;
}
.qv-empty-illus {
  width: 120px;
  height: 80px;
  color: var(--color-muted);
  margin-bottom: var(--space-4);
}
.qv-empty-title {
  margin: 0 0 var(--space-2) 0;
  font-size: 18px;
  font-weight: 600;
  color: var(--color-text);
}
.qv-empty-sub {
  margin: 0 0 var(--space-5) 0;
  color: var(--color-muted);
  font-size: 14px;
}

.qv-loading {
  padding: var(--space-7);
  display: flex;
  justify-content: center;
}

/* ----- CREATION FORM (Layers.to aesthetic) ----- */
.qv-form-wrap {
  max-width: 600px;
  margin: 0 auto;
}
.qv-form-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-5);
}
.qv-back-link {
  background: transparent;
  border: none;
  font-family: var(--font-sans);
  font-size: 13px;
  color: var(--color-muted);
  cursor: pointer;
  padding: 4px 0;
}
.qv-back-link:hover { color: var(--color-text); }
.qv-step-label {
  margin: 0;
  font-size: 11px;
  color: var(--color-muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.qv-form-card {
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  padding: var(--space-7) var(--space-6);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
}
.qv-form-title {
  margin: 0 0 var(--space-5) 0;
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--color-text);
}
.qv-field {
  margin-bottom: var(--space-4);
}
.qv-field-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4);
  margin-bottom: var(--space-4);
}
@media (max-width: 540px) {
  .qv-field-row { grid-template-columns: 1fr; }
}
/* v1.11: three-column row used for Sector | Subsector | Stage on Step 1. */
.qv-field-row-3 {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: var(--space-4);
  margin-bottom: var(--space-4);
}
@media (max-width: 640px) {
  .qv-field-row-3 { grid-template-columns: 1fr; }
}
.qv-field label,
.qv-input-row label {
  display: block;
  font-size: 13px;
  color: var(--color-text);
  font-weight: 500;
  margin-bottom: 6px;
}
.qv-field-optional {
  color: var(--color-muted);
  font-weight: 400;
}
.qv-field input,
.qv-field select,
.qv-field textarea {
  width: 100%;
  padding: 10px 14px;
  border: 1px solid rgba(0, 0, 0, 0.10);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  font-family: var(--font-sans);
  font-size: 14px;
  color: var(--color-text);
  box-sizing: border-box;
}
.qv-field textarea {
  min-height: 80px;
  resize: vertical;
}
.qv-field input:focus,
.qv-field select:focus,
.qv-field textarea:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px rgba(42, 157, 143, 0.12);
}
.qv-field-error {
  color: var(--color-danger);
  font-size: 12px;
  margin: 6px 0 0 0;
}
.qv-field-hint {
  color: var(--color-muted);
  font-size: 12px;
  margin: 6px 0 0 0;
}
.qv-field-counter {
  text-align: right;
  font-size: 11px;
  color: var(--color-muted);
  margin: 4px 0 0 0;
}
.qv-form-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: var(--space-5);
  gap: var(--space-3);
}
.qv-form-actions.split {
  justify-content: space-between;
}

/* ----- RESULTS VIEW (Visible.vc aesthetic) ----- */
.qv-results {
  display: block;
}
.qv-results-header {
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--color-bg);
  padding: var(--space-4) 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  border-bottom: 1px solid rgba(0, 0, 0, 0.06);
  flex-wrap: wrap;
}
.qv-results-header-left {
  flex: 1 1 280px;
  min-width: 0;
}
.qv-results-header-right {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
}
.qv-company-edit {
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--color-text);
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  padding: 6px 10px;
  margin-left: -10px;
  font-family: var(--font-sans);
  width: 100%;
  max-width: 420px;
  box-sizing: border-box;
}
.qv-company-edit:hover {
  border-color: rgba(0, 0, 0, 0.06);
}
.qv-company-edit:focus {
  border-color: var(--color-primary);
  background: var(--color-surface);
  outline: none;
}
.qv-version-select {
  padding: 8px 12px;
  font-size: 13px;
  background: var(--color-surface);
  border: 1px solid rgba(0, 0, 0, 0.10);
  border-radius: var(--radius-md);
  color: var(--color-text);
  cursor: pointer;
}
.qv-toggle {
  background: var(--color-surface);
  border: 1px solid rgba(0, 0, 0, 0.10);
  border-radius: var(--radius-md);
  padding: 8px 12px;
  font-size: 13px;
  color: var(--color-text);
  cursor: pointer;
  font-family: var(--font-sans);
}
.qv-toggle.on {
  background: var(--color-primary);
  color: #FFFFFF;
  border-color: var(--color-primary);
}
.qv-toggle:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
.qv-export-wrap { position: relative; }
.qv-export-btn {
  background: var(--color-surface);
  border: 1px solid rgba(0, 0, 0, 0.10);
  border-radius: var(--radius-md);
  padding: 8px 12px;
  font-size: 13px;
  color: var(--color-text);
  cursor: pointer;
  font-family: var(--font-sans);
}
.qv-export-menu {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  background: var(--color-surface);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: var(--radius-md);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
  min-width: 180px;
  z-index: 20;
  padding: 4px;
}
.qv-export-menu button {
  display: block;
  width: 100%;
  padding: 8px 12px;
  border: none;
  background: transparent;
  text-align: left;
  font-family: var(--font-sans);
  font-size: 13px;
  color: var(--color-text);
  cursor: pointer;
  border-radius: var(--radius-sm);
}
.qv-export-menu button:hover { background: var(--color-bg); }
.qv-header-save { padding: 8px 16px; font-size: 13px; }

.qv-historical-banner {
  background: rgba(233, 196, 106, 0.18);
  border: 1px solid var(--color-warning);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin: var(--space-3) 0;
  flex-wrap: wrap;
}
.qv-historical-banner p {
  margin: 0;
  font-size: 13px;
  color: var(--color-text);
}
.qv-historical-actions {
  display: flex;
  gap: var(--space-2);
}

/* v1.10: 45/55 split — inputs left, scenarios+AI stacked right. The
   right column is a flex column so the AI card sits below scenarios
   with a single gap; this lets the right column extend to roughly
   match the inputs card height. Stacks vertically below 900px. */
.qv-results-grid {
  display: grid;
  grid-template-columns: minmax(0, 45%) minmax(0, 55%);
  gap: var(--space-5);
  margin-top: var(--space-4);
  align-items: stretch;
}
@media (max-width: 900px) {
  .qv-results-grid { grid-template-columns: 1fr; }
}
.qv-results-left,
.qv-results-right {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.qv-results-right .qv-ai-card { flex: 1 1 auto; }
.qv-section-title {
  margin: 0 0 var(--space-3) 0;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-muted);
}

.qv-inputs {
  background: var(--color-surface);
  border: 1px solid rgba(0, 0, 0, 0.06);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
}
.qv-input-row {
  display: grid;
  grid-template-columns: 160px 1fr;
  gap: var(--space-3);
  align-items: center;
  padding: var(--space-2) 0;
}
.qv-input-row-wide { grid-template-columns: 160px 1fr; align-items: start; }
.qv-input-row-wide label { padding-top: 8px; }
.qv-input {
  width: 100%;
  padding: 8px 12px;
  border: 1px solid rgba(0, 0, 0, 0.10);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  font-family: var(--font-sans);
  font-size: 14px;
  color: var(--color-text);
  box-sizing: border-box;
  font-variant-numeric: tabular-nums;
}
.qv-input:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px rgba(42, 157, 143, 0.12);
}
.qv-input[readonly],
.qv-input:disabled {
  background: var(--color-bg);
  color: var(--color-muted);
  cursor: not-allowed;
}
textarea.qv-input { min-height: 64px; resize: vertical; }

/* ----- SMART DROPDOWN (v1.11) -----
 * Replacement for native <select> on Sector, Subsector, Stage. Used in
 * both the Step 1 form (.qv-field context) and the Results inputs panel
 * (.qv-input context). The component renders a button "trigger" that
 * looks like the surrounding input, plus an absolutely-positioned
 * panel with a search box and option list. Built by createSmartDropdown
 * in js/quick-val.js — see that for the JS contract.
 */
.qv-smart-dd {
  position: relative;
  width: 100%;
}
.qv-smart-dd-trigger {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: 10px 14px;
  border: 1px solid rgba(0, 0, 0, 0.10);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  font-family: var(--font-sans);
  font-size: 14px;
  color: var(--color-text);
  cursor: pointer;
  box-sizing: border-box;
  text-align: left;
  line-height: 1.3;
}
.qv-smart-dd-trigger:hover { border-color: rgba(0, 0, 0, 0.18); }
.qv-smart-dd-trigger:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px rgba(42, 157, 143, 0.12);
}
/* The results inputs panel uses the slimmer .qv-input padding, so
 * shrink the trigger to match when nested under .qv-inputs. */
.qv-inputs .qv-smart-dd-trigger {
  padding: 8px 12px;
}
.qv-smart-dd-placeholder { color: var(--color-muted); }
.qv-smart-dd-chevron {
  flex: 0 0 auto;
  width: 10px;
  height: 10px;
  border-right: 2px solid var(--color-muted);
  border-bottom: 2px solid var(--color-muted);
  transform: rotate(45deg) translateY(-2px);
  transition: transform 120ms ease;
}
.qv-smart-dd.open .qv-smart-dd-chevron {
  transform: rotate(-135deg) translateY(-2px);
}
/* Auto-populated sector (chosen by selecting a subsector when no sector
 * was set). Soft grey tint distinguishes it from a manual selection.
 * Still clickable — operator can override the auto choice. */
.qv-smart-dd.auto .qv-smart-dd-trigger {
  background: var(--color-bg);
  border-color: var(--color-muted);
}

.qv-smart-dd-panel {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  z-index: 100;
  background: var(--color-surface);
  border: 1px solid rgba(0, 0, 0, 0.10);
  border-radius: var(--radius-md);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.10);
  max-height: 320px;
  display: none;
  flex-direction: column;
  overflow: hidden;
}
/* Drop-up variant — when the dropdown is near the bottom of the
 * viewport, JS adds .drop-up and the panel opens above the trigger. */
.qv-smart-dd.drop-up .qv-smart-dd-panel {
  top: auto;
  bottom: calc(100% + 4px);
}
.qv-smart-dd.open .qv-smart-dd-panel { display: flex; }

.qv-smart-dd-search {
  width: 100%;
  border: none;
  border-bottom: 1px solid rgba(0, 0, 0, 0.06);
  padding: 10px 12px;
  font-family: var(--font-sans);
  font-size: 13px;
  color: var(--color-text);
  background: transparent;
  box-sizing: border-box;
}
.qv-smart-dd-search:focus { outline: none; }
.qv-smart-dd-search::placeholder { color: var(--color-muted); }

.qv-smart-dd-list {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: 4px 0;
}
.qv-smart-dd-option {
  padding: 8px 12px;
  font-size: 14px;
  color: var(--color-text);
  cursor: pointer;
  line-height: 1.3;
}
.qv-smart-dd-option:hover,
.qv-smart-dd-option.focused {
  background: rgba(42, 157, 143, 0.08);
}
.qv-smart-dd-option-other {
  font-weight: 600;
  color: var(--color-primary);
  border-bottom: 1px solid rgba(0, 0, 0, 0.06);
}
.qv-smart-dd-empty {
  padding: 12px;
  font-size: 13px;
  color: var(--color-muted);
  text-align: center;
}

/* "Other" inline editor — appears below the trigger after the user
 * picks the Other option. Same width as the trigger. Apply / Exit are
 * inline buttons to the right of the input. */
.qv-smart-dd-other-wrap {
  display: flex;
  gap: var(--space-2);
  align-items: center;
  margin-top: 6px;
}
.qv-smart-dd-other-input {
  flex: 1 1 auto;
  padding: 10px 14px;
  border: 1px solid rgba(0, 0, 0, 0.10);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  font-family: var(--font-sans);
  font-size: 14px;
  color: var(--color-text);
  box-sizing: border-box;
}
.qv-inputs .qv-smart-dd-other-input { padding: 8px 12px; }
.qv-smart-dd-other-input:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px rgba(42, 157, 143, 0.12);
}
.qv-smart-dd-other-actions {
  display: inline-flex;
  gap: 6px;
  flex: 0 0 auto;
}
.qv-smart-dd-other-apply,
.qv-smart-dd-other-exit {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 8px 12px;
  border-radius: var(--radius-md);
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  border: 1px solid transparent;
  line-height: 1;
}
.qv-smart-dd-other-apply {
  background: var(--color-primary);
  color: #fff;
}
.qv-smart-dd-other-apply:hover { filter: brightness(0.95); }
.qv-smart-dd-other-exit {
  background: transparent;
  color: var(--color-muted);
  border-color: rgba(0, 0, 0, 0.10);
}
.qv-smart-dd-other-exit:hover {
  color: var(--color-text);
  border-color: rgba(0, 0, 0, 0.18);
}

/* Show-changes diff */
.qv-diff {
  border: 1px solid var(--color-warning);
  background: rgba(233, 196, 106, 0.08);
  border-radius: var(--radius-md);
  padding: var(--space-2);
}
.qv-diff-prev {
  margin: 0 0 4px 0;
  font-size: 11px;
  color: var(--color-muted);
}
.qv-diff-prev strong { color: var(--color-text); }
.qv-diff-curr {
  margin: 4px 0 0 0;
  font-size: 11px;
  color: var(--color-muted);
}

/* Scenario table */
.qv-scenarios {
  background: var(--color-surface);
  border: 1px solid rgba(0, 0, 0, 0.06);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
}
.qv-scenario-table {
  width: 100%;
  border-collapse: collapse;
}
.qv-scenario-table th {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-muted);
  text-align: right;
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid rgba(0, 0, 0, 0.06);
}
.qv-scenario-table th:first-child {
  text-align: left;
}
.qv-scenario-table td {
  padding: var(--space-3);
  font-size: 16px;
  font-weight: 600;
  text-align: right;
  font-variant-numeric: tabular-nums;
  color: var(--color-text);
}
.qv-scenario-label {
  text-align: left !important;
  font-size: 12px !important;
  font-weight: 500 !important;
  color: var(--color-muted) !important;
}
.qv-scenario-bear { color: var(--color-muted); }
.qv-scenario-base {
  background: rgba(42, 157, 143, 0.05);
  border-left: 3px solid var(--color-primary);
}
.qv-scenario-table th.qv-scenario-base {
  color: var(--color-primary);
  background: rgba(42, 157, 143, 0.05);
  border-left: 3px solid var(--color-primary);
}
.qv-scenario-bull { color: var(--color-text); }

/* v1.10: % difference sub-labels below Bear and Bull column headers.
   Computed live from exit_valuation vs base; updated on recompute by
   re-rendering the whole scenario table. Muted warm red / muted
   green — not bright, so they read as context, not alerts. */
.qv-scenario-sub {
  display: block;
  font-size: 11px;
  font-weight: 500;
  margin-top: 3px;
  letter-spacing: 0;
  text-transform: none;
  font-variant-numeric: tabular-nums;
}
.qv-scenario-sub-bear { color: rgba(220, 53, 69, 0.65); }
.qv-scenario-sub-bull { color: rgba(40, 167, 69, 0.65);  }

/* AI narrative card */
.qv-ai-card {
  background: var(--color-bg);
  border: 1px solid rgba(0, 0, 0, 0.06);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
}
.qv-ai-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-3);
}
.qv-ai-title {
  margin: 0;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-muted);
}
.qv-ai-regen {
  background: transparent;
  border: 1px solid rgba(0, 0, 0, 0.10);
  border-radius: var(--radius-sm);
  width: 28px;
  height: 28px;
  cursor: pointer;
  font-size: 14px;
  color: var(--color-muted);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.qv-ai-regen:hover {
  color: var(--color-primary);
  border-color: var(--color-primary);
}
.qv-ai-body {
  font-size: 14px;
  line-height: 1.55;
  color: var(--color-text);
}
.qv-ai-body p { margin: 0 0 var(--space-3) 0; }
.qv-ai-body p:last-child { margin-bottom: 0; }
.qv-ai-body ul { margin: 0 0 var(--space-3) var(--space-4); padding: 0; }
.qv-ai-body strong { font-weight: 600; }
.qv-ai-loading {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--color-muted);
  font-size: 13px;
}
.qv-ai-loading .loading-spinner.small {
  width: 14px;
  height: 14px;
  border-width: 2px;
}
.qv-ai-fail {
  margin: 0;
  font-size: 13px;
  color: var(--color-muted);
  font-style: italic;
}

/* Action bar */
.qv-action-bar {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-3);
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: 1px solid rgba(0, 0, 0, 0.06);
  flex-wrap: wrap;
}
.qv-action-bar #qv-action-new { margin-right: auto; }
.qv-action-bar .btn-ghost,
.qv-action-bar .btn-primary {
  padding: 10px 18px;
  border-radius: var(--radius-md);
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  border: none;
  font-family: var(--font-sans);
}
.qv-action-bar .btn-ghost {
  background: transparent;
  color: var(--color-text);
  border: 1px solid rgba(0, 0, 0, 0.12);
}
.qv-action-bar .btn-ghost:hover:not(:disabled) {
  border-color: rgba(0, 0, 0, 0.24);
}
.qv-action-bar .btn-ghost:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
.qv-action-bar .btn-primary {
  background: var(--color-primary);
  color: #FFFFFF;
}
.qv-action-bar .btn-primary:hover:not(:disabled) {
  filter: brightness(0.94);
}
.qv-lock { margin-right: 2px; }

/* =========================================================================
 * === QUICK VAL v1.9 ADDITIONS — Demo Isolated View + Formatted Inputs ===
 *
 * Demo mode now renders a completely separate top-level view (sibling
 * of authed-view) with its own top bar and two-panel layout. The
 * authenticated dashboard shell + toolbar are never loaded in demo
 * mode; nothing in this section affects authed-mode rendering.
 * ========================================================================= */

/* ----- DEMO TOP BAR -----
 * Single thin strip with the wordmark + context label on the left and
 * Share / Sign in / Sign up actions on the right. v1.10: wordmark
 * compressed so the right-side actions and the centered form below
 * have room. .demo-context replaces the old org-name slot from the
 * authed top-bar so the demo top-bar parallels its layout. */
.demo-top-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--color-surface);
  border-bottom: 1px solid rgba(0, 0, 0, 0.08);
  padding: 0 var(--space-5);
  height: 56px;
}
.demo-top-bar .demo-top-left {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
}
.demo-top-bar .brand {
  font-weight: 600;
  font-size: 13px;
  color: var(--color-text);
  letter-spacing: -0.04em;
  /* v1.13 fix — constrain the wordmark to its compressed footprint
     so the demo top-bar left cluster stays balanced against the
     'Share this demo / Sign in / Sign up' actions on the right. The
     "Vantage" mark renders ~50px wide at 13px/600/-0.04em letter-
     spacing; max-width 60px is a tight cap with a small safety
     margin. white-space + overflow guard against future font swaps
     that could otherwise push the wordmark past the cap. Only the
     demo-top-bar instance is affected — the .top-bar .brand rule
     above (authed nav, 16px/700) keeps its full presence. */
  max-width: 60px;
  white-space: nowrap;
  overflow: hidden;
}
.demo-top-bar .brand-sep {
  color: var(--color-muted);
  font-size: 13px;
}
.demo-top-bar .demo-context {
  font-size: 13px;
  color: var(--color-muted);
  letter-spacing: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.demo-top-actions {
  display: flex;
  align-items: center;
  gap: var(--space-4);
}
.demo-top-actions .demo-share-link {
  color: var(--color-text);
  text-decoration: none;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
}
.demo-top-actions .demo-share-link:hover {
  color: var(--color-primary);
}
.demo-top-actions .demo-signin-link {
  color: var(--color-text);
  text-decoration: none;
  font-size: 14px;
  font-weight: 500;
}
.demo-top-actions .demo-signin-link:hover {
  color: var(--color-primary);
}
.demo-top-actions .demo-signup-btn {
  background: var(--color-primary);
  color: #FFFFFF;
  border: none;
  border-radius: var(--radius-md);
  padding: 8px 18px;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  font-family: var(--font-sans);
}
.demo-top-actions .demo-signup-btn:hover { filter: brightness(0.94); }

/* ----- DEMO MAIN GRID -----
 * Left panel ~35%, right panel ~65%. The whole experience targets a
 * 1280×800 laptop screen without scroll — the right panel uses the
 * compact form overrides below. */
.demo-main {
  display: grid;
  grid-template-columns: minmax(320px, 35%) 1fr;
  gap: var(--space-5);
  padding: var(--space-5);
  max-width: 1440px;
  margin: 0 auto;
}
@media (max-width: 900px) {
  .demo-main { grid-template-columns: 1fr; }
}

/* ----- DEMO LEFT PANEL ----- */
.demo-left {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  padding: var(--space-2);
}
.demo-headline {
  margin: 0 0 var(--space-2) 0;
  font-size: 26px;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--color-text);
  line-height: 1.2;
}
.demo-subhead {
  margin: 0;
  font-size: 14px;
  color: var(--color-text);
  line-height: 1.5;
}
.demo-features {
  list-style: none;
  padding: 0;
  margin: var(--space-3) 0 0 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.demo-feature-row {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
}
.demo-feature-icon {
  flex: 0 0 32px;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-md);
  background: rgba(42, 157, 143, 0.10);
  color: var(--color-primary);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.demo-feature-icon svg { width: 16px; height: 16px; }
.demo-feature-body {
  flex: 1 1 auto;
}
.demo-feature-title {
  margin: 0 0 2px 0;
  font-size: 14px;
  font-weight: 600;
  color: var(--color-text);
}
.demo-feature-blurb {
  margin: 0;
  font-size: 12px;
  color: var(--color-muted);
  line-height: 1.45;
}

/* v1.10: share-this-demo moved to a top-bar modal (#share-overlay).
   See SHARE MODAL section below. Left-panel "Try with your own
   company →" CTA replaces the share block as the left-panel anchor. */
.demo-cta-wrap {
  margin-top: auto;
  display: flex;
  flex-direction: column;
}
.demo-cta-wrap .demo-cta-btn {
  width: 100%;
  text-align: center;
}

/* ----- DEMO RIGHT PANEL -----
 * The Quick Val results view, rendered into #demo-quickval-root.
 * Compact overrides below shrink padding/heights so everything fits
 * 1280×800 without scroll. */
.demo-right {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

/* In-content action bar above the results grid (demo only). v1.10:
   Parameters + Save sit on the left; version / show-changes / export
   stay on the right. Authed mode uses the persistent app toolbar. */
.demo-action-bar {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}
.demo-action-bar .demo-action-left {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.demo-action-bar .demo-action-right {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.demo-action-bar .qv-version-select { padding: 6px 10px; font-size: 12px; }
.demo-action-bar .qv-toggle         { padding: 6px 10px; font-size: 12px; }
.demo-action-bar .qv-export-btn     { padding: 6px 10px; font-size: 12px; }

/* Parameters button — warm slate grey so it reads as a secondary
   control distinct from teal. Used in both the toolbar and the
   demo-action-bar via separate selectors (kept symmetrical). */
.toolbar-params-btn {
  background: #6B7280;
  color: #FFFFFF;
  border: none;
  border-radius: var(--radius-md);
  padding: 8px 14px;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  font-family: var(--font-sans);
}
.toolbar-params-btn:hover { filter: brightness(0.94); }
.demo-action-bar .qv-params-btn {
  background: #6B7280;
  color: #FFFFFF;
  border: none;
  border-radius: var(--radius-md);
  padding: 6px 12px;
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  font-family: var(--font-sans);
}
.demo-action-bar .qv-params-btn:hover { filter: brightness(0.94); }

/* Demo Save button — light grey to read as a soft CTA in demo mode.
   v1.10: clicking opens the signup modal; never writes to the DB. */
.demo-action-bar .qv-save-btn {
  background: #E5E7EB;
  color: var(--color-text);
  border: none;
  border-radius: var(--radius-md);
  padding: 6px 12px;
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  font-family: var(--font-sans);
}
.demo-action-bar .qv-save-btn:hover { background: #D1D5DB; }

/* "Try with your own company →" CTA. v1.10: moved out of the results
   right-panel flow and into .demo-left (above the share block, now
   in the top bar). Full-width primary teal anchor. */
.demo-cta-btn {
  background: var(--color-primary);
  color: #FFFFFF;
  border: none;
  border-radius: var(--radius-md);
  padding: 12px 28px;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  font-family: var(--font-sans);
  letter-spacing: 0.01em;
}
.demo-cta-btn:hover { filter: brightness(0.94); }

/* Compact form overrides — only inside .demo-right scope so authed
   mode is untouched. Tighter padding + smaller hero numbers. */
.demo-right .qv-inputs    { padding: var(--space-3) var(--space-4); }
.demo-right .qv-input-row { padding: 4px 0; grid-template-columns: 140px 1fr; }
.demo-right .qv-input     { padding: 6px 10px; font-size: 13px; }
.demo-right textarea.qv-input { min-height: 44px; }
.demo-right .qv-scenarios { padding: var(--space-3) var(--space-4); }
.demo-right .qv-scenario-table td { padding: var(--space-2); font-size: 14px; }
.demo-right .qv-scenario-table th { padding: 6px var(--space-2); }
.demo-right .qv-ai-card   { padding: var(--space-3) var(--space-4); }
.demo-right .qv-ai-body   { font-size: 13px; line-height: 1.45; }
.demo-right .qv-section-title { margin-bottom: 6px; }

/* v1.10: bring the company name closer to the top white toolbar and
   make it more prominent. Demo-only override — the authed sticky
   header retains its own breathing room. */
.demo-right .qv-results-header {
  position: static;
  padding: var(--space-2) 0 var(--space-3);
  margin-bottom: var(--space-2);
  border-bottom: none;
}
.demo-right .qv-company-edit {
  font-size: 26px;
  font-weight: 600;
}

/* ----- FORMATTED INPUT (results view) -----
 * Text inputs styled as numerics so the formatted display ($X.XM,
 * X%, Xx) reads correctly. On focus the JS handler swaps the value
 * to the raw number for editing; on blur it reformats and stores
 * raw on dataset.raw for recompute. */
.qv-input[data-input-format] {
  font-variant-numeric: tabular-nums;
  text-align: left;
}
.qv-input[data-input-format]::placeholder {
  color: var(--color-muted);
}

/* =========================================================================
 * === v1.10 — SHARE / PARAMETERS / SIGNUP MODALS =========================
 *
 * Three standalone overlays following the same pattern as
 * .account-overlay / .terms-overlay. All live as top-level siblings
 * of #demo-view inside #app so they can be opened from demo or
 * authed mode (demo for share + signup, both for parameters).
 * z-index 310 matches terms-overlay (above account-overlay at 300).
 * ========================================================================= */

/* ----- SHARE MODAL -----
 * Top-bar-triggered (demo-share-link). Email chip input + mailto:
 * send. Replaces the v1.9 inline share block in the left panel. */
.share-overlay {
  position: fixed;
  inset: 0;
  background: rgba(27, 27, 27, 0.32);
  z-index: 310;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6) var(--space-5);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s ease;
}
.share-overlay.open {
  opacity: 1;
  pointer-events: all;
}
.share-modal {
  width: 100%;
  max-width: 480px;
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-pop);
  padding: var(--space-5) var(--space-5) var(--space-5);
  transform: scale(0.97) translateY(8px);
  transition: transform 0.18s ease;
}
.share-overlay.open .share-modal {
  transform: scale(1) translateY(0);
}
.share-modal-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-2);
}
.share-modal-title {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  color: var(--color-primary);
  letter-spacing: -0.01em;
}
.share-modal-close {
  background: transparent;
  border: none;
  color: var(--color-muted);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 2px 8px;
  border-radius: var(--radius-sm);
}
.share-modal-close:hover {
  background: var(--color-bg);
  color: var(--color-text);
}
.share-modal-blurb {
  margin: 0 0 var(--space-4) 0;
  font-size: 13px;
  color: var(--color-muted);
}
.share-modal-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: var(--space-3);
}
.share-modal-send {
  background: var(--color-primary);
  color: #FFFFFF;
  border: none;
  border-radius: var(--radius-md);
  padding: 8px 18px;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  font-family: var(--font-sans);
}
.share-modal-send:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}
.share-modal-send:hover:not(:disabled) { filter: brightness(0.94); }
.share-modal-msg {
  font-size: 12px;
  color: var(--color-muted);
  margin: var(--space-2) 0 0 0;
}
.share-modal-msg.success { color: var(--color-success); }
.share-modal-msg.error   { color: var(--color-danger);  }

/* ----- PARAMETERS MODAL -----
 * Bear / Bull adjustment percentages applied to base-case exit
 * valuation. Values live on quickValState.params (session only,
 * not persisted to DB in v1.10). Apply triggers recompute. */
.params-overlay {
  position: fixed;
  inset: 0;
  background: rgba(27, 27, 27, 0.32);
  z-index: 310;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6) var(--space-5);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s ease;
}
.params-overlay.open {
  opacity: 1;
  pointer-events: all;
}
.params-modal {
  width: 100%;
  max-width: 440px;
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-pop);
  padding: var(--space-5);
  transform: scale(0.97) translateY(8px);
  transition: transform 0.18s ease;
}
.params-overlay.open .params-modal {
  transform: scale(1) translateY(0);
}
.params-modal-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-2);
}
.params-modal-title {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  color: var(--color-primary);
  letter-spacing: -0.01em;
}
.params-modal-close {
  background: transparent;
  border: none;
  color: var(--color-muted);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 2px 8px;
  border-radius: var(--radius-sm);
}
.params-modal-close:hover {
  background: var(--color-bg);
  color: var(--color-text);
}
.params-modal-blurb {
  margin: 0 0 var(--space-4) 0;
  font-size: 13px;
  color: var(--color-muted);
}
.params-modal-row {
  display: grid;
  grid-template-columns: 1fr 110px;
  gap: var(--space-3);
  align-items: center;
  padding: var(--space-2) 0;
}
.params-modal-row label {
  font-size: 13px;
  color: var(--color-text);
}
.params-modal-row input {
  width: 100%;
  padding: 8px 12px;
  border: 1px solid rgba(0, 0, 0, 0.10);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  font-family: var(--font-sans);
  font-size: 14px;
  color: var(--color-text);
  text-align: right;
  box-sizing: border-box;
  font-variant-numeric: tabular-nums;
}
.params-modal-row input:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px rgba(42, 157, 143, 0.12);
}
.params-modal-actions {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--space-2);
  margin-top: var(--space-4);
}
.params-modal-apply {
  background: var(--color-primary);
  color: #FFFFFF;
  border: none;
  border-radius: var(--radius-md);
  padding: 10px 18px;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  font-family: var(--font-sans);
}
.params-modal-apply:hover { filter: brightness(0.94); }
.params-modal-reset {
  background: transparent;
  border: none;
  color: var(--color-muted);
  font-size: 12px;
  cursor: pointer;
  text-decoration: underline;
  padding: 4px;
  font-family: var(--font-sans);
}
.params-modal-reset:hover { color: var(--color-text); }
.params-modal-error {
  font-size: 12px;
  color: var(--color-danger);
  margin: var(--space-2) 0 0 0;
  min-height: 16px;
}

/* ----- SIGNUP MODAL -----
 * Two entry points (demo Save / "Try with your own company →") that
 * both teleport the existing .auth-card into #signup-modal-mount,
 * preserving every auth.js event handler. On close the card is
 * moved back to #auth-view. Title + subtext set per context. */
.signup-overlay {
  position: fixed;
  inset: 0;
  background: rgba(27, 27, 27, 0.32);
  z-index: 310;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6) var(--space-5);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s ease;
}
.signup-overlay.open {
  opacity: 1;
  pointer-events: all;
}
.signup-modal {
  width: 100%;
  max-width: 480px;
  max-height: calc(100vh - 96px);
  overflow-y: auto;
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-pop);
  padding: var(--space-5);
  transform: scale(0.97) translateY(8px);
  transition: transform 0.18s ease;
}
.signup-overlay.open .signup-modal {
  transform: scale(1) translateY(0);
}
.signup-modal-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-2);
}
.signup-modal-title {
  margin: 0;
  font-size: 20px;
  font-weight: 600;
  color: var(--color-primary);
  letter-spacing: -0.01em;
}
.signup-modal-close {
  background: transparent;
  border: none;
  color: var(--color-muted);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 2px 8px;
  border-radius: var(--radius-sm);
}
.signup-modal-close:hover {
  background: var(--color-bg);
  color: var(--color-text);
}
.signup-modal-blurb {
  margin: 0 0 var(--space-3) 0;
  font-size: 13px;
  color: var(--color-muted);
}
/* Scope auth-card overrides to the modal mount so the teleported
   card sits flush inside the modal — no double border / shadow /
   wide padding. The original .auth-card rules apply only at the
   auth-view depth so the regular view is unaffected. */
.signup-modal .auth-card {
  box-shadow: none;
  background: transparent;
  padding: 0;
  margin: 0;
  max-width: 100%;
  width: 100%;
}
.signup-modal .auth-card h1 { display: none; }
.signup-modal .auth-card .subtitle { display: none; }

/* v1.13 — when the auth card is teleported into the signup modal,
   the "Try a live demo" link is redundant (user is already in the
   demo) and the "Forgot password?" link makes no sense (intent is
   signup, not sign-in). Both rows hide via class + ID selectors so
   the rule survives either a future markup tweak (id renamed) or a
   future class tweak (id renamed). */
.in-signup-modal #auth-demo-row,
.in-signup-modal .auth-demo-row,
.in-signup-modal #auth-forgot-row,
.in-signup-modal .auth-forgot-row {
  display: none !important;
}

/* --- FIELD VALIDATION (v1.12) ---
   Inline error styling shared by every form on the platform. The
   .field-error-active class is applied directly to <input>, <select>,
   or <textarea> (or onto the .qv-smart-dd / .chip-input-wrap wrapper
   when the visual border lives there rather than on the inner control).
   The accompanying .field-error span is inserted as the next sibling
   of the input (or wrapper) by showFieldError() in js/utils.js. */
input.field-error-active,
select.field-error-active,
textarea.field-error-active {
  border-color: #DC3545;
  outline: none;
}
input.field-error-active:focus,
select.field-error-active:focus,
textarea.field-error-active:focus {
  box-shadow: 0 0 0 3px rgba(220, 53, 69, 0.15);
}
.field-error {
  display: block;
  font-size: 12px;
  color: #DC3545;
  margin-top: 4px;
  line-height: 1.4;
  min-height: 0;
  animation: field-error-in 0.15s ease;
}
@keyframes field-error-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}
/* Smart dropdown error state — class is applied to the .qv-smart-dd
   wrapper so the visible trigger picks up the red border. */
.qv-smart-dd.field-error-active .qv-smart-dd-trigger {
  border-color: #DC3545;
}
/* Chip input error state — class is applied to the .chip-input-wrap
   so the bordered chip region tints red. */
.chip-input-wrap.field-error-active {
  border-color: #DC3545;
}
