/* pq-radar.css — "THE PRECISION RADAR"
   ============================================================================
   Hero visualisation for the #evaluations recorded-evidence section on
   primae.html. Companion to js/pq-radar.js.

   Sits inside each evidence panel below that panel's summary and never
   restyles a pm-/pv-/hv-/uv-/uw- node. Every class, attribute,
   custom property and keyframe in this file is pq- prefixed; no bare state
   class is used anywhere — state lives in data-pq-* attributes.

   Rules honoured here:
     · every visible text computes >= 13px (.82rem floor, SVG text 13.2px)
     · every label on the ink ground is at least #c8c2b7; recorded values are
       brighter still. No rule fades TEXT: emphasis is carried by weight,
       rule-lines and background, never by transparency over prose
     · the three systems are separated by BOTH colour AND marker shape AND
       stroke pattern, so colour is never the only cue
     · forced-colors keeps the chart and its non-colour shape/dash cues
   ========================================================================== */

/* ---------------------------------------------------------------- scope */

.primae-v3-page .pq-wrap {
    /* three systems: hue, shape and dash all differ. None of these three sit
       on the page's verdict palette (pass/close/fail/open). */
    --pq-s0: #ff8a45;
    --pq-s1: #78b4f2;
    --pq-s2: #c199f2;

    /* The ring FILLS are lighter, less saturated tints of the same three
       hues, not the stroke colours at low alpha. Three saturated washes stack
       into brown; three tints stack into a neutral warm grey, so an area
       where all three systems agree stays readable and every stroke over it
       keeps its own colour. */
    --pq-f0: rgba(255, 178, 136, .105);
    --pq-f1: rgba(150, 197, 247, .105);
    --pq-f2: rgba(209, 180, 247, .095);

    --pq-ground: #121210;
    --pq-ground-2: #1b1a17;
    --pq-rule: rgba(244, 241, 233, .18);
    --pq-rule-2: rgba(244, 241, 233, .095);

    --pq-label: #d2ccc1;
    --pq-dim: #c8c2b7;
    --pq-value: #f1eee5;

    grid-column: 1 / -1;
    min-width: 0;
    display: grid;
    gap: 2.1rem;
    margin-top: .3rem;
    padding-top: 1.5rem;
    border-top: 1px solid var(--pq-rule-2);
    color: var(--pq-label);
    font-family: var(--pm-sans);
}

.primae-v3-page .pq-wrap * {
    min-width: 0;
}

.pq-sr {
    position: absolute !important;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
}

/* ===========================================================================
   1. FIGURE

   There is no headline bar above the figures: each one carries its own ring
   key and no-comparison row. The first child of .pq-wrap is therefore the
   first figure, and the grid gap above it is the wrap's own padding-top.
   ========================================================================= */

.pq-fig {
    display: grid;
    gap: 1.1rem;
    min-width: 0;
}

.pq-fig + .pq-fig {
    padding-top: 1.9rem;
    border-top: 1px solid var(--pq-rule-2);
}

.pq-cap {
    display: grid;
    gap: .3rem;
    min-width: 0;
}

.pq-cap-ix {
    display: flex;
    align-items: baseline;
    gap: .45rem;
    color: var(--pm-rust-light);
    font-family: var(--pm-mono);
    font-size: .82rem;
    letter-spacing: .1em;
}

.pq-cap-ix b { font-weight: 500; }

.pq-cap-t {
    color: var(--pm-paper);
    font-size: clamp(1.2rem, 2.2vw, 1.55rem);
    font-weight: 600;
    letter-spacing: -.015em;
    line-height: 1.15;
}

.pq-cap-note {
    max-width: 62ch;
    margin-top: .15rem;
    color: var(--pq-label);
    font-size: .95rem;
    line-height: 1.55;
    text-wrap: pretty;
}

/* ===========================================================================
   2. BODY — plot beside the reading rail
   ========================================================================= */

.pq-body {
    display: grid;
    gap: 1.4rem;
    min-width: 0;
}

