/*
 * Stage colors — the single source of truth for the rendered `PipelineStage` values
 * (ISH-353, which absorbed ISH-274; drawn as a gradient by ISH-523, redrawn as
 * five light/dark hue families by ISH-799).
 *
 * This replaced per-page copies of the stage palette that had drifted across the
 * six pages carrying them, the same way css/portal-rail.css replaced the old
 * per-page rail CSS. Before this file, Close was blue in the Broker Portal but
 * green on the Sales Pipeline board, and Qualify/Pursue had three mutually
 * contradicting definitions. Don't re-declare any of these colors in a page's
 * inline <style> — add the stage here and link this file instead.
 *
 * Every page that renders a stage indicator must link this file. Today that is
 * index.html, brokers.html, broker.html, map.html, sales-pipeline.html,
 * sales-pipeline-detail.html, sales-pipeline-home.html,
 * sales-pipeline-report.html and implementation-detail.html (added by ISH-801,
 * which found it rendering a hardcoded grey bullet for all eleven stages).
 * staff-profile.html uses [data-stage="Active"|"Completed"] for *process*
 * status, not a pipeline stage, and deliberately does not link this file.
 *
 * ⚠️ Nothing enforces this rule — it is a comment, and ISH-801 is what happens
 * when a comment is the only guard. ISH-803 is the parity test that would.
 *
 * The palette must stay in sync with the `PipelineStage` enum in
 * dataconnect/schema/schema.gql — with one deliberate exception. DESIGN_GUIDE.md
 * carries the same table for humans, and .docs/AGENT_GUIDE.md records why each
 * hue was chosen.
 *
 * ⚠️ `NotABrokerProspect` (ISH-798) has NO token here, on purpose. That enum
 * value exists for CRM parity only and is rendered nowhere in the app: it is
 * absent from every stage picker, from salesPipelineVisibleStages() and from
 * pipelineStageLabel(), and a raw `NotABrokerProspect` on screen is the tell
 * that something rendered a stage it should have filtered. Giving it a colour
 * would make that mistake look deliberate and blunt the tripwire, so it falls
 * through to the neutral grey the consumer rules already default to. **Do not
 * "fix" the enum/palette mismatch by adding it.** The enum has eleven values
 * and this file has ten stages plus `Won`; that is correct.
 *
 * Two token-carrying conventions are supported because the app already uses
 * both: a [data-stage="<Stage>"] attribute on an ancestor (dots, badges, bucket
 * and kanban counts) and a .pill-<stage> class on the element itself (the
 * .stage-pill tinted breakdown pills). Both resolve the same three tokens, so a
 * dot and a pill for one stage can never disagree.
 *
 *   --stage-color      solid fill: status dots, bucket counts, kanban counts
 *   --stage-tint       ~12% wash used as the tinted-pill background
 *   --stage-text       stage color darkened where needed to stay readable on
 *                      --stage-tint; equal to --stage-color where it already is
 *   --stage-count-text text for a solid count pill; defaults to white and is
 *                      overridden to #1a1a1a on the light member of each family,
 *                      whose fill can't carry white (ISH-799 made this a rule
 *                      rather than the ad-hoc set of three it used to be)
 *
 * ── The structure: five families, each a light stage and a deep one ─────────
 *
 * ISH-799 replaced ISH-523's single indigo -> teal -> green gradient. That sweep
 * encoded progression in *hue only*, which left six of the eight progression
 * stages inside a 5.4-point lightness band: Close/Implementation were 9.2 ΔE2000
 * apart — the closest pair in the app, on the Sales Pipeline -> Broker Portal
 * handoff — with Qualify/Pursue at 9.9 and Identify/Plan at 10.1. At the size a
 * status dot actually renders, that is not a usable difference.
 *
 * Each family now holds two stages that genuinely belong together, so the shared
 * hue means something, and within a family the *earlier stage is the light one*:
 *
 *   teal        Identify -> Plan            before engagement (both hidden)
 *   purple      Qualify  -> Pursue          prospecting, no commitment yet
 *   blue        Close    -> Implementation  the handoff: signature, then build
 *   green       Service  -> Expand          a live account
 *   warm grey   OnHoldOrLost / Churned      left the funnel
 *
 * Every light member sits at L* 61 and every deep member at L* 37 — the same two
 * rungs in all four progression families, so no stage is the odd one out. That
 * is a consequence of how the values were derived, not hand-matching: each fill
 * is the maximum in-gamut chroma at the OKLCH lightness yielding a fixed
 * contrast on white (3.04:1 light, 7.2:1 deep). Closest pair anywhere in the
 * palette is now 20.8 ΔE, and 23.2 among the six stages the board renders.
 *
 * ⚠️ The two greys deliberately run the *other* way — Churned deep, Hold light.
 * They are outcomes rather than a sequence, and the heavier of the pair being
 * the permanent one is correct. Don't "fix" that to match the four above.
 *
 * ⚠️ Contrast: every --stage-text-on---stage-tint and
 * --stage-count-text-on---stage-color pairing below is WCAG AA-verified for
 * *text* (>=4.5:1; 5.68:1 is the worst case). That is a claim about text only —
 * the status dot is a graphic under WCAG 1.4.11's 3:1 rule, which nine of the
 * ten fills clear. OnHoldOrLost's dot is 2.52:1 and is a deliberate exception:
 * it is a kept value, and a terminal row also carries .stage-faded and its own
 * label, so the dot is never the only cue. Before ISH-799 the header claimed
 * ">=4.5:1" for every pairing without that carve-out, which was wrong for three
 * of the dots.
 */

