/* ── Font demo (Space Grotesk headings / JetBrains Mono numerals) ──
   To back out: delete this block, delete the two font-family rules
   below that reference these variables (search "--font-heading" and
   "--font-mono"), and revert the Google Fonts <link> in index.html/
   detail.html back to just Inter. Nothing else depends on this. */
:root {
  --font-heading: 'Space Grotesk', 'Inter', Arial, sans-serif;
  --font-mono:    'JetBrains Mono', 'Inter', monospace;
}

/* Wraps every dynamically-inserted numeric value across both pages
   (app.js/detail.js) — search ".num" in either file to find them all. */
.num { font-family: var(--font-mono); }

/* ── shadcn/ui token retrofit ──
   Phase 1 (this block): adopt shadcn's semantic vocabulary — background/
   foreground/card/primary/secondary/muted/accent/destructive/border/
   input/ring/radius, plus its --chart-1..5 convention for categorical
   data colors — mapped onto the colors this project already settled on
   through iteration, not shadcn's stock slate palette. Purely additive:
   every existing variable below (--bg, --accent-deep, --radius-lg, etc.)
   is untouched and still drives 100% of the current CSS, so this can't
   cause a visual regression. New components should be built against
   these tokens directly; migrating existing rules to consume them
   (instead of the legacy names) would be a natural phase 2.

   Two of our existing tokens don't map 1:1 onto a shadcn slot and were
   deliberately left alone rather than force-fit: --accent (a saturated
   brand blue-grey used for active/focus states — closest to --ring,
   not --accent, which in shadcn means a subtle hover background) and
   --accent-deep (our emphasis-text color, distinct from --primary,
   which corresponds to the solid dark CTA button background/text
   instead). Tier colors (green/amber/rose) and the per-source palette
   also stay as their own extension, same as shadcn's own docs do for
   product-specific colors beyond the core set. */
:root {
  /* Aliased via var() (not duplicated hex) since the consolidation pass —
     these can't go stale the way the old hardcoded copies did. */
  --background:         var(--bg);
  --foreground:         var(--text-primary);
  --card:                var(--surface);
  --card-foreground:    var(--text-primary);
  --popover:             var(--surface);
  --popover-foreground: var(--text-primary);
  --primary:             var(--text-primary); /* the solid dark CTA button */
  --primary-foreground: #ffffff;
  --secondary:           var(--bg); /* no separate surface-alt anymore */
  --secondary-foreground: var(--text-primary);
  --muted:               var(--accent-tint);
  --muted-foreground:   var(--text-secondary);
  /* No separate --accent slot: shadcn's "accent" (a subtle hover bg) would
     be the same value as --muted above, and this project already has an
     unrelated --accent (brand blue-grey, #607d8b) declared below — reusing
     the name here would silently shadow one or the other depending on
     source order. --muted covers shadcn's accent role instead. */
  --accent-foreground:  var(--accent-deep);
  --destructive:         var(--rose-deep);
  --destructive-foreground: #ffffff;
  --border:              var(--border);
  --input:               var(--border-input);
  --ring:                var(--accent); /* used for focus rings below */
  --radius:              0.625rem; /* = --radius-lg (10px) — sm/md/lg/xl below derive from this */

  /* shadcn chart-color convention — same hues as our per-source tokens.
     Aliased via var() so this can't go stale the way the hardcoded
     copies here previously did after a source color changed. */
  --chart-1: var(--news-color);
  --chart-2: var(--reddit-red);
  --chart-3: var(--linkedin-blue);
  --chart-4: var(--github-color);
  --chart-5: var(--hn-color);
  --chart-6: var(--exec-hire-color);
  --chart-7: var(--funding-color);
}

/* Real accessibility win from adopting --ring, not just a decorative
   token: a visible focus indicator for keyboard navigation. */
:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
}

/* ── Design tokens ──
   Consolidated 2026-07-16: everything below derives from 10 core colors
   (bg / surface / border / text-primary / text-secondary / accent /
   accent-deep / green / amber / rose). Every "-deep" is that color mixed
   ~30% toward black; every "-tint" is mixed ~85% toward white — not an
   independently hand-picked hex. Dropped as redundant near-duplicates in
   this pass: --surface-alt, --row-bg, --control-bg, --accent-light,
   --text-muted, and the separate --gauge-accent* hue (folded into
   --accent). The 7 --news-color..--funding-color source colors are the
   deliberate exception — a categorical data-viz palette where 7-way
   distinguishability is the actual requirement, so they keep their own
   hues rather than deriving from the core 10. */