.pq-fig[data-pq-lay="wide"] .pq-body {
    grid-template-columns: minmax(0, 1fr) 20.5rem;
    align-items: start;
}

.pq-plot {
    display: flex;
    justify-content: flex-start;
    align-items: flex-start;
    min-width: 0;
    padding: .55rem;
    background: var(--pq-ground);
    border: 1px solid var(--pq-rule-2);
    overflow-x: auto;
    overscroll-behavior-inline: contain;
}

.pq-plot:focus-visible {
    outline: 2px solid var(--pm-rust-light);
    outline-offset: 3px;
}

.pq-svgwrap { flex: 0 0 auto; min-width: 0; margin-inline: auto; }

.pq-svg { display: block; }

/* ---------------------------------------------------------------- grid */

/* THE NOT-COMPARABLE SECTOR. A component no system can be scored on leaves
   its spoke empty from the hub to the rim; several of them side by side leave
   a wide blank wedge, and a blank wedge reads as a drawing that stopped
   rather than as a stated result. The hatch is the "excluded, not missing"
   mark. It is drawn under the grid and under the shaded band, faint enough
   that the rings, the dashed spokes and the italic axis labels all read over
   it, and it appears ONLY where the record has no value for any system. */
.pq-hatch-l {
    stroke: rgba(244, 241, 233, .115);
    stroke-width: 1;
}

.pq-nawedge { stroke: none; }

.pq-band { fill: rgba(244, 241, 233, .075); }

.pq-band-edge {
    fill: none;
    stroke: rgba(244, 241, 233, .34);
    stroke-width: 1;
    stroke-dasharray: 3 3;
}

.pq-ring {
    fill: none;
    stroke: rgba(244, 241, 233, .125);
    stroke-width: 1;
}

.pq-ring[data-pq-ring="edge"] { stroke: rgba(244, 241, 233, .4); }

/* THE NO-COMPARISON HUB. Every component the record does not compare puts a
   vertex in here, so it is drawn as a named zone rather than a dot: a darker
   well under the rings, and a dashed rim repeated ABOVE them (see the append
   order in js/pq-radar.js) so three translucent fills cannot bury the boundary
   of the zone. Its caption sits directly below it. */
.pq-hub {
    fill: #080806;
    stroke: none;
}

/* the veil sits over the three fills but under the marks: inside the zone the
   ring colours are damped back towards the plate, so the glyphs the reader has
   to count are the brightest thing in there */
.pq-hubveil { fill: rgba(9, 9, 7, .34); }

.pq-hubrim {
    fill: none;
    stroke: rgba(244, 241, 233, .55);
    stroke-width: 1.1;
    stroke-dasharray: 3 3;
}

.pq-spoke {
    stroke: rgba(244, 241, 233, .11);
    stroke-width: 1;
}

.pq-spoke[data-pq-na="1"] {
    stroke: rgba(244, 241, 233, .22);
    stroke-dasharray: 2 4;
}

.pq-spoke[data-pq-act="1"] { stroke: rgba(244, 241, 233, .3); }

/* the ring ruler is painted on top of the data (see the append order in
   js/pq-radar.js) and carries a halo rather than an opaque plate: a plate
   drawn after the label above it erases that label as the radius shrinks,
   and a plate under the polygons is erased by them in turn */
.pq-ringlab-t,
.pq-hublab-t {
    fill: #cbc5ba;
    font-family: var(--pm-mono);
    font-size: 13.2px;
    paint-order: stroke;
    stroke: #121210;
    stroke-width: 3.6px;
    stroke-linejoin: round;
}