/* Sales Pipeline portal stages, in lifecycle order.
 *
 * Identify and Plan are in SALES_PIPELINE_HIDDEN_STAGES (js/shared.js), which
 * keeps them off the board and off every Broker Portal page. These two tokens
 * were defined ahead of any consumer for exactly that reason; as of ISH-320
 * they have one — sales-pipeline-report.html is the single page in the app that
 * renders these stages, and "hidden" there means hidden from the board, not
 * from the portal. They are the teal family: nothing has been engaged yet. */
[data-stage="Identify"],
.pill-identify {
  --stage-color: #00a59a;
  --stage-tint: rgba(0, 165, 154, 0.12);
  --stage-text: #23645d;
  --stage-count-text: #1a1a1a;
}

[data-stage="Plan"],
.pill-plan {
  --stage-color: #00625b;
  --stage-tint: rgba(0, 98, 91, 0.12);
  --stage-text: #1f5a54;
}

/* Qualify and Pursue are the purple family — prospecting, nothing committed. */
[data-stage="Qualify"],
.pill-qualify {
  --stage-color: #a381f0;
  --stage-tint: rgba(163, 129, 240, 0.12);
  --stage-text: #7432d0;
  --stage-count-text: #1a1a1a;
}

[data-stage="Pursue"],
.pill-pursue {
  --stage-color: #702ccb;
  --stage-tint: rgba(112, 44, 203, 0.12);
  --stage-text: #682dbd;
}

/* Close and Implementation are the blue family, and they are the pair ISH-799
 * exists for: they were 9.2 ΔE apart, the closest in the app, sitting on the
 * Sales Pipeline -> Broker Portal handoff. Same hue now says "these two are one
 * transition"; the 24.6 ΔE between light and deep says which side you're on. */
[data-stage="Close"],
.pill-close {
  --stage-color: #2c9be6;
  --stage-tint: rgba(44, 155, 230, 0.12);
  --stage-text: #225f8b;
  --stage-count-text: #1a1a1a;
}

/* First Broker Portal stage — the deep half of the blue pair. */
[data-stage="Implementation"],
.pill-implementation {
  --stage-color: #165c8b;
  --stage-tint: rgba(22, 92, 139, 0.12);
  --stage-text: #1e567e;
}

/* Service and Expand are the green family — a live account. Service is the
 * light member, so it keeps --stage-count-text (3.06:1 fill can't carry white). */
[data-stage="Service"],
.pill-service {
  --stage-color: #43a828;
  --stage-tint: rgba(67, 168, 40, 0.12);
  --stage-text: #2d671f;
  --stage-count-text: #1a1a1a;
}

/* Expand is the deep member and therefore has NO --stage-count-text: at 7.21:1
 * its fill carries white. It had one under ISH-523's lighter olive; that
 * override was deleted rather than left as a no-op override of the default. */
[data-stage="Expand"],
.pill-expand {
  --stage-color: #256414;
  --stage-tint: rgba(37, 100, 20, 0.12);
  --stage-text: #285d1b;
}

/* Churned is a warm dark grey rather than pure black (ISH-523) — still reads
 * as "this one stopped", softer than black without losing that meaning.
 *
 * ⚠️ Churned and OnHoldOrLost are the one family whose deep member comes
 * *second* in enum order, i.e. the inverse of the four progression families
 * above. That is deliberate (ISH-799): they are outcomes, not a sequence, and
 * the permanent one being the heavier of the two is the right way round. These
 * two values are also the only ones ISH-799 left untouched. */
[data-stage="Churned"],
.pill-churned {
  --stage-color: #57534e;
  --stage-tint: rgba(87, 83, 78, 0.12);
  --stage-text: #292524;
}