:root {
  --bg:              #eff3f6;
  --surface:         #fdfeff;
  --border:          #d3dee4;
  --border-input:    var(--border);
  --border-emphasis: #bbc5d0; /* border a step darker for hover/selected rows -- lighter than --text-secondary */

  --text-primary:    #0d1219;
  --text-secondary:  #838ba0;

  --accent:          #607d8b;
  --accent-deep:     #455a64;
  --accent-tint:     #e7ecee;
  --callout-tint:    var(--bg);

  /* ── Hue ramp: 7 core hues, each with dark / base(100%) / tint-1 / tint-2,
     derived via one consistent formula — dark = hue mixed 30% toward
     black; tint-1 = hue mixed 50% toward white; tint-2 = hue mixed 85%
     toward white — not independently hand-picked per hue. Every semantic
     name below (--green, --news-color, etc.) just aliases whichever
     shade of whichever hue that role needs; every rule elsewhere in this
     file that consumes those semantic names is unchanged. */
  --hue-red:           #bf635e;
  --hue-red-dark:      #864542;
  --hue-red-tint-1:    #dfb1af;
  --hue-red-tint-2:    #f5e8e7;

  --hue-green:         #5e864d;
  --hue-green-dark:    #425e36;
  --hue-green-tint-1:  #afc3a6;
  --hue-green-tint-2:  #e7ede4;

  --hue-blue:          #4c6c91;
  --hue-blue-dark:     #354c66;
  --hue-blue-tint-1:   #a6b6c8;
  --hue-blue-tint-2:   #e4e9ef;

  --hue-purple:        #955d94;
  --hue-purple-dark:   #684168;
  --hue-purple-tint-1: #caaeca;
  --hue-purple-tint-2: #efe7ef;

  --hue-orange:        #dd914a;
  --hue-orange-dark:   #9b6634;
  --hue-orange-tint-1: #eec8a5;
  --hue-orange-tint-2: #faefe4;

  --hue-yellow:        #e1d270;
  --hue-yellow-dark:   #9e934e;
  --hue-yellow-tint-1: #f0e9b8;
  --hue-yellow-tint-2: #fbf8ea;

  --hue-teal:          #267069;
  --hue-teal-dark:     #1b4e4a;
  --hue-teal-tint-1:   #93b8b4;
  --hue-teal-tint-2:   #deeae9;

  /* 8th hue, added when the pipeline added patents as a source — all 7
     original hues (red/green/blue/purple/orange/yellow/teal) were
     already spoken for. First attempt was an indigo (blue-violet, ~235°)
     which sat too close to blue(~212°) and purple(~301°) to actually
     read as distinct; pink(~338°) sits in the real gap between them. */
  --hue-pink:        #c46e8e;
  --hue-pink-dark:   #894d63;
  --hue-pink-tint-1: #e2b7c7;
  --hue-pink-tint-2: #f6e9ee;

  /* Tier status colors — reuse the same hues as the source palette below
     (rose=red, green=green, amber=orange) instead of maintaining 3 more
     standalone shades. */
  --green:           var(--hue-green);
  --green-deep:      var(--hue-green-dark);
  --green-tint:      var(--hue-green-tint-2);

  --amber:           var(--hue-orange);
  --amber-deep:      var(--hue-orange-dark);
  --amber-tint:      var(--hue-orange-tint-2);

  --rose:            var(--hue-red);
  --rose-deep:       var(--hue-red-dark);
  --rose-tint:       var(--hue-red-tint-2);

  --news-color:      var(--hue-red);
  --linkedin-blue:   var(--hue-blue);
  --reddit-red:      var(--hue-green);
  --github-color:    var(--hue-purple);
  --hn-color:        var(--hue-orange);
  --exec-hire-color: var(--hue-teal);
  --funding-color:   var(--hue-yellow);
  --patents-color:   var(--hue-pink);
  --trend-accent:    var(--green);
  --peer-muted-dot:  var(--text-secondary);

  --radius-sm:   6px;
  --radius-md:   8px;
  --radius-lg:   10px;
  --radius-xl:   12px;
  --radius-full: 9999px;

  /* Type scale: 12 near-duplicate sizes (8-28px) consolidated to 6.
     Every font-size declaration in this file references one of these —
     no more independently-picked pixel values. */
  --text-2xs: 10px;
  --text-sm:  12px;
  --text-md:  16px;
  --text-lg:  22px;
  --text-xl:  28px;

  --shadow-xs:  0 1px 2px 0 rgba(0, 0, 0, 0.1);
  --shadow-btn: 0 1px 1px 0 rgba(0, 0, 0, 0.1);

  --header-h:     128px;
}

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

