/**
 * css/targets-cards.css — the RAG palette and the scored-card treatment.
 * Version: 1.3.1 (Phase 20.1 follow-up — the accent bar is removed, not recoloured).
 * Version: 1.3.0 (Phase 20.1 follow-up — the verdict is the card surface).
 * Version: 1.2.0 (Phase 20.1 follow-up — the accent bar means RAG only).
 * Version: 1.1.0 (Phase 20.1 follow-up — row alignment).
 * Version: 1.0.0 (Phase 20.1, T7).
 *
 * Loaded on all thirteen dashboard/clients pages AND on targets.html.
 *
 * ── 1.1.0: the target line bottom-aligns ──────────────────────────────────
 * Against real CRC data the band read ragged: the Overdue tile's combined
 * `£209,712 (73.7%)` value wrapped at the true column width, so its target line
 * sat ~29px below DSO's and Debt >90's. Two changes fix it — the percentage is
 * now a deliberate sub-figure rather than a wrap, and .stat-target takes
 * margin-top: auto inside the flex column .stat-card became in
 * css/dashboard.css v3.1.2. Every scored card's verdict now shares one baseline
 * at the card's base, whatever the value above it does.
 *
 * ── 1.2.0: the accent bar carries the verdict and nothing else ────────────
 * The same 2px ::before that shows RAG also carried the brand gradient on the
 * band's first card, and for CRC and Virtus that brand glow IS a RAG hue. An
 * unscored tile therefore wore a verdict. The gradient is now suppressed on any
 * band that contains a scoreable card. This deliberately supersedes
 * UI-CONTRACT §11's "the :first-child brand gradient is preserved exactly",
 * which was written before the collision was visible against real data.
 *
 * ── 1.3.0: the verdict moves from a bar to the card surface ───────────────
 * The saturated 2px bar could not be made to meet the rounded card cleanly —
 * a 14px radius on a 2px-tall box, positioned against the padding box inside a
 * same-hue translucent border, on a card that must keep overflow: visible for
 * its tooltip. Rather than chase that geometry, the verdict became the card's
 * own surface: a 7% wash plus the border tint, both of which follow
 * border-radius natively. This also cuts the card from four red channels to
 * two, which is the actual reason the band read as alarming.
 * Supersedes UI-CONTRACT §3's "RAG lands on the existing 2px ::before accent
 * bar at full hue". The value colour and the text verdict are unchanged, so
 * criterion 6 ("colour the value and the card border") and criterion 15
 * (legible without colour) both still hold.
 *
 * ── Why this is a separate file, not part of css/targets.css ───────────────
 * css/targets.css reads --text-dim and --r-lg UNGUARDED, and
 * css/group-dashboard.css defines neither (CLAUDE.md records the
 * group-dashboard → targets-page → targets load order as load-bearing).
 * Pulling css/targets.css onto group/dashboard.html merely to reach a palette
 * would walk straight back into that trap. This file therefore owns the RAG
 * custom properties, and css/targets.css consumes them with its current
 * literals as fallbacks — one palette, one definition, no duplication.
 *
 * ── Contrast, measured for THIS phase ─────────────────────────────────────
 * css/targets.css:116 measured its pairs as a tint composited over the card.
 * Here the value and target text sit DIRECTLY on --card-bg with no tint
 * behind them, and the dark surface (#0F172A) had never been measured at all.
 * Re-measured with the WCAG relative-luminance formula, at 0.6875rem/600 —
 * which is NORMAL text for WCAG, not large — so the floor is AA 4.5:1:
 *
 *   light  green #166534 over #FFFFFF 7.13   over #F7FAFD 6.81
 *   light  red   #B91C1C over #FFFFFF 6.47   over #F7FAFD 6.18
 *   dark   green #4ADE80 over #0F172A 10.25
 *   dark   red   #F87171 over #0F172A 6.45
 *   neutral --text-muted  #8893A7 over #0F172A 5.76
 *                         #64748B over #FFFFFF 4.76   over #F7FAFD 4.54
 *
 * All eight clear AA, so no step-lightening was needed. The figures are
 * recorded rather than the conclusion, so a later palette change can be
 * re-checked against them.
 *
 * v1.3.0 puts a 7% RAG wash on the scored card, so the text no longer sits on
 * the bare surface and every pair above was RE-MEASURED over the composited
 * background. All six still clear AA; the worst case is 5.64:
 *
 *   light  green #166534 over #F0FBF4 6.73   over #E8F6F2 6.42
 *   light  red   #B91C1C over #FEF2F2 5.91   over #F6EDF0 5.64
 *   dark   green #4ADE80 over #10232E 9.26
 *   dark   red   #F87171 over #1F1A2C 6.11
 *
 * If the wash alpha is ever raised, re-measure: it is the background of record
 * for the value and the target line now, not --card-bg.
 *
 * Text hue and bar hue are DELIBERATELY different values. The 2px bar and the
 * 4px left border are graphics with no contrast floor, so they take the
 * saturated hue; text takes the darkened/lightened variant. Do not collapse
 * them into one token, and do not use --success / --danger for RAG text —
 * those measure 2.28:1 and 3.76:1 as light-theme text, both below AA.
 *
 * ── British English. No !important anywhere in this file. ─────────────────
 * Every rule that sets display on an element that can also carry [hidden] is
 * :not([hidden])-scoped, because class specificity beats the UA [hidden] rule
 * (Locked Decision #14).
 */

