/* drix-ui.css, the shared DRiX component look.
 *
 * WHY THIS FILE EXISTS
 *
 * The pain point, question block and strategy card were the best-looking things
 * in DRiX, and they were also the most fragile. They lived as HTML strings with
 * every rule written as an inline style="..." attribute inside a 3,000 line
 * component file. Nothing could reference them, nothing could reuse them, and
 * nothing would fail if someone changed them. SDR could not adopt the look
 * without copying inline styles by hand, so it grew its own instead and the two
 * drifted apart within a day.
 *
 * This is that look, extracted into classes so it can be versioned, shared and
 * regression-tested. The palette is copied verbatim from DRiX-Leads
 * (client/src/index.css) so the colours are the ones already approved, not a
 * reinterpretation of them.
 *
 * HOW IT IS SHIPPED
 *
 * By copying this file into each product, not as a package. A private repo
 * consumed as a build dependency is exactly what broke the DRiX-Leads build:
 * an anonymous build machine cannot clone it. One stylesheet with no build step
 * cannot fail that way.
 *
 * THE CONTRACT
 *
 * Emit the DOM documented in DRIX-UI.md and these rules apply. Both a React
 * app and a no-build vanilla page can produce that DOM, which is the only way
 * one look can cover both products.
 *
 * Everything is scoped under .dx so it can be dropped into a page that still
 * has its own theme without bleeding into it.
 */

/* ─── TOKENS ─────────────────────────────────────────────────────────────────
 *
 * Verbatim from DRiX-Leads. `--dx-accent` is the ONE token a product may
 * override per record: SDR points it at the prospect's own brand colour so a
 * territory of leads is not thirty identical screens, while the surfaces stay
 * fixed so the product still looks like one product.
 */
.dx {
  --dx-bg:        #0a0e13;
  --dx-surface:   #121820;
  --dx-surface-2: #1a222c;
  --dx-surface-3: #222c38;
  --dx-text:      #e8ecf2;
  --dx-text-dim:  #a8b2c0;
  --dx-text-muted:#6b7685;
  --dx-border:    #2a3542;
  --dx-accent:    #5aa9ff;

  --dx-green:  #3ddc84;
  --dx-yellow: #ffc757;
  --dx-red:    #ff5a5a;
  --dx-orange: #ff9d5a;
  --dx-cyan:   #5ad4ff;
  --dx-purple: #b583ff;

  /* The three pain tiers. Company pain is the most specific and reads hottest;
     industry pain is the most general and reads coolest. The colour carries the
     same meaning as the tier label, so the two never disagree. */
  --dx-tier-company:     var(--dx-red);
  --dx-tier-subindustry: var(--dx-orange);
  --dx-tier-industry:    var(--dx-cyan);

  color: var(--dx-text);
  background: var(--dx-bg);
  font-family: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
}

/* ─── SHARED PRIMITIVES ──────────────────────────────────────────────────── */

/* Section heading: a short rule, then the label, then an optional count.
   Used above every group so the eye finds the boundary without a heavy border. */
.dx-section {
  display: flex; align-items: center; gap: .6rem;
  margin: 0 0 .85rem;
  font-size: 11px; font-weight: 800; letter-spacing: .16em; text-transform: uppercase;
  color: var(--dx-text-muted);
}
.dx-section::before {
  content: ""; width: 18px; height: 2px; border-radius: 2px;
  background: var(--dx-accent); flex: none;
}
.dx-section-count {
  font-size: 10px; font-weight: 800; letter-spacing: .06em;
  background: var(--dx-surface-2); color: var(--dx-text-dim);
  border-radius: 999px; padding: 2px 8px;
}

.dx-chips { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 6px; }
.dx-chip {
  font-size: 10px; font-weight: 700; letter-spacing: .02em;
  padding: 2px 8px; border-radius: 999px;
  background: var(--dx-surface-3); color: var(--dx-text-dim);
  white-space: nowrap;
}
/* Urgency is the only chip that earns colour. Everything else stays neutral so
   the coloured one actually means something when a rep scans the card. */
.dx-chip--urgency-high   { background: rgba(255, 90, 90, .16);  color: #ff8f8f; }
.dx-chip--urgency-medium { background: rgba(255, 199, 87, .16); color: var(--dx-yellow); }
.dx-chip--urgency-low    { background: rgba(107, 118, 133, .2); color: var(--dx-text-muted); }
.dx-chip--plain { background: none; padding-left: 0; color: var(--dx-text-muted); }

/* ─── PAIN POINT ─────────────────────────────────────────────────────────── */

.dx-pain-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 12px;
}