body {
  margin: 0;
  font-family: 'Inter', Arial, sans-serif;
  background: var(--bg);
  color: var(--text-primary);
  font-size: var(--text-md);
  -webkit-font-smoothing: antialiased;
}

.dashboard {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

/* ─────────────────────────────────────────
   Header
───────────────────────────────────────── */
.dashboard-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  height: var(--header-h);
  padding: 16px 32px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}

.header-titles {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.header-eyebrow {
  font-size: var(--text-sm);
  line-height: 16px;
  font-weight: 700;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--accent-deep);
}

.header-title {
  margin: 6px 0 0;
  font-size: var(--text-xl);
  line-height: 34px;
  font-weight: 700;
  color: var(--text-primary);
}

/* Font demo — see the --font-heading/--font-mono block near the top of
   this file for how to back this out. */
.header-title,
.company-row-name,
.inspector-company-name,
.detail-company-name {
  font-family: var(--font-heading);
}

.header-subtitle {
  margin: 4px 0 0;
  font-size: var(--text-sm);
  font-weight: 400;
  color: var(--text-secondary);
  line-height: 18px;
  white-space: nowrap;
}

.header-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}

/* ─────────────────────────────────────────
   Buttons
───────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 32px;
  padding: 6px 14px;
  border: none;
  border-radius: var(--radius-lg);
  font-family: inherit;
  font-size: var(--text-sm);
  font-weight: 600;
  line-height: 20px;
  cursor: pointer;
  text-decoration: none;
  box-sizing: border-box;
}

.btn-outline {
  background: var(--surface);
  color: var(--text-secondary);
  border: 1px solid var(--border);
}

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

/* The one exception to the site-wide neutral button treatment — the
   primary CTA on Suggested Contact stays a solid, filled button so it
   still reads as "the" action on the card. Was solid near-black
   (--text-primary); softened to --accent once the rest of the app's
   palette got muted this session — pure black read as disproportionately
   loud once everything around it got quieter. */
.btn-dark {
  background: var(--accent);
  color: #ffffff;
}

.btn-full { width: 100%; }

/* ─────────────────────────────────────────
   Filter bar
───────────────────────────────────────── */
.filter-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 32px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}

.filter-search-wrap {
  position: relative;
  flex: 1 0 0;
  min-width: 0;
  max-width: 360px;
}

.filter-search {
  width: 100%;
  height: 32px;
  border: 1px solid var(--border-input);
  border-radius: var(--radius-md);
  background: var(--surface);
  box-shadow: var(--shadow-xs);
  padding: 0 12px 0 34px;
  font-family: inherit;
  font-size: var(--text-sm);
  color: var(--text-primary);
}

.filter-search::placeholder { color: var(--text-secondary); }

.filter-search-icon {
  position: absolute;
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-secondary);
  pointer-events: none;
}

.pill-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 32px;
  padding: 0 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  font-family: inherit;
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--text-secondary);
  cursor: pointer;
  flex-shrink: 0;
}

.pill-btn svg { flex-shrink: 0; transition: transform 0.15s; }
.pill-btn.sort-asc svg { transform: rotate(180deg); }

.pill-btn[aria-pressed="true"] {
  background: var(--accent-tint);
  border-color: var(--border);
  color: var(--accent-deep);
}

.pill-btn-clear {
  background: var(--accent-tint);
}

/* ─────────────────────────────────────────
   Body: 3-column layout
───────────────────────────────────────── */
.dashboard-body {
  position: relative;
  display: grid;
  grid-template-columns: 350px 1fr 350px;
  gap: 28px;
  align-items: start;
  flex: 1 0 auto;
  padding: 24px 32px 48px;
  min-height: 300px;
}

.loading-overlay {
  position: absolute;
  inset: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg);
}

.loading-overlay p {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--text-secondary);
}

.loading-overlay[hidden] { display: none; }

.fallback-banner {
  padding: 10px 32px;
  background: var(--amber-tint);
  color: var(--amber-deep);
  font-size: var(--text-sm);
  font-weight: 600;
  border-bottom: 1px solid var(--border);
}

.fallback-banner[hidden] { display: none; }

.card-eyebrow {
  padding-left: 3px;
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  color: var(--accent-deep);
}


