/*
ScaleIQ shared design tokens + components — the one place the dark theme
(colors, fonts, spacing, and reusable component classes) lives. Every page in
the app pulls from this file (via {% static 'css/theme.css' %} in
templates/base.html and the standalone error/login templates); a future
phase's UI (Call/Coach going real, Phase 2's research-status partial) should
extend it rather than re-deriving the palette.

Served as a real static asset via Django's staticfiles app with
WHITENOISE_USE_FINDERS=True (config/settings.py) — no collectstatic build
step required; see docs/theme-guide.md's "Deploy note" for why. (This file
used to live under templates/ and get pulled in with an include tag instead,
back when the manifest-storage backend made a real static asset unsafe to
add without collectstatic actually running. That's fixed now, so it moved
here — a real .css file, not parsed as a template.)
*/

:root {
  /* surfaces */
  --bg: #0a100d;
  --card-bg: #101a15;
  --card-border: #1f2b25;
  --input-border: #24352c;

  /* text */
  --text-primary: #eef3f0;
  --text-heading: #f4f8f6;
  --text-secondary: #9db3a8;
  --text-muted: #7b9186;
  /* Lightened from #56695f — the original failed WCAG AA (4.5:1) for
     normal text against both --bg (3.28:1) and --card-bg (3.03:1), and
     this is real small (11-13px) text throughout the app (timestamps,
     optional-field markers, empty states), not decorative. #78877f clears
     4.5:1 against the harder case (--card-bg, 4.72:1) with real margin —
     see docs/detail-page-restructure-design.md's contrast pass. */
  --text-faint: #78877f;
  --text-footnote: #4a5c52;

  /* accent + status */
  --accent: #39d367;
  --accent-hover: #5be085;
  --warning: #f5b942;
  --error: #dc5959;
  /* Alpha lowered from 0.12 — at 0.12 the resulting tint made --error text
     on top of it fail AA (4.20:1 vs. the 4.5:1 needed for .badge-lost/
     .btn-danger:hover, both real small text) by a narrow margin. --error
     itself is unchanged (already passes everywhere it's plain text on
     --bg); darkening its own background tint clears the gap instead. */
  --error-bg: rgba(220, 89, 89, 0.04);
  /* Round 2 additions — info/caution/insight accents for the initiative
     detail page's restructure (docs/detail-page-restructure-design.md).
     Real audit before adding: no blue or violet token existed anywhere in
     this file; --warning (amber) and --error (danger) already did and are
     reused as-is below rather than duplicated. Both new hex values clear
     AA at every size they're used at (plain text on --bg/--card-bg, and as
     a 12% tint background under their own text, matching .badge-internal/
     .badge-client's existing alpha) — see that doc's Round 2 contrast
     table for the real computed ratios. */
  --info: #5b9dff;
  --insight: #b389f9;

  /* spacing scale — named after the pixel values already in real use across
     the guided flow, not invented fresh */
  --space-xs: 6px;
  --space-sm: 12px;
  --space-md: 16px;
  --space-lg: 24px;
  --space-xl: 32px;
  --space-2xl: 48px;

  /* fonts */
  --font-heading: 'Space Grotesk', sans-serif;
  --font-body: 'Manrope', system-ui, sans-serif;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--font-body);
  background: var(--bg);
  background-image: linear-gradient(180deg, #0d1712 0%, #0a100d 40%);
  background-attachment: fixed;
  color: var(--text-primary);
  min-height: 100vh;
}

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

input, textarea, select {
  font-family: var(--font-body);
  background: var(--card-bg);
  border: 1px solid var(--input-border);
  color: var(--text-primary);
  border-radius: 3px;
  outline: none;
  padding: 12px 14px;
  font-size: 14px;
  width: 100%;
}
/* Round 2 (site-wide visual system, Round 2) — the glow ring reuses
   ctaGlow's own literal rest-state value (0 0 6px rgba(57, 211, 103,
   0.45), the exact numbers already defined below for .btn-primary:hover)
   as a static ring, not the animation itself — a continuously pulsing
   glow on every focused field would be a distracting, unusual UX pattern
   this app doesn't use anywhere else; the value is what's reused, not
   the motion. border-color: var(--accent) here is unchanged from before
   this pass. */
input:focus, textarea:focus, select:focus {
  border-color: var(--accent);
  box-shadow: 0 0 6px rgba(57, 211, 103, 0.45);
}
input[type="checkbox"], input[type="radio"] { width: auto; padding: 0; accent-color: var(--accent); }
input::placeholder, textarea::placeholder { color: var(--text-faint); }

label {
  display: block; font-size: 11px; letter-spacing: 0.6px; font-weight: 700;
  color: var(--text-muted); margin-bottom: var(--space-xs); text-transform: uppercase;
}