.pq-ringlab[data-pq-band="1"] .pq-ringlab-t { fill: #e4dfd4; }

.pq-hublab-t { fill: #e4dfd4; }

/* ------------------------------------------------------------- highlight */

.pq-hiline {
    stroke: var(--pm-rust-light);
    stroke-width: 2;
    opacity: .8;
}

.pq-halo {
    fill: none;
    stroke-width: 1.5;
    opacity: .85;
}

.pq-halo[data-pq-s="0"] { stroke: var(--pq-s0); }
.pq-halo[data-pq-s="1"] { stroke: var(--pq-s1); }
.pq-halo[data-pq-s="2"] { stroke: var(--pq-s2); }

.pq-svg [data-pq-off="1"] { display: none; }

/* ---------------------------------------------------------------- series */

/* Each series is ONE closed body: a translucent fill of its own colour, a
   solid stroke and a marker at every vertex. The three fills are kept light
   and are ordered blue → violet → orange (see the paint order in
   js/pq-radar.js), so where all three overlap the stack still lands on a
   tinted ink rather than an opaque brown, and every stroke stays legible
   through the two fills above it. */
.pq-poly {
    fill-rule: nonzero;
    stroke-linejoin: round;
    stroke-linecap: round;
    vector-effect: non-scaling-stroke;
}

/* THREE STROKE PATTERNS, ONE PER SERIES — and every series that is painted
   OVER another one has to leave windows in itself.
   This record is full of components where two systems land on the same
   number, which puts two strokes on exactly the same path. The upper stroke
   is also the wider one, so a solid upper stroke erases the lower one along
   the whole shared edge: on the road figure eleven of fourteen components
   agree between the first two systems, and the second system's line would
   never be seen at all. The paint order is 1 → 2 → 0 (see js/pq-radar.js), so
   only series 1 sits at the bottom and may run solid; series 2 already
   carries a short dash, and series 0 — on top, and the widest — carries a
   long one. It still reads as one continuous line at a glance, and butt caps
   keep its windows the width they are set to instead of letting round caps
   close them up. Three patterns also make the file's own promise true: hue,
   marker shape AND stroke pattern all differ between the three systems. */
.pq-poly[data-pq-s="0"] {
    fill: var(--pq-f0);
    stroke: var(--pq-s0);
    stroke-width: 2.5;
    stroke-dasharray: 19 4.8;
    stroke-linecap: butt;
}

.pq-poly[data-pq-s="1"] {
    fill: var(--pq-f1);
    stroke: var(--pq-s1);
    stroke-width: 2;
}

.pq-poly[data-pq-s="2"] {
    fill: var(--pq-f2);
    stroke: var(--pq-s2);
    stroke-width: 1.9;
    stroke-dasharray: 6 4.5;
}

/* the home series is a small solid core; the other two are open outlines, so
   a vertex two systems share shows all three marks nested instead of hiding
   one. This holds at the hub too, where the glyphs are scaled down together
   and therefore stay nested. */
.pq-mark[data-pq-s="0"] { fill: var(--pq-s0); stroke: #0e0e0c; stroke-width: 1.2; }
.pq-mark[data-pq-s="1"] { fill: none; stroke: var(--pq-s1); stroke-width: 2.2; }
.pq-mark[data-pq-s="2"] { fill: none; stroke: var(--pq-s2); stroke-width: 2.2; }

/* a glyph on the hub is drawn at the chord scale, so its stroke is scaled
   with it — the weight is put back so a hub mark is as crisp as any other */
.pq-mark[data-pq-na="1"][data-pq-s="0"] { stroke-width: 1.7; }
.pq-mark[data-pq-na="1"][data-pq-s="1"],
.pq-mark[data-pq-na="1"][data-pq-s="2"] { stroke-width: 3; }

/* series emphasis — chart marks only, never the words */
.pq-fig[data-pq-solo] .pq-series { opacity: .28; }
.pq-fig[data-pq-solo="0"] .pq-series[data-pq-s="0"],
.pq-fig[data-pq-solo="1"] .pq-series[data-pq-s="1"],
.pq-fig[data-pq-solo="2"] .pq-series[data-pq-s="2"] { opacity: 1; }

/* ----------------------------------------------------------- axis labels */

/* The halo is what lets a label cross a gridline, so it stays — but it is cut
   back to the width that job actually needs. The most common recorded value
   here is "exact", which puts a marker ON the rim, right against its own
   label: at 3.4px the halo took a notch out of the glyph it was standing
   beside. The other half of the same fix is in js/pq-radar.js (LABGAP), which
   moves the label a few px further out and reserves the room for it. Markers
   sit on a dark plate already; they do not need 3.4px of separation. */
.pq-ax-t {
    fill: #d5cfc4;
    font-family: var(--pm-mono);
    font-size: 13.2px;
    paint-order: stroke;
    stroke: #121210;
    stroke-width: 2.4px;
    stroke-linejoin: round;
}

.pq-ax[data-pq-na="1"] .pq-ax-t {
    fill: #c8c2b7;
    font-style: italic;
}

.pq-ax[data-pq-act="1"] .pq-ax-t {
    fill: #fff8f2;
    font-weight: 600;
}

.pq-hit {
    fill: rgba(0, 0, 0, 0);
    stroke: none;
    cursor: default;
}

/* ===========================================================================
   3. READING RAIL — series key, radial key, readout
   ========================================================================= */

.pq-rail {
    display: grid;
    align-content: start;
    gap: .9rem 1.2rem;
    min-width: 0;
}

/* Stacked under the plot the rail has the full width, so the key and the
   readout sit side by side instead of running as one long column. Flex, not
   auto-fit tracks: with exactly two children an auto-fit grid opens a third
   track at wide-ish widths and leaves it empty. Flex shares the row out
   between whatever is actually there. */
.pq-fig[data-pq-lay="stack"] .pq-rail {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
}

.pq-fig[data-pq-lay="stack"] .pq-legend { flex: 1 1 100%; }

.pq-fig[data-pq-lay="stack"] .pq-key,
.pq-fig[data-pq-lay="stack"] .pq-read {
    flex: 1 1 17rem;
    min-width: min(17rem, 100%);
}

/* -- series legend: real toggle buttons -- */

.pq-legend {
    display: flex;
    flex-wrap: wrap;
    gap: .4rem;
}

.pq-lg {
    display: inline-flex;
    align-items: center;
    gap: .45rem;
    min-height: 2.1rem;
    padding: .3rem .6rem;
    color: var(--pq-label);
    background: var(--pq-ground);
    border: 1px solid var(--pq-rule-2);
    font-family: var(--pm-mono);
    font-size: .84rem;
    cursor: pointer;
}

.pq-lg:hover { color: var(--pm-paper); border-color: var(--pq-rule); }

.pq-lg[aria-pressed="true"] {
    color: var(--pm-paper);
    background: var(--pq-ground-2);
    border-color: var(--pm-rust-light);
    box-shadow: inset 0 -2px var(--pm-rust-light);
}

.pq-gl {
    flex: none;
    width: 1rem;
    height: 1rem;
    display: block;
    overflow: visible;
}

/* -- radial key -- */

.pq-key { min-width: 0; }

.pq-key-h {
    color: var(--pq-dim);
    font-family: var(--pm-mono);
    font-size: .82rem;
    letter-spacing: .09em;
    text-transform: uppercase;
}

.pq-key-l {
    display: grid;
    margin-top: .45rem;
    border: 1px solid var(--pq-rule-2);
}

.pq-key-i {
    display: grid;
    grid-template-columns: .95rem minmax(0, 1fr) auto;
    align-items: center;
    gap: .5rem;
    padding: .32rem .55rem;
    border-bottom: 1px solid var(--pq-rule-2);
    color: var(--pq-label);
    font-family: var(--pm-mono);
    font-size: .82rem;
}

.pq-key-i:last-child { border-bottom: 0; }

.pq-key-i[data-pq-band="1"] { background: rgba(244, 241, 233, .055); }

.pq-key-i em {
    color: var(--pq-dim);
    font-style: normal;
    font-size: .82rem;
}

.pq-key-tick {
    width: .95rem;
    height: 1px;
    background: rgba(244, 241, 233, .4);
}

.pq-key-i[data-pq-hub="1"] {
    background: var(--pq-ground-2);
}

.pq-key-i[data-pq-hub="1"] .pq-key-tick {
    width: .5rem;
    height: .5rem;
    margin-left: .22rem;
    background: none;
    border: 1px dashed rgba(244, 241, 233, .6);
    border-radius: 50%;
}

/* -- readout -- */

.pq-read {
    display: grid;
    align-content: start;
    gap: .3rem;
    min-height: 10rem;
    padding: .75rem .8rem .8rem;
    background: var(--pq-ground);
    border: 1px solid var(--pq-rule);
}

.pq-read-hint {
    color: var(--pq-dim);
    font-size: .84rem;
    line-height: 1.5;
    text-wrap: pretty;
}

.pq-read[data-pq-state="idle"] .pq-read-b { display: none; }
.pq-read[data-pq-state="live"] .pq-read-hint { display: none; }

.pq-read-b { display: grid; gap: .28rem; }

.pq-read-n {
    color: var(--pq-value);
    font-size: 1rem;
    font-weight: 600;
    line-height: 1.25;
}

.pq-read-d {
    color: var(--pq-label);
    font-size: .86rem;
    line-height: 1.5;
    text-wrap: pretty;
}

.pq-read-v {
    display: grid;
    gap: .18rem;
    margin-top: .35rem;
    font-family: var(--pm-mono);
    font-size: .82rem;
}

.pq-read-v li {
    display: grid;
    grid-template-columns: 1rem 5.9rem minmax(0, 1fr);
    align-items: center;
    gap: .45rem;
}

.pq-read-s { color: var(--pq-dim); }
.pq-read-val { color: var(--pq-value); font-weight: 500; overflow-wrap: anywhere; }
.pq-read-word { display: none; }

.pq-fig[data-pq-scale="categorical"] .pq-read-v li {
    grid-template-columns: 1rem 5.9rem 2.2rem minmax(0, 1fr);
}

.pq-fig[data-pq-scale="categorical"] .pq-read-word {
    display: block;
    color: var(--pq-dim);
    font-style: normal;
}

.pq-tools { margin-top: .55rem; }

.pq-replay {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    min-height: 2.1rem;
    padding: .3rem .7rem;
    color: var(--pq-label);
    background: transparent;
    border: 1px solid var(--pq-rule);
    font-family: var(--pm-mono);
    font-size: .84rem;
    cursor: pointer;
}

.pq-replay i { font-style: normal; }
.pq-replay:hover { color: var(--pm-paper); border-color: var(--pm-rust-light); }

/* ===========================================================================
   6. NARROW TRIM
   ========================================================================= */

@media (max-width: 45rem) {
    .primae-v3-page .pq-wrap { gap: 1.7rem; }
    .pq-cap-note { font-size: .92rem; }
}

/* only where a readout value and its system name cannot share a line */
@media (max-width: 23rem) {
    .pq-read-v li { grid-template-columns: 1rem minmax(0, 1fr); }
    .pq-read-val { grid-column: 2; }
    .pq-fig[data-pq-scale="categorical"] .pq-read-v li { grid-template-columns: 1rem minmax(0, 1fr) auto; }
}

/* ===========================================================================
   7. MOTION AND FORCED COLOURS
   ========================================================================= */

@media (prefers-reduced-motion: reduce) {
    .pq-lg, .pq-replay { transition: none; }
}

@media (forced-colors: active) {
    /* Keep the chart and its shape/dash cues; only ornamental helpers stand down. */
    .primae-v3-page .pq-key-tick,
    .primae-v3-page .pq-tools { display: none; }

    .primae-v3-page .pq-wrap { display: grid; }
    .primae-v3-page .pq-body { display: grid; }
    .primae-v3-page .pq-rail { display: grid; }
    .primae-v3-page .pq-read { display: grid; border: 1px solid CanvasText; }
    .primae-v3-page .pq-key-l { display: grid; border: 1px solid CanvasText; }
    .primae-v3-page .pq-key-i { display: grid; grid-template-columns: minmax(0, 1fr) auto; }
}