.divider {
  margin: 12px 0;
  border: none;
  border-top: 1px solid var(--border);
}

/* Flex items don't collapse margins — without this, a divider's own
   margin-bottom stacks with the label's margin-top instead of merging,
   leaving an oversized gap. */
.divider + .section-label { margin-top: 8px; }

.section-label {
  margin: 18px 0 10px;
  padding-left: 3px;
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  color: var(--accent-deep);
}

.fine-print {
  margin: 8px 0 0;
  font-size: var(--text-sm);
  font-weight: 400;
  color: var(--text-secondary);
  line-height: 1.4;
}

/* Verified vs. unverified captions differ a lot in length (one line vs.
   three). Deliberately not reserving height for the longer message here
   - a fixed-height reservation just left dead space under the shorter
   one. Letting the card size naturally to its own content and shift
   the layout below it is the more graceful failure mode. */

.tier-badge {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: var(--radius-full);
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: 0.4px;
  background: var(--accent-tint);
  color: var(--accent-deep);
}

.tier-badge.tier-green { background: var(--green-tint); color: var(--green-deep); }
.tier-badge.tier-amber { background: var(--amber-tint); color: var(--amber-deep); }
.tier-badge.tier-rose  { background: var(--rose-tint);  color: var(--rose-deep); }

.discovery-badge {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: var(--radius-full);
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: 0.4px;
  /* Reuses the purple hue ramp (same one github uses) instead of a
     separate standalone purple -- keeps the "New Discovery" badge its
     original light-purple identity without reintroducing a whole new
     color for it. */
  background: var(--hue-purple-tint-2);
  color: var(--hue-purple-dark);
}

.discovery-badge[hidden] { display: none; }

/* Same funding/exec-hire-vs-LinkedIn criteria as the Job Value
   Quadrant's bottom-right cell — teal because that's exec_hire's own
   hue, one of the two signals driving this flag. */
.stealth-badge {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: var(--radius-full);
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: 0.4px;
  background: var(--hue-teal-tint-2);
  color: var(--hue-teal-dark);
}

.callout-box {
  margin-top: 16px;
  padding: 14px 16px;
  border-radius: var(--radius-lg);
  background: var(--callout-tint);
  border: 1px solid var(--border);
}

.callout-label {
  display: block;
  font-size: var(--text-2xs);
  font-weight: 700;
  color: var(--accent-deep);
  margin-bottom: 5px;
}

.callout-text {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--text-secondary);
  line-height: 1.6;
}

/* ─────────────────────────────────────────
   Radar column
───────────────────────────────────────── */
.quadrant-column {
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 24px;
  max-height: calc(100vh - 48px);
  overflow-y: auto;
  /* Reserves the scrollbar's gutter whether or not it's actually needed,
     so content taller than the viewport toggling the scrollbar on/off
     between renders can't shrink/grow this column's available width -
     which would otherwise resize the quadrant chart (aspect-ratio: 1/1
     scales with container width) every time it happened. */
  scrollbar-gutter: stable;
}

.quadrant-scope {
  aspect-ratio: 1 / 1;
  width: 100%;
  flex-shrink: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  overflow: hidden;
}

.chart-toggle-row {
  display: flex;
  gap: 8px;
  margin-bottom: 12px;
}

.chart-toggle-btn {
  flex: 1;
  justify-content: center;
}

/* No aspect-ratio — this is a list of N companies, not a square chart,
   so it gets its own internal scroll instead of dictating the column's
   height (a leaderboard tall enough for 40 companies would otherwise
   push Job Opportunity Signals far down the page). */
.leaderboard-scope {
  width: 100%;
  max-height: 300px;
  overflow-y: auto;
  flex-shrink: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: 14px 16px 8px;
}

.leaderboard-scope[hidden] { display: none; }
.quadrant-scope[hidden] { display: none; }

.quadrant-caption {
  margin: 16px 0 0;
  font-size: var(--text-sm);
  font-weight: 400;
  color: var(--text-secondary);
  line-height: 1.5;
}


.job-signals-card,
.inspector-card,
.contact-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: 20px;
  /* These are direct children of the sticky columns (.quadrant-column /
     .right-rail), which cap their own height and scroll rather than
     grow past the viewport. Without flex-shrink:0, default flex
     behavior lets a card get squeezed below its natural content height
     when a sibling's variable-length text (an unverified caption, a
     "why it matters" blurb) pushes the column over that cap - which is
     what caused the Momentum Trend chart to render squished into a
     shorter box than its own coordinate math assumed. Now any real
     overflow goes to the column's existing scroll instead. */
  flex-shrink: 0;
}