/* Plain Django form.as_p() rendering — label/input/help/error, no new form library */
form p { margin: 0 0 var(--space-md); }
form p ul.errorlist { color: var(--error); font-size: 12px; list-style: none; padding: 0; margin: 4px 0 0; }
form p .helptext {
  display: block; color: var(--text-footnote); font-size: 11px; margin-top: 4px;
  text-transform: none; letter-spacing: normal;
}

button { font-family: var(--font-body); cursor: pointer; border: none; }

::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-thumb { background: var(--input-border); }

/* Headings + section card */
.heading { font-family: var(--font-heading); font-weight: 700; color: var(--text-heading); }
.card {
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: 4px;
  padding: var(--space-lg);
}

/* Page container for plain (non-flow-stage) screens */
.page { max-width: 1080px; margin: 0 auto; padding: var(--space-xl) var(--space-2xl); }
.page-back { font-size: 13px; color: var(--text-muted); margin-bottom: var(--space-md); display: inline-block; }
.page-title { font-size: 26px; margin: 0 0 var(--space-lg); }
.section-title {
  font-family: var(--font-heading); font-weight: 700; color: var(--text-heading);
  font-size: 15px; letter-spacing: 0.3px; margin: var(--space-xl) 0 var(--space-md);
  padding-top: var(--space-md); border-top: 2px solid var(--card-border);
  position: relative;
}
/* restrained checkered-flag accent — a header rule, not a repeating pattern */
.section-title::before {
  content: ""; position: absolute; top: -2px; left: 0; width: 16px; height: 2px;
  background-image:
    linear-gradient(45deg, var(--accent) 25%, transparent 25%, transparent 75%, var(--accent) 75%),
    linear-gradient(45deg, var(--accent) 25%, transparent 25%, transparent 75%, var(--accent) 75%);
  background-size: 4px 4px; background-position: 0 0, 2px 2px;
}

/* Buttons */
.btn-primary {
  display: inline-block; background: var(--accent); color: var(--bg); font-size: 15px; font-weight: 700;
  padding: 16px 38px; border-radius: 3px; letter-spacing: 0.2px; text-align: center;
}
.btn-primary:hover { background: var(--accent-hover); color: var(--bg); }
/* Round 2 — one of exactly three pulse/glow spots in this app (see
   .dot-circle-track.active and .badge-pulse); purely decorative (a glow,
   not a text/background pairing), guarded by prefers-reduced-motion below. */
.btn-primary:hover, .btn-primary:focus-visible { animation: ctaGlow 1.6s ease-in-out infinite; }
.btn-primary[disabled] { opacity: 0.5; cursor: not-allowed; }
/* Loading state for a submit button mid-flight on a slow, synchronous
   request (e.g. Go — see static/js/app.js's data-loading-label handler). */
.btn-spinner {
  display: inline-block; width: 13px; height: 13px; margin-right: 8px; vertical-align: -2px;
  border: 2px solid rgba(11, 15, 13, 0.35); border-top-color: var(--bg); border-radius: 50%;
  animation: btn-spin 0.8s linear infinite;
}
@keyframes btn-spin { to { transform: rotate(360deg); } }
.btn-secondary {
  display: inline-block; background: transparent; color: var(--text-secondary); font-size: 14px; font-weight: 700;
  padding: 12px 22px; border: 1px solid var(--card-border); border-radius: 3px; text-align: center;
}
/* Round 2b — a real secondary-action hover treatment where there was none
   before (confirmed by reading this file before this pass: `.btn-secondary`
   had zero hover glow anywhere on the site, not just on the list page's
   "Advanced setup" button that surfaced the gap). Reuses ctaGlow's own
   literal rest-state value (0 0 6px rgba(57, 211, 103, 0.45)) as a static
   ring — the same already-established "reuse the number, not the motion"
   pattern input:focus uses above — deliberately not the full pulsing
   ctaGlow animation itself, which stays reserved for primary actions. No
   transform/lift: no such pattern exists anywhere else in this file, and
   inventing one here would be a new component, not a carry-through. */
.btn-secondary:hover, .btn-secondary:focus-visible {
  color: var(--text-heading);
  border-color: var(--text-muted);
  box-shadow: 0 0 6px rgba(57, 211, 103, 0.45);
}
.btn-ghost {
  display: inline-block; background: transparent; color: var(--text-muted); font-size: 14px; font-weight: 700;
  padding: 16px 22px;
}
.btn-ghost:hover { color: var(--text-secondary); }
.btn-danger {
  display: inline-block; background: transparent; color: var(--error); font-size: 13px; font-weight: 700;
  padding: 8px 14px; border: 1px solid var(--error); border-radius: 3px; text-align: center;
}
.btn-danger:hover { background: var(--error-bg); }
.btn-sm { font-size: 12px; padding: 6px 12px; }