/* "Won" is NOT a PipelineStage — it is the Pipeline Report funnel's synthetic terminal step
 * (ISH-320), standing for Service and Expand together: the deal closed, implementation finished,
 * and the account is live. It lives here rather than in that page's own <style> block for the
 * reason this whole file exists — a stage color declared in a page is how the palette drifted
 * before ISH-353. It reuses Expand's green deliberately: the step means "live account", and Expand
 * is the stage a healthy live account sits in. If a real `Won` stage is ever added to the
 * PipelineStage enum, this entry already fits it and nothing needs to move.
 *
 * ⚠️ It mirrors Expand *exactly*, so it tracks Expand through a palette change —
 * including dropping --stage-count-text when ISH-799 made Expand's fill dark
 * enough for white. Change Expand, change this. */
[data-stage="Won"] {
  --stage-color: #256414;
  --stage-tint: rgba(37, 100, 20, 0.12);
  --stage-text: #285d1b;
}

/* OnHoldOrLost is a lighter warm grey (ISH-523; was a plain mid-grey before) —
 * dark text on its solid count pill, since white fails contrast on a fill this
 * light (2.52:1). That same 2.52:1 is why its *dot* is the palette's one
 * deliberate WCAG 1.4.11 exception — see the header. Kept as-is by ISH-799. */
[data-stage="OnHoldOrLost"],
.pill-onholdorlost {
  --stage-color: #a8a29e;
  --stage-tint: rgba(168, 162, 158, 0.12);
  --stage-text: #44403c;
  --stage-count-text: #1a1a1a;
}

/* ---- Consumers ------------------------------------------------------------
 *
 * Each selector below is deliberately specific enough to outrank the unstyled
 * base rule it overrides in a page's inline <style>, which loads *after* this
 * file. The tinted-pill rules are written as .stage-pill.pill-<stage> rather
 * than bare .pill-<stage> for exactly that reason: a bare single-class selector
 * ties with the page's own `.stage-pill { color: inherit }` and would lose on
 * source order. A stage with no token falls back to the same neutral grey the
 * base rules already used, so an unrecognised stage degrades instead of
 * disappearing. */

/* Solid fill — status dots. */
[data-stage] .status-dot {
  background: var(--stage-color, #999999);
}

/* Solid fill — the count badge on a Sales Pipeline bucket and on a Broker
 * Portal kanban column. */
.stage-bucket[data-stage] .bucket-count,
.broker-kanban-column[data-stage] .broker-kanban-column-count {
  background: var(--stage-color, #999999);
  color: var(--stage-count-text, #ffffff);
}

/* Tinted pill — the .stage-pill stage breakdowns on the two portal home pages. */
.stage-pill.pill-identify,
.stage-pill.pill-plan,
.stage-pill.pill-qualify,
.stage-pill.pill-pursue,
.stage-pill.pill-close,
.stage-pill.pill-implementation,
.stage-pill.pill-service,
.stage-pill.pill-expand,
.stage-pill.pill-churned,
.stage-pill.pill-onholdorlost {
  background: var(--stage-tint, rgba(153, 153, 153, 0.15));
  color: var(--stage-text, #6b7280);
}

/* Tinted badge — the stage badge in a map.html broker popup. */
.badge-stage[data-stage] {
  background: var(--stage-tint, rgba(153, 153, 153, 0.15));
  color: var(--stage-text, #6b7280);
}

/* Faded — a broker that has left the funnel rather than progressed through it (Churned or
 * OnHoldOrLost, i.e. `BrokerApp.isTerminalStage()`). Applied by the page's own renderer as a
 * class, not by a `[data-stage]` attribute, because the *rule* is "terminal", not "this stage":
 * a page adds it from `isTerminalStage()` so a future terminal stage inherits it with no CSS
 * edit. That helper's JSDoc already names fading a row as one of its three uses.
 *
 * ⚠️ Deliberately NOT scoped to `.broker-card`. It is on the `<tr>` as well in brokers.html's
 * Table view, which is the whole reason the selector is bare.
 *
 * ISH-482 promoted this out of brokers.html's inline <style>. It was already duplicated —
 * map.html carried a `.broker-card.stage-faded` copy whose own comment said it was "matching
 * brokers.html's" — and sales-pipeline.html's Hold column needed it as a third. The values are
 * brokers.html's verbatim; map.html's copy held the same two numbers, so removing it changes
 * nothing there. The hover partially lifts the fade rather than clearing it: these rows are
 * still readable on demand without ever reading as active.
 *
 * Don't re-declare this in a page's inline <style> — that is exactly how the second copy
 * happened. */
.stage-faded {
  opacity: 0.55;
  transition: opacity 0.25s ease;
}

.stage-faded:hover {
  opacity: 0.95;
}