.stat-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 0;
}

.stat-label {
  font-size: var(--text-sm);
  color: var(--text-secondary);
}

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

.gauge-row {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 8px 0 4px;
}

.gauge-visual {
  position: relative;
  width: 72px;
  height: 72px;
  flex-shrink: 0;
}

.gauge-visual svg {
  transform: rotate(-90deg);
}

.gauge-center-value {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-md);
  font-weight: 700;
  color: var(--text-primary);
}

.gauge-info {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
}

.gauge-info .stat-label {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-primary);
}

.gauge-momentum-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.gauge-momentum-row .stat-label {
  font-size: var(--text-sm);
  color: var(--text-secondary);
}

/* ─────────────────────────────────────────
   Ranked list (middle column)
───────────────────────────────────────── */
.list-column {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
}

.list-heading {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.list-count {
  font-size: var(--text-sm);
  color: var(--text-secondary);
}

.list-hint {
  margin: 4px 0 12px;
  font-size: var(--text-sm);
  font-weight: 400;
  color: var(--text-secondary);
}

.tier-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 8px;
}

.tier-group-header {
  display: flex;
  align-items: center;
  gap: 6px;
}

.tier-group-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
}

.tier-group-dot.green { background: var(--green); }
.tier-group-dot.amber { background: var(--amber); }
.tier-group-dot.rose  { background: var(--rose); }

.tier-group-label {
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: 1px;
  color: var(--accent-deep);
}

.tier-group-label.green { color: var(--green-deep); }
.tier-group-label.amber { color: var(--amber-deep); }
.tier-group-label.rose  { color: var(--rose-deep); }

.company-row {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 14px 18px;
  cursor: pointer;
  transition: border-color 0.12s, background 0.12s;
}

.company-row:hover {
  background: var(--surface);
  border-color: var(--border-emphasis);
}

.company-row.selected {
  background: var(--surface);
  border-color: var(--border-emphasis);
}

.company-row-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.company-row-name-group {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.company-row-name {
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--text-primary);
  text-decoration: none;
}

.company-row-name:hover {
  color: var(--accent-deep);
  text-decoration: underline;
}

.company-row-right {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
}

/* Font demo — see the --font-heading/--font-mono block near the top of
   this file for how to back this out. */
.company-row-index,
.inspector-index,
.detail-index,
.gauge-center-value {
  font-family: var(--font-mono);
}

.company-row-index {
  font-size: var(--text-md);
  font-weight: 700;
  color: var(--accent);
}

.company-row-index.amber { color: var(--amber); }
.company-row-index.rose  { color: var(--rose); }

.momentum-delta {
  font-size: var(--text-sm);
  font-weight: 600;
  white-space: nowrap;
  opacity: 0.5;
}

.momentum-delta.momentum-up   { color: var(--green); }
.momentum-delta.momentum-down { color: var(--rose-deep); }
.momentum-delta.momentum-flat { color: var(--text-secondary); }