/* Badges — a stage/status marker, styled like a lap marker */
.badge {
  font-size: 10px; letter-spacing: 0.5px; font-weight: 700; padding: 3px 8px; border-radius: 2px;
  display: inline-block; white-space: nowrap;
}
.badge-internal { color: var(--warning); background: rgba(245, 185, 66, 0.12); }
.badge-client { color: var(--accent); background: rgba(57, 211, 103, 0.12); }
/* Alpha lowered from 0.14 — with the lightened --text-faint above as the
   foreground, the old alpha still failed AA (4.19:1 vs. 4.5:1 needed)
   against --card-bg; 0.05 clears it (4.53:1) — see contrast pass notes. */
.badge-muted { color: var(--text-faint); background: rgba(86, 105, 95, 0.05); }
.badge-progress { color: var(--accent); background: rgba(57, 211, 103, 0.12); }
.badge-won { color: var(--bg); background: var(--accent); }
.badge-lost { color: var(--error); background: var(--error-bg); }
.badge-stalled { color: var(--text-faint); background: rgba(86, 105, 95, 0.05); }
/* Round 2 correction — solid-fill badge modifiers, replacing the low-alpha
   tinted-text .badge-info/.badge-insight (and the reused .badge-won/
   .badge-internal/.badge-lost) that read as outlined rather than the
   mockup's solid pills. Used alongside the base .badge class on every
   badge Round 2 introduced or recolored (risk_of_stalling,
   MaturityAssessment.level, the transcript score badges) — everywhere
   else in the app (OutcomeRecord.outcome_type, the initiative list, doc
   types) is untouched. Dark --bg text on each solid fill all clear AA
   with real margin — see docs/detail-page-restructure-design.md's Round 2
   correction section for the full ratio table. */
.badge.b-green { color: var(--bg); background: var(--accent); }
.badge.b-amber { color: var(--bg); background: var(--warning); }
.badge.b-coral { color: var(--bg); background: var(--error); }
.badge.b-blue { color: var(--bg); background: var(--info); }
.badge.b-violet { color: var(--bg); background: var(--insight); }
.badge.b-slate { color: var(--text-heading); background: var(--card-border); }
/* A `risk_of_stalling: high` badge specifically (never medium/low, never
   any other b-coral use) gets a pulsing glow — see .btn-primary:hover
   and .dot-circle-track.active below for the other two Round 2 pulse
   spots; all three share the same prefers-reduced-motion guard. */
.badge-pulse { animation: pulseGlow 1.6s ease-in-out infinite; }

/* Messages (Django's messages framework) */
.messages { list-style: none; padding: 0 var(--space-2xl); margin: 18px 0 0; }
.messages.messages-flush { padding: 0; margin: 0 0 var(--space-md); }
.messages li {
  padding: 0.6rem 1rem; margin-bottom: var(--space-xs); border-radius: 4px;
  border: 1px solid transparent; font-size: 13px;
}
.messages li.success { background: rgba(57, 211, 103, 0.12); border-color: var(--accent); }
.messages li.warning { background: rgba(245, 185, 66, 0.12); border-color: var(--warning); }
.messages li.error { background: var(--error-bg); border-color: var(--error); }

/* Top bar / shared header+nav */
.topbar { display: flex; align-items: center; justify-content: space-between; padding: 28px var(--space-2xl) 0 var(--space-2xl); flex-wrap: wrap; gap: var(--space-sm); }
.wordmark { font-family: var(--font-heading); font-weight: 700; font-size: 22px; letter-spacing: 0.5px; color: var(--text-heading); }
.wordmark .accent { color: var(--accent); }
.topbar-sub { font-size: 13px; color: var(--text-faint); font-weight: 500; }
.topbar-right { font-size: 13px; color: var(--text-secondary); font-weight: 500; display: flex; align-items: center; gap: var(--space-md); }
.topbar-right a { color: var(--text-muted); font-weight: 600; font-size: 13px; }

/* Progress / lap track — used by both the guided flow's step dots
   (initiatives.flow.flow_dots) and the stage lap track
   (initiatives.templatetags.theme_tags.stage_track); same visual family,
   same markup shape ({num, label, state}), reused via
   initiatives/templates/initiatives/_dots.html for both. */
.dots-row { display: flex; align-items: center; justify-content: center; gap: var(--space-xs); padding: 26px var(--space-2xl) 10px var(--space-2xl); flex-wrap: wrap; }
.dots-row.dots-row-compact { justify-content: flex-start; padding: 0; }
.dot-group { display: flex; align-items: center; gap: var(--space-xs); }
.dot-col { display: flex; flex-direction: column; align-items: center; gap: var(--space-xs); width: 84px; }
.dots-row-compact .dot-col { width: 54px; }
.dot-circle {
  position: relative;
  width: 26px; height: 26px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700; font-family: var(--font-heading);
}
.dots-row-compact .dot-circle { width: 18px; height: 18px; font-size: 9px; }
.dot-circle.done, .dot-circle.active { background: var(--accent); color: var(--bg); }
/* Round 2 — the current stage's pulse, but ONLY on the initiative detail
   page's race-position track (._dots.html's `clickable` param adds this
   modifier class; the guided flow's own progress dots never do, and never
   pulse — this round doesn't touch the flow). One of exactly three
   pulse/glow spots in this app; guarded by prefers-reduced-motion below. */