.dx-pain {
  background: rgba(255, 90, 90, .04);
  border: 1px solid color-mix(in srgb, var(--dx-tier) 19%, transparent);
  border-left: 3px solid var(--dx-tier);
  border-radius: 8px; padding: 12px 14px;
  --dx-tier: var(--dx-tier-company);
}
.dx-pain--company     { --dx-tier: var(--dx-tier-company);     background: rgba(255, 90, 90, .04); }
.dx-pain--subindustry { --dx-tier: var(--dx-tier-subindustry); background: rgba(255, 157, 90, .04); }
.dx-pain--industry    { --dx-tier: var(--dx-tier-industry);    background: rgba(90, 212, 255, .04); }

.dx-pain-title { font-size: 13px; font-weight: 700; color: var(--dx-text); margin: 0 0 4px; }
.dx-pain-desc  { font-size: 11px; color: var(--dx-text-dim); line-height: 1.5; margin: 0 0 6px; }
/* Evidence is quieter than the claim it supports, and set behind a rule so it
   reads as a citation rather than as another sentence of the pitch. */
.dx-pain-evidence {
  font-size: 10px; color: var(--dx-text-muted); font-style: italic; line-height: 1.4;
  border-left: 2px solid var(--dx-border); padding-left: 6px; margin: 0 0 6px;
}

/* Two personas side by side. This is the part that makes a pain usable on a
   call rather than merely true: who owns it, and who else feels it. */
.dx-personas { display: flex; gap: 8px; flex-wrap: wrap; }
.dx-persona {
  flex: 1; min-width: 140px;
  background: var(--dx-surface-2); border-radius: 6px; padding: 6px 8px;
  border-left: 2px solid var(--dx-text-muted);
}
.dx-persona--primary { border-left-color: var(--dx-accent); }
.dx-persona-label {
  font-size: 8px; text-transform: uppercase; letter-spacing: .08em;
  color: var(--dx-text-muted); font-weight: 700; margin-bottom: 2px;
}
.dx-persona-role { font-size: 11px; font-weight: 700; color: var(--dx-text); margin-bottom: 2px; }
.dx-persona-why  { font-size: 10px; color: var(--dx-accent); font-weight: 600; line-height: 1.4; margin-bottom: 2px; }
/* Their own words, in their voice. Italic because the rep is reading a quote,
   not a line to say back. */
.dx-persona-says { font-size: 10px; color: var(--dx-text-dim); line-height: 1.4; font-style: italic; }

/* ─── QUESTION BLOCK ─────────────────────────────────────────────────────── */

.dx-q {
  background: var(--dx-surface); border: 1px solid var(--dx-border);
  border-radius: 10px; padding: 16px 18px; margin-bottom: 12px;
}
.dx-q-stage {
  font-size: 10px; font-weight: 800; letter-spacing: .12em; text-transform: uppercase;
  color: var(--dx-accent); margin-bottom: 8px;
}
.dx-q-ask { font-size: 17px; font-weight: 700; line-height: 1.35; color: var(--dx-text); margin: 0 0 12px; }
.dx-q-label {
  font-size: 9px; font-weight: 800; letter-spacing: .12em; text-transform: uppercase;
  color: var(--dx-text-muted); margin-bottom: 3px;
}
.dx-q-text { font-size: 12.5px; color: var(--dx-text-dim); line-height: 1.55; margin: 0 0 10px; }
/* How to say it, not what to say. Set apart because tone is the thing a rep
   forgets under pressure. */
.dx-q-tone {
  background: var(--dx-surface-2); border-left: 3px solid var(--dx-accent);
  border-radius: 0 6px 6px 0; padding: 10px 14px; margin: 0 0 12px;
  font-size: 12px; font-style: italic; color: var(--dx-text-dim); line-height: 1.5;
}

/* Branches: what they might say, and what to say back. Two columns because a
   rep glances left for "this is going well" and right for "recover". */