.company-row-blurb {
  margin: 6px 0 0;
  font-size: var(--text-sm);
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Progressive disclosure: the per-source breakdown stays collapsed
   until you hover a row, so the list stays calm at rest but the "where
   does this number come from" detail is one hover away instead of
   locked behind a click into Company Inspector. */
.company-row-detail {
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  transition: grid-template-rows 0.3s ease, opacity 0.22s ease;
}

.company-row.expanded .company-row-detail {
  grid-template-rows: 1fr;
  opacity: 1;
}

.company-row-detail-inner {
  overflow: hidden;
  min-height: 0;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px 14px;
  padding-top: 0;
  transition: padding-top 0.3s ease;
}

.company-row.expanded .company-row-detail-inner {
  padding-top: 12px;
}

.row-detail-item {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.row-detail-meter {
  margin-top: 2px;
}

.row-detail-label {
  font-size: var(--text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Deliberately no per-source color override here (unlike source-pill/
   meter-fill/math-label elsewhere) — each label already sits directly
   next to its own value with no legend or bar segment to decode, so
   coloring the text added no information, just noise. Color stays
   reserved for spots where it's actually functional: the dots, bars,
   and the "At cap" badge. */

.row-detail-cap-flag {
  display: inline-block;
  margin-left: 5px;
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: 0.3px;
  text-transform: uppercase;
  color: var(--amber-deep);
  background: var(--amber-tint);
  padding: 1px 5px;
  border-radius: var(--radius-full);
  vertical-align: middle;
}

.row-detail-value {
  font-size: var(--text-sm);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.row-detail-cap {
  font-weight: 400;
  color: var(--text-secondary);
}

.row-detail-contrib {
  font-size: var(--text-sm);
  font-weight: 400;
  color: var(--text-secondary);
}

/* The arrow glyph renders a couple pixels low relative to the digits next
   to it in this font — nudge it up so it optically aligns with the text. */
.row-detail-contrib::before { content: '→ '; position: relative; top: -1px; }

.source-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: var(--text-sm);
  color: var(--text-secondary);
}

.source-pill::before {
  content: '';
  width: 6px;
  height: 6px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--accent);
  opacity: 0.9;
}

.source-pill.source-news::before      { background: var(--news-color); }
.source-pill.source-reddit::before   { background: var(--reddit-red); }
.source-pill.source-linkedin::before { background: var(--linkedin-blue); }
.source-pill.source-github::before   { background: var(--github-color); }
.source-pill.source-hn::before       { background: var(--hn-color); }
.source-pill.source-exec_hire::before { background: var(--exec-hire-color); }
.source-pill.source-funding::before  { background: var(--funding-color); }
.source-pill.source-patents::before  { background: var(--patents-color); }

.meter-track {
  height: 5px;
  border-radius: var(--radius-sm);
  background: transparent;
  overflow: hidden;
}

.meter-fill {
  height: 100%;
  border-radius: var(--radius-sm);
  background: var(--accent-deep);
}

.meter-fill.source-news     { background: var(--news-color); opacity: 0.9; }
.meter-fill.source-reddit   { background: var(--reddit-red); opacity: 0.9; }
.meter-fill.source-linkedin { background: var(--linkedin-blue); opacity: 0.9; }
.meter-fill.source-github   { background: var(--github-color); opacity: 0.9; }
.meter-fill.source-hn       { background: var(--hn-color); opacity: 0.9; }
.meter-fill.source-exec_hire { background: var(--exec-hire-color); opacity: 0.9; }
.meter-fill.source-funding   { background: var(--funding-color); opacity: 0.9; }
.meter-fill.source-patents   { background: var(--patents-color); opacity: 0.9; }

.table-empty {
  margin: 0;
  padding: 32px 16px;
  text-align: center;
  font-size: var(--text-sm);
  color: var(--text-secondary);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}

/* ─────────────────────────────────────────
   Right rail
───────────────────────────────────────── */
.right-rail {
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 24px;
  max-height: calc(100vh - 48px);
  overflow-y: auto;
  scrollbar-gutter: stable;
}

.inspector-title-row {
  margin-top: 14px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.inspector-company-name {
  margin: 0;
  font-size: var(--text-lg);
  font-weight: 700;
  color: var(--text-primary);
}

.inspector-badge-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 10px;
}

/* Plain link, not a badge/pill — this is a reference, not a status flag
   like the tier/discovery badges above it. Own line, not inline with
   the pills, so it doesn't read as a third badge. Reserves its line
   height always (visibility, not display:none) so the Momentum Trend
   section below doesn't shift up/down depending on whether this
   particular company has a URL. */
.inspector-website-link {
  display: block;
  min-height: 1.4em;
  margin-top: 8px;
  margin-left: 3px;
  font-size: var(--text-sm);
  color: var(--text-secondary);
  text-decoration: none;
}

.inspector-website-link:hover { color: var(--hue-blue); }

.inspector-index {
  font-size: var(--text-lg);
  font-weight: 700;
  color: var(--accent);
}

.mini-breakdown {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-bottom: 6px;
}

.mini-breakdown-row {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.mini-breakdown-contrib {
  display: block;
}

.mini-breakdown-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: var(--text-sm);
  line-height: 16px;
}

.mini-breakdown-top .label { color: var(--text-secondary); }
.mini-breakdown-top .value { color: var(--text-primary); font-weight: 700; font-family: var(--font-mono); }

.math-panel {
  margin-top: 16px;
  padding: 16px;
  border-radius: var(--radius-lg);
  background: var(--surface);
  border: 1px solid var(--border);
  flex-shrink: 0;
}

.math-caption {
  margin: 2px 0 10px;
  font-size: var(--text-sm);
  font-weight: 400;
  color: var(--text-secondary);
  line-height: 1.5;
}

.math-group-label {
  display: block;
  margin: 10px 0 4px;
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: var(--text-secondary);
}

.math-group-label:first-child { margin-top: 0; }

.math-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 5px 0;
  font-size: var(--text-sm);
}

.math-row .math-label { color: var(--text-primary); font-weight: 500; }
.math-row .math-detail { color: var(--text-secondary); }

.math-label::before {
  content: '';
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  margin-right: 6px;
  background: var(--accent-deep);
  opacity: 0.9;
}

.math-label.source-news::before      { background: var(--news-color); }
.math-label.source-reddit::before   { background: var(--reddit-red); }
.math-label.source-linkedin::before { background: var(--linkedin-blue); }
.math-label.source-github::before   { background: var(--github-color); }
.math-label.source-hn::before       { background: var(--hn-color); }
.math-label.source-exec_hire::before { background: var(--exec-hire-color); }
.math-label.source-funding::before   { background: var(--funding-color); }
.math-label.source-patents::before   { background: var(--patents-color); }

.math-total-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 10px;
}

.math-total-label {
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--text-primary);
}