.dot-circle-track.active { animation: currentPulse 1.8s ease-in-out infinite; }
/* Round 2 (site-wide visual system, Round 2) — completes the one area the
   prior round deliberately left untouched: the guided flow's own progress
   dots (._dots.html rendered with `flow=True`, from flow/_body.html and
   quick_start.html — never the detail page's race track, which keeps its
   own `-track` modifier above, independent of this one). Real bg-text
   contrast on the gradient's lighter endpoint (--accent-hover) is 11.39:1
   — see initiatives/tests/test_theme_contrast.py.

   Reuses `currentPulse` (green), not `pulseGlow` (coral/red, reserved
   everywhere else in this app for a risk_of_stalling: high badge) — the
   flow's current step is the identical "you are here, this is normal"
   concept the detail page's own race-track current-stage dot already
   uses that keyframe for; a coral pulse on an ordinary in-progress step
   would read as a danger/error state matching nothing else on these
   screens. Flagged explicitly since a literal reading of the build spec
   named `pulseGlow` instead — see docs/site-wide-visual-system-design.md's
   Round 2 section for the full note. */
.dot-circle-flow.done, .dot-circle-flow.active {
  background: linear-gradient(135deg, var(--accent), var(--accent-hover));
}
.dot-circle-flow.active { animation: currentPulse 1.8s ease-in-out infinite; }
/* #5f7267 was failing AA even at the 3:1 UI-component floor (2.86:1)
   against --card-border — real text (the step number inside the dot),
   just intentionally the least-emphasized state. #8c9992 clears 3:1 with
   real margin (4.97:1) while staying visibly duller than done/active. */
.dot-circle.upcoming { background: var(--card-border); color: #8c9992; }
.dot-label { font-size: 10px; letter-spacing: 0.6px; font-weight: 700; }
.dots-row-compact .dot-label { font-size: 9px; }
.dot-label.active { color: var(--text-heading); }
.dot-label.done { color: var(--text-muted); }
/* #3f4d46 was failing badly (2.16:1) against --bg — real text (a future
   stage's name). #7e8883 clears 4.5:1 (5.24:1) while still reading as
   the most de-emphasized of the three dot-label states. */
.dot-label.upcoming { color: #7e8883; }
.dot-connector { width: 34px; height: 2px; margin-bottom: 16px; }
.dots-row-compact .dot-connector { width: 14px; margin-bottom: 9px; }
.dot-connector.done { background: var(--accent); }
.dot-connector.upcoming { background: var(--card-border); }
/* Round 2 (site-wide visual system, Round 2) — the guided flow's own
   connector between completed steps, gradient-filled like its dots above
   (`--card-border` upcoming color is shared/unchanged — no gap there to
   resolve). No pre-existing "green gradient" token pairing existed
   anywhere in this file before this pass (confirmed by searching for
   every real `gradient` use here) — this reuses the two existing green
   tokens (`--accent`/`--accent-hover`) rather than adding a new one. */
.dot-connector-flow.done { background: linear-gradient(90deg, var(--accent), var(--accent-hover)); }
/* the finish-line dot (stage track's CLOSED_WON) gets the checkered accent
   instead of a plain checkmark */
.dot-circle.finish { background-image:
    linear-gradient(45deg, var(--bg) 25%, transparent 25%, transparent 75%, var(--bg) 75%),
    linear-gradient(45deg, var(--bg) 25%, transparent 25%, transparent 75%, var(--bg) 75%);
  background-color: var(--accent); background-size: 6px 6px; background-position: 0 0, 3px 3px;
}

/* Race-position track click-to-log (Round 2, initiative detail page only —
   never the flow's own progress dots): a dot becomes a plain link, not
   restyled beyond removing the global `a` color/underline so the dot's own
   state colors (done/active/upcoming) still apply, plus a hover ring so it
   reads as clickable. */
.dot-link {
  display: flex; flex-direction: column; align-items: center; gap: var(--space-xs);
  text-decoration: none; color: inherit;
}
.dot-link:hover .dot-circle { box-shadow: 0 0 0 2px var(--accent); }
.dot-link:hover .dot-label { color: var(--text-heading); }
/* The has-logged-entry badge — deliberately a distinct color (amber, not
   the green used for done/active) and shape (a small corner pip, not a
   filled circle) from the current-stage highlight, so the two signals
   ("something's logged here" vs. "this is where the deal officially is")
   never read as the same thing at a glance. */
.dot-logged-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--warning); }
.dot-logged-badge {
  position: absolute; top: -3px; right: -3px;
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--warning); border: 2px solid var(--bg);
}