.dx-branches { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; align-items: start; }
.dx-branch {
  background: var(--dx-surface-2); border-radius: 6px; padding: 10px 12px;
  border-left: 3px solid var(--dx-text-muted); margin-bottom: 10px;
}
.dx-branch--positive   { border-left-color: var(--dx-green);  background: rgba(61, 220, 132, .05); }
.dx-branch--pivot      { border-left-color: var(--dx-red);    background: rgba(255, 90, 90, .05); }
.dx-branch--unexpected { border-left-color: var(--dx-yellow); background: rgba(255, 199, 87, .05); }
.dx-branch-label {
  font-size: 10px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase;
  margin-bottom: 5px;
}
.dx-branch--positive   .dx-branch-label { color: var(--dx-green); }
.dx-branch--pivot      .dx-branch-label { color: var(--dx-red); }
.dx-branch--unexpected .dx-branch-label { color: var(--dx-yellow); }
.dx-branch-said  { font-size: 12px; font-style: italic; color: var(--dx-text); margin: 0 0 5px; line-height: 1.45; }
/* Next / Pivot, as a label above the points rather than a bold word inside a
   sentence. The rep is scanning for the label, not reading a paragraph. */
.dx-branch-replylabel {
  font-size: 9px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase;
  color: var(--dx-text-muted); margin-bottom: 3px;
}
/* Tighter inside a branch, where space is at a premium and the points are short. */
.dx-points--tight li { font-size: 12px; margin-bottom: .3rem; padding-left: .9rem; }
.dx-points--tight li::before { top: .5em; width: 4px; height: 4px; }
.dx-branch-reply { font-size: 12px; color: var(--dx-text-dim); line-height: 1.5; margin: 0; }
.dx-branch-reply b { color: var(--dx-text); font-weight: 700; }

/* Below the two-column breakpoint the branches stack, and stacking them in
   source order interleaves positive and pivot. Ordering keeps each column's
   sense intact when they collapse. */
@media (max-width: 720px) {
  .dx-branches { grid-template-columns: 1fr; }
}

/* Talking points. Deliberately not prose: a rep glances at these mid call and
   says it in their own words, so each one has to be findable in one sweep of
   the eye rather than read. */
.dx-points { margin: 0; padding: 0; list-style: none; }
.dx-points li {
  position: relative; padding-left: 1.05rem; margin-bottom: .45rem;
  font-size: 13px; line-height: 1.5; color: var(--dx-text);
}
.dx-points li::before {
  content: ""; position: absolute; left: 0; top: .52em;
  width: 5px; height: 5px; border-radius: 50%; background: var(--dx-accent);
}
/* A bullet that is really a paragraph. Marked rather than hidden, because the
   fix is to regenerate the card, and a rep should know which lines are stale. */
.dx-points li.prose { color: var(--dx-text-dim); font-style: italic; }
.dx-points li.prose::before { background: var(--dx-text-muted); }

/* ─── STRATEGY CARD ──────────────────────────────────────────────────────── */

.dx-strat {
  background: var(--dx-surface); border: 1px solid var(--dx-border);
  border-radius: 10px; padding: 16px 18px; margin-bottom: 12px;
}
.dx-strat--chosen { border-color: color-mix(in srgb, var(--dx-accent) 55%, transparent); }
.dx-strat-title { font-size: 16px; font-weight: 700; color: var(--dx-text); margin: 0 0 10px; }

/* Persona x pain. The signature of the strategy card: it says in one line who
   this is aimed at and what it is aimed at, which is the whole thesis. */
.dx-anchor { display: flex; align-items: center; flex-wrap: wrap; gap: 0; margin-bottom: 12px; }
.dx-anchor-persona, .dx-anchor-pain {
  font-size: 11.5px; font-weight: 700; padding: 4px 12px;
}
.dx-anchor-persona {
  background: rgba(90, 169, 255, .14); color: var(--dx-accent);
  border-radius: 999px 0 0 999px;
}
.dx-anchor-x {
  font-size: 11px; color: var(--dx-text-muted); padding: 4px 7px;
  background: rgba(90, 169, 255, .07);
}
.dx-anchor-pain {
  background: rgba(255, 90, 90, .12); color: #ff8f8f;
  border-radius: 0 999px 999px 0;
}
.dx-force {
  margin-left: 10px; font-size: 10px; font-weight: 800; letter-spacing: .08em;
  text-transform: uppercase; padding: 4px 10px; border-radius: 999px;
}
.dx-force--counter_inertia { background: rgba(181, 131, 255, .16); color: var(--dx-purple); }
.dx-force--economic_pull   { background: rgba(61, 220, 132, .14);  color: var(--dx-green); }
.dx-force--balanced        { background: rgba(90, 212, 255, .14);  color: var(--dx-cyan); }

.dx-strat-explain { font-size: 13px; color: var(--dx-text-dim); line-height: 1.6; margin: 0 0 14px; }