.math-total-value {
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--accent-deep);
  font-family: var(--font-mono);
}

.inspector-card .btn-dark { margin-top: 16px; }

/* Suggested Contact */
/* flex-start, not center — the avatar must stay flush to this row's own
   top edge always. Nothing precedes the row itself (the Unverified
   badge lives inside .contact-person-info, not above the row), so the
   row's top position is constant regardless of badge presence, and the
   avatar lands next to whichever text is first: the badge when present,
   the name when it isn't. */
/* Suggested Contact is a list now, not a single fixed card — the
   search routinely returns several candidate people per company, and a
   meaningful fraction are surname coincidences, so the UI shows the
   list and lets a human compare/pick instead of the app silently
   guessing one. Also means reaching out to more than one person is
   just as easy as one. */
.contact-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.contact-list-item { border-radius: var(--radius-md); overflow: hidden; }

/* The whole row is the click target, not just the LinkedIn glyph. */
.contact-list-link {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 8px;
  background: var(--accent-tint);
  text-decoration: none;
  color: inherit;
}

.contact-list-link:hover { background: color-mix(in srgb, var(--accent-tint), var(--border-emphasis) 50%); }

.contact-list-avatar {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--accent);
  color: #ffffff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  font-weight: 700;
  flex-shrink: 0;
}

.contact-list-info {
  flex: 1;
  min-width: 0;
}

.contact-list-name {
  margin: 0;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--text-primary);
}

.contact-list-title {
  margin: 2px 0 0;
  font-size: var(--text-2xs);
  font-weight: 400;
  color: var(--text-secondary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.contact-list-linkedin {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  margin-top: 3px;
}

/* Amber, not neutral — this is a "check this before you act on it" flag,
   not decoration. Hiding unverified contacts entirely would make the
   feature useless (most of what's found this way is still directionally
   right), but presenting it with the same confidence as a verified
   contact would be dishonest. Inline with the name now (list items are
   compact, no room for its own line). */
.contact-unverified-badge {
  display: inline-flex;
  align-items: center;
  padding: 1px 6px;
  border-radius: var(--radius-full);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.3px;
  text-transform: uppercase;
  background: var(--amber-tint);
  color: var(--amber-deep);
}

.contact-empty-state {
  margin: 0;
  padding: 24px 16px;
  text-align: center;
  font-size: var(--text-sm);
  color: var(--text-secondary);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  flex-shrink: 0;
}

.contact-empty-state p { margin: 0; }
.contact-empty-state .btn { margin-top: 14px; }
.contact-empty-state .fine-print { margin-top: 8px; }
.contact-empty-state[hidden] { display: none; }

/* ─────────────────────────────────────────
   Detail page (3-column, matching main dashboard)
───────────────────────────────────────── */
.detail-page {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.detail-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  height: var(--header-h);
  padding: 16px 32px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}

.detail-topbar-left {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
  min-width: 0;
}

.detail-topbar-nav {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}

.back-link {
  display: inline-block;
  font-size: var(--text-sm);
  line-height: 16px;
  font-weight: 400;
  color: var(--text-secondary);
  text-decoration: none;
}

.back-link:hover { color: var(--text-primary); }

.back-link-arrow {
  display: inline-block;
  position: relative;
  top: -1px;
}

.detail-header {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 6px;
}

.detail-company-name {
  margin: 0;
  font-size: var(--text-xl);
  line-height: 34px;
  font-weight: 700;
  color: var(--text-primary);
}

.detail-index {
  font-size: var(--text-xl);
  line-height: 34px;
  font-weight: 700;
  color: var(--accent);
}

.detail-blurb {
  margin: 4px 0 0;
  font-size: var(--text-sm);
  line-height: 18px;
  color: var(--text-secondary);
}

.detail-body {
  padding: 24px 32px 48px;
  position: relative;
  min-height: 400px;
}

.detail-columns {
  display: grid;
  grid-template-columns: 350px 1fr 350px;
  gap: 30px;
  align-items: start;
}

.detail-col {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.breakdown-compact-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: 16px;
}

.signal-radar-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: 16px;
}

.radar-compare-row {
  display: flex;
  gap: 8px;
  margin-bottom: 12px;
}

.radar-compare-select {
  flex: 1;
  min-width: 0;
  height: 30px;
  border: 1px solid var(--border-input);
  border-radius: var(--radius-md);
  background: var(--surface);
  padding: 0 8px;
  font-family: inherit;
  font-size: var(--text-2xs);
  color: var(--text-secondary);
}

.radar-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 10px;
}