/* Flow-only layout (guided flow's centered single-stage screens).
   .stage's bottom padding reserves real room for the fixed .bottom-nav
   below (~88px tall: two --space-md paddings plus a .btn-primary's own
   16px vertical padding and line height) plus a bit of breathing room, so
   a step's last real content — a Coach step's final sales-skill area, a
   Call step's full transcript text — never ends up hidden underneath it. */
.stage { flex: 1; display: flex; align-items: center; justify-content: center; padding: 0 var(--space-2xl) 110px var(--space-2xl); min-height: 0; }
.stage-inner { width: 100%; max-width: 1080px; }
/* Fixed, not just sticky, so Back/Continue stay reachable the instant a
   rep lands on a long step (a research panel, a full transcript, the
   Coach step's five-section breakdown) without scrolling past it first —
   a solid --card-bg (not transparent) plus a top border and shadow so it
   reads as anchored chrome, not a floating overlay scrolled content could
   bleed through. */
.bottom-nav {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-md) var(--space-2xl);
  background: var(--card-bg);
  border-top: 1px solid var(--card-border);
  box-shadow: 0 -8px 20px rgba(0, 0, 0, 0.35);
  z-index: 30;
}

@media (max-width: 640px) {
  .stage { padding-left: var(--space-md); padding-right: var(--space-md); }
  .bottom-nav { padding-left: var(--space-md); padding-right: var(--space-md); }
}

/* Coach step: a coaching suggestion (a deviation's coaching_note, a
   sales-skill area's suggested_improvement) needs to be visually obvious
   at a glance next to the plain description text it sits below — a real
   rep complaint was "hard to distinguish." A tinted accent-colored callout
   box with its own label, not just a subtle color change on the text
   itself. */
.coaching-callout {
  background: rgba(57, 211, 103, 0.12);
  border-left: 3px solid var(--accent);
  border-radius: 4px;
  padding: 10px 12px;
  margin-top: 8px;
  font-size: 12px;
  color: var(--text-primary);
  line-height: 1.5;
}
.coaching-callout-label {
  display: block;
  font-family: var(--font-heading);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 4px;
}

/* Collapsed-by-default "Research" section on the Review step — the actual
   panel content (initiatives/_research_panel.html) is unchanged, just
   wrapped, so a rep sees the document cards + Continue button first and
   opens this only when they want to review sources before a call. */
.research-accordion { border: 1px solid var(--card-border); border-radius: 4px; padding: var(--space-lg); }
.research-accordion > summary {
  cursor: pointer; list-style: none; font-family: var(--font-heading); font-weight: 700;
  color: var(--text-heading); font-size: 15px; letter-spacing: 0.3px;
}
.research-accordion > summary::-webkit-details-marker { display: none; }
.research-accordion > summary::before { content: "▸ "; color: var(--accent); }
.research-accordion[open] > summary::before { content: "▾ "; }

/* A selectable "radio styled as a card" field (sale type, and reusable
   anywhere else a small exclusive choice needs the same treatment) */
.choice-card {
  cursor: pointer; background: var(--card-bg); border: 2px solid var(--card-border);
  border-radius: 4px; padding: 22px; display: flex; flex-direction: column; gap: var(--space-xs);
}
/* Round 2 (site-wide visual system, Round 2) — the selected card gets
   ctaGlow reused verbatim (unmodified keyframe — see below) plus an
   inset-reading ring. The ring uses `outline`/`outline-offset`
   deliberately, not a second box-shadow: ctaGlow already animates
   `box-shadow` on this same element, and a separately-set static
   box-shadow value on that property would just be overwritten every
   animation frame, not layered with it — outline is a different
   property, so it coexists with the animation instead of fighting it. */
.choice-card:has(input:checked) {
  border-color: var(--accent);
  outline: 2px solid rgba(57, 211, 103, 0.35);
  outline-offset: -6px;
  animation: ctaGlow 1.6s ease-in-out infinite;
}
.choice-card input { display: none; }

/* Table / list rows */
table { border-collapse: collapse; width: 100%; }
th, td { text-align: left; padding: 10px 12px; font-size: 13px; }
thead th {
  font-size: 11px; letter-spacing: 0.6px; font-weight: 700; text-transform: uppercase;
  color: var(--text-muted); border-bottom: 1px solid var(--card-border); padding-bottom: var(--space-xs);
}
tbody tr { border-bottom: 1px solid var(--card-border); }
tbody tr:hover { background: rgba(57, 211, 103, 0.04); }
tbody td { color: var(--text-secondary); }

/* Empty state */
.empty-state {
  text-align: center; color: var(--text-faint); font-size: 13px; padding: var(--space-2xl) var(--space-lg);
  border: 1px dashed var(--card-border); border-radius: 4px;
}

/* Tabs — the initiative detail page (initiatives/templates/initiatives/
   detail.html): every tab's content renders server-side in one response;
   only the active panel's `hidden` attribute is omitted, initially decided
   server-side from `?tab=` (so the correct tab is already right without
   JavaScript), then toggled client-side on click without a reload — see
   static/js/app.js and docs/detail-page-restructure-design.md. */