/* The four columns are the argument, in order: what hurts, what you add, what
   the product does, and the smallest next step. A strategy missing the last one
   is a slide, not a play. */
.dx-grid4 {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 10px;
  padding-bottom: 12px; border-bottom: 1px dashed var(--dx-border);
}
.dx-cell { background: var(--dx-surface-2); border: 1px solid var(--dx-border); border-radius: 6px; padding: 9px 11px; }
.dx-cell-label {
  font-size: 9px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase;
  color: var(--dx-text-muted); margin-bottom: 5px;
}
.dx-cell-text { font-size: 11.5px; color: var(--dx-text-dim); line-height: 1.5; }

.dx-conf { display: flex; align-items: center; gap: 10px; margin-top: 11px; }
.dx-conf-label {
  font-size: 10px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase;
  color: var(--dx-text-muted);
}
.dx-conf-track { width: 90px; height: 4px; border-radius: 2px; background: var(--dx-surface-3); overflow: hidden; }
.dx-conf-fill  { height: 100%; background: var(--dx-green); border-radius: 2px; }

/* A play's own opportunity score, on the strategy card. A chip and not a badge:
   the badge is the strongest play, these are the alternatives it beat. */
.dx-play-score {
  margin-left: 10px; font-size: 10px; font-weight: 800; letter-spacing: .04em;
  padding: 4px 10px; border-radius: 999px; cursor: help;
  font-variant-numeric: tabular-nums;
  background: var(--dx-surface-3); color: var(--dx-text-dim);
}
.dx-play-score--now { background: rgba(61, 220, 132, .16); color: var(--dx-green); }
.dx-play-score--mid { background: rgba(255, 199, 87, .14); color: var(--dx-yellow); }
.dx-play-score--low { opacity: .8; }

/* Fit and opportunity disagreeing is information, not an error. The common case
   is a GOOD lead the ICP would have thrown away, so this must never read as a
   warning. */
.dx-divergence {
  padding: 11px 14px; border-radius: 8px; margin-bottom: 10px;
  font-size: 12.5px; line-height: 1.55; color: var(--dx-text-dim);
  background: var(--dx-surface-2); border-left: 3px solid var(--dx-text-muted);
}
.dx-divergence--strong { border-left-color: var(--dx-green); background: rgba(61, 220, 132, .06); }
.dx-divergence--idle   { border-left-color: var(--dx-text-muted); }

/* ─── SCORE BADGE ────────────────────────────────────────────────────────── */
/* A number with its name under it, in a bordered box. Used for fit in Leads and
   for the opportunity rating in SDR, so the two read as the same kind of claim. */
.dx-score {
  /* Defined here rather than only as an inline fallback. A token that exists
     solely inside a fallback expression reads as defined but is not, and the
     smoke suite's stylesheet check is right to fail it: the day someone uses it
     without a fallback the layout breaks with nothing to point at.
     Do not write an example of that expression in a comment either, because the
     check scans comments too and will count it as a real usage. */
  --dx-score-color: var(--dx-orange);
  display: inline-flex; flex-direction: column; align-items: center; justify-content: center;
  min-width: 78px; padding: 8px 12px; border-radius: 8px;
  border: 1px solid var(--dx-score-color);
  background: color-mix(in srgb, var(--dx-score-color) 10%, transparent);
}
.dx-score-value {
  font-size: 26px; font-weight: 800; line-height: 1; font-variant-numeric: tabular-nums;
  color: var(--dx-score-color);
}
.dx-score-label {
  margin-top: 3px; font-size: 9px; font-weight: 800; letter-spacing: .12em;
  text-transform: uppercase; color: var(--dx-text-muted); text-align: center;
}
.dx-score--now     { --dx-score-color: var(--dx-green); }
.dx-score--mid     { --dx-score-color: var(--dx-yellow); }
.dx-score--low     { --dx-score-color: var(--dx-text-muted); }
.dx-score--unknown { --dx-score-color: var(--dx-text-muted); border-style: dashed; }

/* Segment and industry pain, folded away behind the company's own pain.
   Collapsed on purpose: a pattern is what you reach for when the specific
   thing is missing, and showing both open let a rep open on "companies like
   yours" while something about THIS company sat unread below it. */