.radar-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: var(--text-2xs);
  font-weight: 600;
  color: var(--text-secondary);
}

.radar-legend-swatch {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}

.trend-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: 20px;
}

.peer-compare-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: 20px;
}

.peer-compare-headline {
  margin: 0;
  font-size: var(--text-md);
  font-weight: 700;
  color: var(--text-primary);
}

.peer-compare-sub {
  margin: 4px 0 14px;
  font-size: var(--text-sm);
  font-weight: 400;
  color: var(--text-secondary);
}

.source-rank-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: 20px;
}

.source-rank-headline {
  margin: 0 0 12px;
  font-size: var(--text-sm);
  font-weight: 400;
  color: var(--text-secondary);
}

.source-rank-headline strong { color: var(--text-primary); }

.source-rank-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 0;
}

.source-rank-row + .source-rank-row { border-top: 1px solid var(--border); }

.source-rank-row-label {
  width: 112px;
  flex-shrink: 0;
  white-space: nowrap;
}

.source-rank-row-pct {
  width: 118px;
  flex-shrink: 0;
  font-size: var(--text-sm);
  color: var(--text-secondary);
  text-align: right;
}

/* Same tier-color vocabulary as the overall tier badge — a quick
   scanner should spot a weak source as fast as a strong one. */
.source-rank-row-pct-weak { color: var(--rose-deep); font-weight: 600; }
.source-rank-row-pct-strong { color: var(--green-deep); font-weight: 600; }

.source-rank-row-strip {
  flex: 1 0 0;
  min-width: 0;
}

.callout-box-standalone { margin-top: 0; }
.math-panel-standalone { margin-top: 0; }

.inspector-trend-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: 20px;
}

.inspector-trend-card #inspector-trend-svg {
  display: block;
  width: 100%;
  height: 80px;
}

/* Both possible captions ("Real signal history across N scans." and
   "Not enough scan history yet.") are short enough to stay on one line,
   so no height reservation is needed here — a longer message used to
   wrap to 2 lines and force one wider than the other's 1-line height,
   which is what actually caused the inconsistency. */

.contact-card-standalone { padding: 20px; }

.next-steps-card {
  display: flex;
  flex-direction: column;
  gap: 2px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: 8px;
}

.next-step-row {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 10px 10px;
  border: none;
  border-radius: var(--radius-md);
  background: transparent;
  font-family: inherit;
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--text-primary);
  cursor: pointer;
  text-align: left;
  transition: background 0.12s;
}

.next-step-row:hover { background: var(--accent-tint); }

.next-step-check {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 1.5px solid var(--border-input);
  flex-shrink: 0;
  position: relative;
  transition: background 0.15s, border-color 0.15s;
}

.next-step-row.done .next-step-check {
  background: var(--accent-deep);
  border-color: var(--accent-deep);
}

.next-step-row.done .next-step-check::after {
  content: '✓';
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-sm);
  color: #ffffff;
  line-height: 1;
}

.next-step-row.done .next-step-label { color: var(--text-secondary); }

/* ─────────────────────────────────────────
   Responsive
───────────────────────────────────────── */
@media (max-width: 1200px) {
  .dashboard-body {
    grid-template-columns: 1fr;
  }
  .detail-columns {
    grid-template-columns: 1fr;
  }
}