.tabs-nav {
  display: flex; gap: 4px; margin-bottom: var(--space-lg);
  border-bottom: 1px solid var(--card-border); overflow-x: auto;
}
.tab-link {
  position: relative;
  display: inline-block; white-space: nowrap; font-family: var(--font-heading); font-weight: 700;
  font-size: 13px; letter-spacing: 0.2px; color: var(--text-muted);
  padding: var(--space-sm) var(--space-md) var(--space-sm) 26px; border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.tab-link:hover { color: var(--text-secondary); }
/* "You are here" — a filled glow-pill, always brand green regardless of
   the tab's own category dot color below (a distinct signal type: "this
   is the active tab" vs. "this tab is about X"). Replaces the old thin
   underline (border-bottom-color: var(--accent)). Round 2 correction:
   stronger tint + glow — the original 16%-alpha/0.35-opacity shadow read
   as too subtle. text-heading on this 22%-alpha tint clears AA with wide
   margin (10.50:1) — see docs/detail-page-restructure-design.md's Round 2
   correction section. */
.tab-link.active, .nav-report-link.active {
  color: var(--text-heading);
  background: rgba(57, 211, 103, 0.22);
  border-radius: 999px;
  border-bottom-color: transparent;
  box-shadow: 0 0 16px rgba(57, 211, 103, 0.55);
}
/* Round 2 — the topbar's "Reports" link (see
   docs/site-wide-visual-system-design.md's Round 2 section): reuses the
   exact rule above verbatim (same selector list, not a second copy of
   the declarations) for its active state — "any report page is open,"
   the identical "you are here" signal the detail page's tabs already
   established. No category dot here (::before above is keyed to
   .tab-link specifically) — just the glow-pill. */
.nav-report-link { padding: 4px 10px; }
/* Category dot — visible whether or not the tab is active, a different
   signal from the active-tab pill above (which stays green everywhere).
   Keyed off the existing data-tab attribute already on each tab-link, so
   no template change was needed to add it. Round 2 correction: bigger
   (8px, was 6px) plus each dot's own small glow, matching its own color —
   the plain 6px flat dots read as barely-there. Every dot color clears
   the 3:1 UI-component floor against the page background with wide
   margin — see the Round 2 contrast table. */
.tab-link::before {
  content: ""; position: absolute; left: 10px; top: 50%; transform: translateY(-50%);
  width: 8px; height: 8px; border-radius: 50%;
}
.tab-link[data-tab="overview"]::before { background: var(--accent); box-shadow: 0 0 6px 1px rgba(57, 211, 103, 0.6); }
.tab-link[data-tab="research"]::before { background: var(--info); box-shadow: 0 0 6px 1px rgba(91, 157, 255, 0.6); }
.tab-link[data-tab="communications"]::before { background: var(--warning); box-shadow: 0 0 6px 1px rgba(245, 185, 66, 0.6); }
.tab-link[data-tab="transcripts"]::before { background: var(--error); box-shadow: 0 0 6px 1px rgba(220, 89, 89, 0.6); }
.tab-link[data-tab="maturity"]::before { background: var(--insight); box-shadow: 0 0 6px 1px rgba(179, 137, 249, 0.6); }

/* "At a glance" strip (Overview tab) */
.glance-strip { display: flex; flex-wrap: wrap; gap: var(--space-md); margin-bottom: var(--space-lg); }
.glance-item {
  flex: 1 1 160px; background: var(--card-bg); border: 1px solid var(--card-border); border-radius: 4px;
  padding: var(--space-sm) var(--space-md);
}
.glance-label {
  font-size: 10px; letter-spacing: 0.6px; font-weight: 700; text-transform: uppercase;
  color: var(--text-muted); margin-bottom: 4px;
}
.glance-value { font-size: 13px; color: var(--text-secondary); }

@media (max-width: 640px) {
  .glance-item { flex-basis: 100%; }
}

/* Round 2 — Transcripts & Coaching tab's collapsible full-transcript
   viewer (initiatives/templates/initiatives/detail.html, static/js/app.js).
   The extra-turns container is toggled via `hidden`, same idiom as the
   tab panels above — always in the DOM, never removed, just visually
   collapsed. */
.transcript-viewer { position: relative; }
/* Real fix (see docs/site-wide-visual-system-design.md's "Transcript
   reader fix" section for the full root-cause writeup): the fade mask
   below only has real cut-off content to fade into the background when
   this container is actually height-clipped. It previously had no
   max-height/overflow at all, so all 5 preview turns rendered in full —
   the mask overlapped blank space below already-complete content and
   never visibly faded anything. ~260px comfortably shows several
   short turns in full and partially clips a longer one, matching the
   "roughly the first five turns" preview intent (not an exact turn-count
   guarantee — real turn length varies a lot, confirmed against the real
   Bass Electric transcript). Only applied when there's more than 5 turns
   (i.e. only when the fade/toggle is actually in play). */
.transcript-preview-clipped { max-height: 260px; overflow: hidden; }
.transcript-turn { display: flex; gap: 10px; padding: 5px 0; font-size: 13px; line-height: 1.6; color: var(--text-secondary); }
.transcript-speaker-tag {
  flex: 0 0 auto; font-size: 10px; font-weight: 700; letter-spacing: 0.5px; text-transform: uppercase;
  padding: 2px 7px; border-radius: 2px; height: fit-content;
}
.transcript-speaker-me { color: var(--accent); background: rgba(57, 211, 103, 0.12); }
.transcript-speaker-them { color: var(--info); background: rgba(91, 157, 255, 0.12); }
.transcript-turn-text { flex: 1 1 auto; }
.transcript-turns-extra[hidden] { display: none; }
.transcript-fade-mask {
  height: 36px; margin-top: -36px; position: relative;
  background: linear-gradient(to bottom, transparent, var(--card-bg));
  pointer-events: none;
}
.transcript-fade-mask[hidden] { display: none; }
/* Round 2 correction — a real button (bordered/padded/filled), not a bare
   colored link (the old .btn-ghost treatment had no visual weight at
   all). A chevron rotates via aria-expanded, set by static/js/app.js's
   toggle handler. */
.transcript-toggle-btn {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--card-bg); border: 1px solid var(--card-border); border-radius: 3px;
  padding: 8px 14px; font-size: 12px; font-weight: 700; color: var(--text-secondary);
  cursor: pointer; margin-bottom: 8px;
}
.transcript-toggle-btn:hover { border-color: var(--text-muted); color: var(--text-heading); }
.transcript-toggle-chevron { display: inline-block; transition: transform 0.2s ease; }
.transcript-toggle-btn[aria-expanded="true"] .transcript-toggle-chevron { transform: rotate(180deg); }