.dx-fallback {
  margin-top: 18px;
  border-top: 1px solid var(--rule, #2a3542);
  padding-top: 12px;
}
.dx-fallback > summary {
  cursor: pointer;
  list-style: none;
  user-select: none;
  padding: 4px 0;
}
.dx-fallback > summary::-webkit-details-marker { display: none; }
.dx-fallback > summary::before {
  content: 'B8';
  display: inline-block;
  margin-right: 8px;
  transition: transform .15s ease;
}
.dx-fallback[open] > summary::before { transform: rotate(90deg); }
.dx-fallback > summary:hover { color: var(--ink, #e8ecf2); }
.dx-fallback > div { margin-top: 10px; }

/* ── Ask DRiX ───────────────────────────────────────────────────────────────
   The chat log, the messages and the box had NO styling at all. The panel
   rendered as unstyled text above a default browser input, which is why it
   read as broken rather than as empty. */
.chat {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 14px;
  max-height: 52vh;
  overflow-y: auto;
}
.chat:empty { display: none; }

.msg {
  max-width: 78%;
  padding: 10px 13px;
  border-radius: 10px;
  line-height: 1.55;
  white-space: pre-wrap;
  border: 1px solid var(--rule-soft, #222c38);
}
.msg.me {
  align-self: flex-end;
  background: var(--accent, #5aa9ff);
  color: var(--accent-ink, #0a0e13);
  border-color: transparent;
}
.msg.it {
  align-self: flex-start;
  background: var(--surface-2, #1a222c);
  color: var(--ink, #e8ecf2);
}
.msg.pending { color: var(--soft, #6b7685); font-style: italic; }

.askbox {
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: flex-end;
}
.askbox textarea {
  width: 100%;
  resize: vertical;
  min-height: 92px;
  padding: 11px 13px;
  border-radius: 9px;
  border: 1px solid var(--rule, #2a3542);
  background: var(--bg, #0a0e13);
  color: var(--ink, #e8ecf2);
  font: inherit;
  line-height: 1.55;
}
.askbox textarea::placeholder { color: var(--faint, #55606e); }
.askbox textarea:focus {
  outline: none;
  border-color: var(--accent, #5aa9ff);
}
.askbox button {
  padding: 9px 20px;
  border-radius: 8px;
  border: 0;
  cursor: pointer;
  font: inherit;
  font-weight: 600;
  background: var(--accent, #5aa9ff);
  color: var(--accent-ink, #0a0e13);
}
.askbox button:disabled { opacity: .5; cursor: not-allowed; }

/* ── Sparring, as an overlay ────────────────────────────────────────────────
   It used to insert itself after the button that opened it, which pushed the
   rest of the page down and left the rep scrolling to find the thing they were
   practising against. A drill is a mode, not a paragraph. */
.spar-modal {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 28px;
  background: rgba(6, 9, 14, .72);
  backdrop-filter: blur(3px);
  animation: spar-in .14s ease-out;
}
@keyframes spar-in { from { opacity: 0 } }

.spar-shell {
  width: min(860px, 100%);
  max-height: 88vh;
  display: flex;
  flex-direction: column;
  background: var(--surface, #121820);
  border: 1px solid var(--rule, #2a3542);
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 24px 70px rgba(0, 0, 0, .55);
}

.spar-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 18px;
  border-bottom: 1px solid var(--rule-soft, #222c38);
  background: var(--surface-2, #1a222c);
}
.spar-bar-title { font-weight: 600; color: var(--ink, #e8ecf2); }
.spar-x {
  margin-left: auto;
  background: none;
  border: 0;
  color: var(--soft, #6b7685);
  font-size: 24px;
  line-height: 1;
  cursor: pointer;
  padding: 0 4px;
}
.spar-x:hover { color: var(--ink, #e8ecf2); }

.spar-shell > .spar {
  overflow-y: auto;
  padding: 18px;
  margin: 0;
}

/* The microphone. Practising a call by typing is not practising a call: the
   skill is what comes out of your mouth, and typing lets you edit, which a
   real call never does. */
.btn-mic.on {
  background: var(--failed, #ff5a5a);
  color: var(--accent-ink, #0a0e13);
  border-color: transparent;
  animation: mic-pulse 1.1s ease-in-out infinite;
}
@keyframes mic-pulse { 50% { opacity: .6 } }

/* Our read: what we THINK, kept visually distinct from the consequence above
   it, which is what we OBSERVED. A rep is entitled to know which is which. */
.dx-read {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px dashed var(--rule, #2a3542);
}
.dx-read .dx-q-label { display: flex; align-items: center; gap: 8px; }