/* ============ Tokens ============ */

:root {
    --rag-green-text: #166534;
    --rag-red-text: #B91C1C;
    --rag-green-hue: #22C55E;                     /* group strip 4px left border */
    --rag-red-hue: #EF4444;
    --rag-green-edge: rgba(34, 197, 94, 0.38);    /* 1px card border tint */
    --rag-red-edge: rgba(239, 68, 68, 0.38);
    /* v1.3.0 — the card surface wash. Deliberately faint: it must read as a
       tinted card, not a coloured one, and it sits UNDER the value and target
       text whose AA ratios are re-measured over it in the header block. */
    --rag-green-wash: rgba(34, 197, 94, 0.07);
    --rag-red-wash: rgba(239, 68, 68, 0.07);
    --rag-neutral-text: var(--text-muted);        /* the unknown / unresolved state */
}

/* theme.js always writes an explicit data-theme on <html>, so this
   light-default / dark-override convention coexists with css/dashboard.css's
   dark-default / light-override. Neither is changed. */
[data-theme="dark"] {
    --rag-green-text: #4ADE80;
    --rag-red-text: #F87171;
}

/* ============ System A / A′ — the scored .stat-card ============ */

/* ── The verdict is the card's SURFACE, not a bar on top of it ─────────────
   v1.3.0 replaces the saturated 2px ::before bar. That bar could not be made to
   meet the card cleanly, for three compounding reasons measured in a browser:

     1. It carried `border-radius: var(--r-lg)` — 14px — on a box 2px TALL. CSS
        clamps radii that would overlap, scaling every corner by the same
        factor, so the effective corner collapsed to ~1px. The bar therefore ran
        essentially straight while the card curved at 14px beneath it, and its
        ends overhung the curve.
     2. `position: absolute; top/left/right: 0` resolves against the PADDING
        box, not the border box, so the fully saturated bar sat ~0.7px inside a
        38%-alpha border of the same hue: a doubled edge, a pale hairline
        wrapping a bright line.
     3. `.stat-card` sets `overflow: visible` — required, or the hover tooltip
        would be clipped — so the card's own radius could not rescue it either.

   A surface tint has none of these problems: background and border-color follow
   border-radius natively, so there is no second box to align and nothing to
   clip. It is also the stronger signal. Dashboard-design guidance is
   consistent that background and font colour carry KPI status best, and that
   the failure mode to avoid is the "Christmas tree" — this card previously
   spent FOUR channels on one verdict (bar, border, value, target line), which
   is why the band read as alarming rather than informative.

   The ::before does not paint at all on a scored band (v1.3.1) — see the rule
   below. Recolouring it was not enough: any colour other than the border's own
   leaves a seam at the rounded corner, because the bar is square-ended and
   sits inside the padding box.

   A flat linear-gradient rather than `background`, deliberately: it paints the
   wash as a background IMAGE over .stat-card's existing background-COLOUR, so
   --card-bg is never replaced and the tint cannot leak the page behind it.
   border-color stays in the doubled-class rule below, which also has to win
   against :hover. */