/* Round 2 — FollowUpSuggestion/MaturityAssessment restructure: shared
   chip-grid, stat-tile, and callout building blocks used by both tabs'
   detail.html markup, so a single small vocabulary covers both instead of
   one-off layouts per field. */
.chip-grid { display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
  background: var(--card-bg); border: 1px solid var(--card-border); border-radius: 4px;
  padding: 8px 12px; font-size: 13px; color: var(--text-secondary); line-height: 1.5;
}
.stat-tile-row { display: flex; flex-wrap: wrap; gap: var(--space-sm); }
.stat-tile {
  flex: 1 1 140px; background: var(--card-bg); border: 1px solid var(--card-border); border-radius: 4px;
  padding: var(--space-sm) var(--space-md);
}
.stat-tile-label {
  font-size: 10px; letter-spacing: 0.6px; font-weight: 700; text-transform: uppercase;
  color: var(--text-muted); margin-bottom: 4px;
}
.stat-tile-value { font-size: 14px; color: var(--text-heading); font-weight: 700; }

/* Objection/response card pairs — objection side tinted danger (reusing
   --error-bg, the same alpha Round 1 already cleared AA at), response side
   tinted brand green, so the two columns read as opposite poles at a
   glance. */
.objection-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
@media (max-width: 640px) { .objection-pair { grid-template-columns: 1fr; } }
.objection-card, .response-card {
  border-radius: 4px; padding: 10px 12px; font-size: 13px; line-height: 1.6;
}
.objection-card { background: var(--error-bg); border-left: 3px solid var(--error); color: var(--text-secondary); }
.response-card { background: rgba(57, 211, 103, 0.06); border-left: 3px solid var(--accent); color: var(--text-secondary); }
.objection-response-label {
  display: block; font-size: 10px; letter-spacing: 0.5px; font-weight: 700; text-transform: uppercase;
  margin-bottom: 4px;
}
.objection-card .objection-response-label { color: var(--error); }
.response-card .objection-response-label { color: var(--accent); }

/* Maturity gauge — a compact radial dial, the number centered inside it.
   Drawn as a conic-gradient ring (no SVG/JS needed) from --insight (the
   maturity accent) over --card-border for the unfilled remainder. Round 2
   correction: bigger + a thicker ring (12px, was 8px) + its own glow —
   the original size/thickness read as too thin against the mockup. */
.maturity-gauge {
  --gauge-pct: 0%;
  width: 88px; height: 88px;
  background: conic-gradient(var(--insight) var(--gauge-pct), var(--card-border) 0);
  display: flex; align-items: center; justify-content: center; flex: 0 0 auto;
  box-shadow: 0 0 14px rgba(179, 137, 249, 0.35);
}
.maturity-gauge-inner {
  width: 64px; height: 64px; border-radius: 50%; background: var(--card-bg);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-heading); font-weight: 700; font-size: 20px; color: var(--text-heading);
}
/* Round 2 correction: stronger tint (0.16, was 0.10) + thicker accent
   border (4px, was 3px) — the original read as a thin outline, not a
   tinted callout card. text-primary on the new tint still clears AA with
   wide margin (12.35:1) — see the Round 2 correction section. */
.maturity-callout {
  background: rgba(179, 137, 249, 0.16); border-left: 4px solid var(--insight);
  border-radius: 4px; padding: 12px 14px; font-size: 13px; color: var(--text-primary); line-height: 1.6;
}
.maturity-callout-label {
  display: block; font-family: var(--font-heading); font-size: 10px; font-weight: 700;
  letter-spacing: 0.6px; text-transform: uppercase; color: var(--insight); margin-bottom: 4px;
}

/* Round 2 pulse/glow keyframes — exactly three usages app-wide:
   .dot-circle-track.active (current stage on the race track),
   .badge-pulse (a risk_of_stalling: high badge specifically), and
   .btn-primary:hover/:focus-visible (the primary CTA). All three drop to a
   static (still-visible, just motionless) equivalent under
   prefers-reduced-motion, never to nothing. Round 2 correction: all three
   made stronger (bigger blur/spread, an actual box-shadow glow on the
   lap-track dot instead of a scale-only transform) — the originals read
   as too subtle to register as "glow" at all. */
@keyframes currentPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(57, 211, 103, 0.55); }
  50% { box-shadow: 0 0 0 6px rgba(57, 211, 103, 0), 0 0 18px 4px rgba(57, 211, 103, 0.85); }
}
@keyframes pulseGlow {
  0%, 100% { box-shadow: 0 0 4px 1px rgba(220, 89, 89, 0.6); }
  50% { box-shadow: 0 0 14px 4px rgba(220, 89, 89, 0.9); }
}
@keyframes ctaGlow {
  0%, 100% { box-shadow: 0 0 6px rgba(57, 211, 103, 0.45); }
  50% { box-shadow: 0 0 20px rgba(57, 211, 103, 0.85); }
}
@media (prefers-reduced-motion: reduce) {
  .dot-circle-track.active, .badge-pulse, .btn-primary:hover, .btn-primary:focus-visible,
  .dot-circle-flow.active, .choice-card:has(input:checked) {
    animation: none;
  }
  .dot-circle-track.active { box-shadow: 0 0 10px 3px rgba(57, 211, 103, 0.7); }
  .badge-pulse { box-shadow: 0 0 8px 2px rgba(220, 89, 89, 0.7); }
  .btn-primary:hover, .btn-primary:focus-visible { box-shadow: 0 0 14px rgba(57, 211, 103, 0.7); }
  /* Same discipline as the other two: still visible (the ring/outline is
     a separate property, unaffected either way), just motionless. */
  .dot-circle-flow.active { box-shadow: 0 0 10px 3px rgba(57, 211, 103, 0.7); }
  .choice-card:has(input:checked) { box-shadow: 0 0 10px rgba(57, 211, 103, 0.5); }
}

/* Reports hub (site-wide visual system, Round 2) — see
   docs/site-wide-visual-system-design.md's Round 2 section. */

/* A solid-fill access-level pill — same recipe as .badge.b-green/.b-violet
   (dark --bg text on a solid token fill) but a deliberately separate
   component, not a new .badge.b-* suffix: "who can open this" is a
   different kind of label from "what status is this row" that .badge.b-*
   already covers everywhere else. */
.access {
  font-size: 10px; letter-spacing: 0.5px; font-weight: 700; padding: 3px 8px;
  border-radius: 2px; display: inline-block; white-space: nowrap;
}
.access.everyone { color: var(--bg); background: var(--accent); }
.access.vp { color: var(--bg); background: var(--insight); }

/* A small colored status dot next to a report's live status line — same
   plain-circle shape as .dot-logged-dot, three real states instead of one. */
.status-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; }
.status-dot.ready { background: var(--accent); }
.status-dot.gated { background: var(--warning); }
.status-dot.empty { background: var(--text-faint); }

.reports-hub-grid {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-lg);
}
@media (max-width: 760px) {
  .reports-hub-grid { grid-template-columns: 1fr; }
}
.report-card {
  background: var(--card-bg); border: 1px solid var(--card-border); border-top: 3px solid var(--card-border);
  border-radius: 4px; padding: var(--space-lg); display: flex; flex-direction: column; gap: var(--space-sm);
}
.report-card.accent-amber { border-top-color: var(--warning); }
.report-card.accent-blue { border-top-color: var(--info); }
.report-card.accent-green { border-top-color: var(--accent); }
.report-card.accent-violet { border-top-color: var(--insight); }
.report-card-title { font-family: var(--font-heading); font-weight: 700; color: var(--text-heading); font-size: 17px; }
.report-card-description { font-size: 13px; color: var(--text-secondary); line-height: 1.6; flex: 1; }
.report-card-status { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--text-faint); }