.stat-card--scored[data-rag="green"] {
    background-image: linear-gradient(var(--rag-green-wash), var(--rag-green-wash));
}
.stat-card--scored[data-rag="red"] {
    background-image: linear-gradient(var(--rag-red-wash), var(--rag-red-wash));
}

/* ── One channel, one meaning ─────────────────────────────────────────────
   The 2px ::before bar now carries the RAG verdict, so it must not also carry
   brand decoration on the same band. css/dashboard.css gives
   .stat-card:first-child a `transparent → --brand-glow → transparent` gradient,
   and for two of the six brands that glow IS a RAG hue: CRC's #00B871 against
   RAG green #22C55E, and Virtus's #E5202E against RAG red #EF4444. On those
   dashboards the unscored Total Debt tile wore a bar that read as a verdict —
   "on target" for CRC, "off target" for Virtus — for a metric that has no
   target at all. The other four brands are cyan/blue and do not collide, but
   the rule is uniform: a reader should not have to learn it per brand.

   Keyed on [data-metric], NOT on .stat-card--scored. data-metric is in the
   markup from the first paint, whereas .stat-card--scored only lands when
   /api/manage/targets resolves — keying on the latter would flash the brand
   gradient and then fade it to grey through .stat-card::before's 0.25s
   background transition on every page load.

   v1.3.1 — the bar is REMOVED from a scored band, not recoloured, and from
   EVERY card in it rather than only the first.

   v1.3.0 set it to var(--border) and called that neutral. It was not. The bar
   is painted inside the padding box, so on a scored card a dark #1E293B band
   sat directly on top of a red-tinted 1px border: the corners showed the
   border's 14px curve in red, then the square-ended bar cut across the top
   between them, leaving a visible dark notch at each top corner. Recolouring
   the bar could never fix that — ANY colour that is not exactly the border's
   own leaves a seam, and matching it exactly just reinstates a 3px top edge
   that the rounded corners still cannot follow.

   So nothing paints there at all. The top edge of a scored card is now purely
   its own border, which follows border-radius natively and meets the corner
   perfectly. Applying it to every card in the band, not just :first-child,
   also keeps the border weight uniform across the row: one 1px edge on all six
   tiles, rather than 1px on the scored ones and a doubled edge on the rest.

   The per-client dashboard band emits no data-metric (D16), so it is unmatched
   and keeps both its bar and the brand gradient: no verdicts there, nothing to
   confuse. Brand identity is unaffected elsewhere — the topbar stamp,
   --primary controls, the chart palette, the hover border and the focus ring
   all still carry it. */
.stats-grid:has(.stat-card[data-metric]) .stat-card::before,
#clients-kpi-strip:has(.stat-card[data-metric]) .stat-card::before {
    background: transparent;
}

/* (0,3,0), which also beats .stat-card:hover's (0,2,0). A scored card keeps
   its RAG border under the cursor; the lift and shadow still give the hover
   feedback. Deliberate: a border flickering from "off target" to brand-glow on
   hover would be worse than a static one. */
.stat-card.stat-card--scored[data-rag="green"] {
    border-color: var(--rag-green-edge);
}
.stat-card.stat-card--scored[data-rag="red"] {
    border-color: var(--rag-red-edge);
}

/* The :not() is what lets the Overdue tile colour only its bracketed
   percentage (D10) while every other card colours the whole value. */
.stat-card.stat-card--scored[data-rag="green"] .stat-value:not(.stat-value--partial),
.stat-card.stat-card--scored[data-rag="green"] .stat-value-scored {
    color: var(--rag-green-text);
}
.stat-card.stat-card--scored[data-rag="red"] .stat-value:not(.stat-value--partial),
.stat-card.stat-card--scored[data-rag="red"] .stat-value-scored {
    color: var(--rag-red-text);
}

/* D10 keeps the Overdue tile's combined `£209,712 (73.7%)` value. At the band's
   real column width (~174px of content at six tiles across 1440px) that string
   is ~230px in JetBrains Mono at 1.5rem, so it WRAPPED — splitting the figure
   mid-value and pushing the target line out of step with its neighbours.
   The percentage therefore becomes a deliberate sub-figure on its own line at
   ~0.7× the headline, which is the card vocabulary .stat-dual-incl already uses
   on the Total Debt tile. Both fragments are still present and only the
   percentage is still coloured, so D10 is honoured; what changes is that the
   second line is now designed rather than accidental. */
.stat-value--partial .stat-value-scored {
    display: block;
    font-size: 1.0625rem;
    line-height: 1.3;
}

/* ============ The target line ============ */

.stat-target {
    display: none;
}
.stat-target:not([hidden]) {
    display: block;
    font-family: 'JetBrains Mono', monospace;
    font-size: 0.6875rem;
    font-weight: 600;
    /* `auto`, not a fixed step: .stat-card is a flex column (css/dashboard.css
       v3.1.2) and .stats-grid stretches every card in a row to the tallest, so
       this pins the line to the card's base. That is what keeps the three
       target lines on ONE baseline when the value above them takes a different
       number of lines per card — the Overdue tile's £ headline plus its
       percentage sub-figure is two, the others are one. Without it the row
       reads ragged. Inert on targets.html, which loads this file for the
       palette but renders no .stat-card. */
    margin-top: auto;
    padding-top: var(--space-h);
    line-height: 1.35;
    color: var(--rag-neutral-text);
    /* At the 160px minimum column width the status word wraps to a second line
       rather than truncating (UI-CONTRACT §3 Responsive). No new breakpoint. */
    overflow-wrap: break-word;
}
.stat-card[data-rag="green"] .stat-target:not([hidden]) { color: var(--rag-green-text); }
.stat-card[data-rag="red"] .stat-target:not([hidden]) { color: var(--rag-red-text); }

/* The basis line D14 adds inside the hover tooltip. A block child of
   .stat-tooltip-desc, so it reads as its own line and inherits the desc's
   colour and line-height. */
.stat-tooltip-basis {
    margin-top: var(--space-h);
}

/* ============ System B — the group KPI strip ============ */

.kpi-target {
    display: none;
}
.kpi-target:not([hidden]) {
    display: block;
    font-family: 'JetBrains Mono', monospace;
    font-size: 0.85rem;
    font-weight: 600;
    margin-top: 4px;
    line-height: 1.35;
    color: var(--rag-neutral-text);
    overflow-wrap: break-word;
}

/* Scoped to the three scored tiles by id, so #kpi-total-outstanding's
   --group-accent left border is untouchable from here. */
#kpi-overdue[data-rag="green"],
#kpi-weighted-avg[data-rag="green"],
#kpi-debt90[data-rag="green"] {
    border-left-color: var(--rag-green-hue);
}
#kpi-overdue[data-rag="red"],
#kpi-weighted-avg[data-rag="red"],
#kpi-debt90[data-rag="red"] {
    border-left-color: var(--rag-red-hue);
}

#kpi-overdue[data-rag="green"] .kpi-value,
#kpi-weighted-avg[data-rag="green"] .kpi-value,
#kpi-debt90[data-rag="green"] .kpi-value {
    color: var(--rag-green-text);
}
#kpi-overdue[data-rag="red"] .kpi-value,
#kpi-weighted-avg[data-rag="red"] .kpi-value,
#kpi-debt90[data-rag="red"] .kpi-value {
    color: var(--rag-red-text);
}

#kpi-overdue[data-rag="green"] .kpi-target:not([hidden]),
#kpi-weighted-avg[data-rag="green"] .kpi-target:not([hidden]),
#kpi-debt90[data-rag="green"] .kpi-target:not([hidden]) {
    color: var(--rag-green-text);
}
#kpi-overdue[data-rag="red"] .kpi-target:not([hidden]),
#kpi-weighted-avg[data-rag="red"] .kpi-target:not([hidden]),
#kpi-debt90[data-rag="red"] .kpi-target:not([hidden]) {
    color: var(--rag-red-text);
}

/* ============ Notes ============ */

/* D15 — the figures on screen are seeds, not agreed targets. */
.targets-seed-note {
    display: none;
}
.targets-seed-note:not([hidden]) {
    display: block;
    margin-top: var(--space-1);
    font-size: 0.75rem;
    color: var(--text-muted);
}

/* The clients page's brand-wide caveat. Mirrors .targets-note
   (css/targets.css:210). */
.clients-targets-note {
    display: none;
}
.clients-targets-note:not([hidden]) {
    display: block;
    margin-top: var(--space-1);
    font-size: 0.75rem;
    color: var(--text-muted);
    font-style: italic;
}
