/*
 * HSCodeMatch regulation news — footnotes + infographic figure.
 *
 * Loaded once for all articles instead of a <style> block per post. That is the
 * whole reason the infographic prompt is forbidden from emitting CSS: 507 unique
 * style blocks would be uncacheable, unreviewable, and would leak bare `body{}`
 * and `.card{}` selectors into the theme.
 *
 * Everything is scoped under .hsn-*. Colours and fonts come from the theme's own
 * Elementor globals, with the measured values as fallbacks, so this tracks the
 * site rather than competing with it.
 */

:root {
    --hsn-ink:    var(--e-global-color-primary,   #181D27);
    --hsn-accent: var(--e-global-color-secondary, #7A5AF8);
    --hsn-text:   var(--e-global-color-text,      #535862);
    --hsn-line:   rgba(24, 29, 39, .12);
    --hsn-wash:   rgba(122, 90, 248, .07);
    --hsn-warn:   #C2410C;
    --hsn-radius: 14px;
}

/* ── lede ─────────────────────────────────────────────────────────────── */

.hsn-lede {
    font-size: 1.18em;
    line-height: 1.6;
    color: var(--hsn-ink);
    font-weight: 500;
    border-left: 3px solid var(--hsn-accent);
    padding-left: 1em;
    margin-bottom: 1.6em;
}

/* ── inline citations ─────────────────────────────────────────────────── */

.hsn-cite {
    font-size: .7em;
    line-height: 0;
    vertical-align: super;
    white-space: nowrap;
    margin-left: .12em;
}
.hsn-cite a {
    color: var(--hsn-accent);
    text-decoration: none;
    font-weight: 600;
    padding: 0 .1em;
}
.hsn-cite a:hover,
.hsn-cite a:focus { text-decoration: underline; }
/* Highlight the footnote you just jumped to. */
.hsn-refs li:target { background: var(--hsn-wash); border-radius: 6px; }

/*
 * Where an anchor jump LANDS.
 *
 * A citation is a round trip: the superscript jumps down to the footnote, the
 * footnote's arrow jumps back up to the sentence. By default the browser puts
 * the target's top edge flush with the top of the viewport, and Soledad's
 * navigation is sticky (`sticky-enable` / `is-sticky` on #navigation) — so the
 * highlighted footnote landed underneath the navbar and the marker you came
 * from landed behind it too.
 *
 * 40vh rather than the navbar's height. Clearing the bar is not enough on its
 * own: it puts the thing you clicked at the very top edge of the readable area
 * with none of its surroundings above it, and a citation only means anything in
 * context — you jump to a footnote to read the line it sits in, and back to a
 * marker to re-read the sentence carrying it. Landing near the middle brings
 * that context with it, and it needs no number from the theme, so a header that
 * changes height does not silently break it.
 *
 * Near the foot of the page the browser cannot scroll 40vh further and the
 * target lands as low as the document allows. That is the correct behaviour and
 * the Sources block, which sits last, is where it shows.
 */
.hsn-refs li,
.hsn-cite a[id] { scroll-margin-top: 40vh; }

/* ── source list ──────────────────────────────────────────────────────── */

/* Size and weight come from the theme's .wp-block-heading; only spacing here. */
.hsn-refs-title { margin-top: 2.4em; }

.hsn-refs {
    font-size: .9em;
    line-height: 1.55;
    color: var(--hsn-text);
    padding-left: 1.4em;
    border-top: 1px solid var(--hsn-line);
    padding-top: 1.1em;
}
.hsn-refs li { margin-bottom: .8em; padding: .2em .4em; }
.hsn-refs a { color: var(--hsn-ink); }
.hsn-refs__back { margin-right: .4em; text-decoration: none; color: var(--hsn-accent); }
.hsn-refs__url {
    display: block;
    font-size: .85em;
    color: var(--hsn-text);
    opacity: .75;
    word-break: break-all; /* long WTO directdoc URLs must not widen the page */
}

/* ── tables in the long-form answer ───────────────────────────────────── */

/* The answer pipeline emits comparison tables. They must scroll inside their own
   box — the page body must never scroll sideways on a phone. */
.hsn-table {
    overflow-x: auto;
    margin: 1.6em 0;
    border: 1px solid var(--hsn-line);
    border-radius: 10px;
    -webkit-overflow-scrolling: touch;
}
.hsn-table table {
    border-collapse: collapse;
    width: 100%;
    min-width: 480px;
    font-size: .92em;
    margin: 0;
}
.hsn-table th,
.hsn-table td {
    padding: .7em .9em;
    text-align: left;
    vertical-align: top;
    border-bottom: 1px solid var(--hsn-line);
}
.hsn-table thead th {
    background: rgba(24, 29, 39, .03);
    font-weight: 600;
    color: var(--hsn-ink);
    white-space: nowrap;
}
.hsn-table tbody tr:last-child td { border-bottom: 0; }

/* ── infographic figure ───────────────────────────────────────────────── */

/* Section headings inside the figure. The theme sizes h3/h4 for article body
   copy, which is far too loud for a caption-scale label inside a card. */
.hsn-fig h3:not(.hsn-fig__headline),
.hsn-fig h4 {
    font-size: .78em !important;
    font-weight: 700 !important;
    line-height: 1.3 !important;
    text-transform: uppercase;
    letter-spacing: .07em;
    color: var(--hsn-text);
    margin: 0 0 .9em !important;
}
/* Fixed class vocabulary. The generator may only use these plus inline <svg>. */

.hsn-fig {
    margin: 2em 0;
    border: 1px solid var(--hsn-line);
    border-radius: var(--hsn-radius);
    overflow: hidden;
    background: #fff;
}

.hsn-fig__hero { background: var(--hsn-ink); color: #fff; padding: 1.8em 1.6em; }
.hsn-fig__kicker {
    font-size: .72em; text-transform: uppercase; letter-spacing: .09em;
    opacity: .72; margin-bottom: .7em;
}
/* Two classes, not one. Themes colour every heading inside the content
   wrapper — Soledad's `.post-entry h3` (0,1,1) outranked a lone
   `.hsn-fig__headline` (0,1,0) and painted the hero's headline dark grey on a
   near-black panel. `.hsn-fig .hsn-fig__headline` is 0,2,0 and wins without
   reaching for !important. The same applies to anything else the hero owns. */
.hsn-fig .hsn-fig__headline {
    font-size: 1.75em; font-weight: 800; line-height: 1.15; margin: 0 0 .45em;
    color: #fff;
}
.hsn-fig .hsn-fig__hero .hsn-fig__kicker,
.hsn-fig .hsn-fig__hero .hsn-fig__stand { color: inherit; }
.hsn-fig__stand { font-size: 1em; opacity: .82; margin: 0; line-height: 1.5; }

/* Flex, not grid. `repeat(auto-fit, minmax(140px, 1fr))` sized the row for as
   many 140px tracks as fit, and the <h4> spanning `1 / -1` kept the surplus
   tracks from collapsing — so a two-number figure left a third of its width as
   bare grey container background. Flex items stretch to fill the row whatever
   the count, and the 1px gaps still show the background as hairlines. */
.hsn-fig__stats {
    display: flex; flex-wrap: wrap;
    gap: 1px; background: var(--hsn-line);
}
.hsn-fig__stats > *:not(.hsn-fig__stat) {
    flex: 1 0 100%; background: #fff; padding: 1.1em 1.2em 0;
}
.hsn-fig__stat { flex: 1 1 140px; background: #fff; padding: 1.3em 1.2em; }
.hsn-fig__num {
    display: block; font-size: 2.1em; font-weight: 800; line-height: 1.05;
    color: var(--hsn-accent);
}
.hsn-fig__lab {
    display: block; font-size: .8em; color: var(--hsn-text); margin-top: .35em;
    line-height: 1.4;
}

.hsn-fig__cards, .hsn-fig__who, .hsn-fig__flow, .hsn-fig__time { padding: 1.5em 1.6em; }
/* Cards and rows are filled blocks like everything else now. They were the last
   outlined-white-box-with-an-icon form on the page, and a figure that speaks two
   visual languages at once reads as two figures. Colour still comes from the
   series slot, so a set of cards can be grouped the same way a flow is. */
.hsn-fig__cards { display: grid; gap: .9em; }
.hsn-fig__cards > *:not(.hsn-fig__card) { grid-column: 1 / -1; }
.hsn-fig__card {
    display: flex; gap: .9em; align-items: flex-start;
    border: 1px solid var(--hsn-line); border-left: 3px solid var(--hsn-accent);
    border-radius: 10px; padding: .95em 1.1em;
}
.hsn-fig__card > *:not(.hsn-fig__icon) { flex: 1; margin: 0; }
.hsn-fig__card.hsn-fig--warn { border-left-color: var(--hsn-warn); }

/* Icon chip. The set is stroke-based and inherits currentColor, so one rule
   colours every icon and --warn recolours it without a second icon set. */
.hsn-fig__icon {
    flex: 0 0 auto;
    display: inline-flex; align-items: center; justify-content: center;
    width: 2.2em; height: 2.2em;
    border-radius: 9px;
    background: var(--hsn-wash);
    color: var(--hsn-accent);
}
.hsn-fig__icon svg { width: 1.25em; height: 1.25em; display: block; }
.hsn-fig--warn > .hsn-fig__icon { background: rgba(194, 65, 12, .10); color: var(--hsn-warn); }
.hsn-fig__hero .hsn-fig__icon { background: rgba(255, 255, 255, .14); color: #fff; }
.hsn-fig__stat .hsn-fig__icon { width: 1.9em; height: 1.9em; margin-bottom: .5em; }

.hsn-fig__who { background: var(--hsn-wash); }
.hsn-fig__row {
    display: flex; gap: .9em; align-items: flex-start;
    padding: .8em 0; border-bottom: 1px solid var(--hsn-line);
}
.hsn-fig__row > *:not(.hsn-fig__icon) { flex: 1; margin: 0; }
.hsn-fig__row .hsn-fig__icon { background: #fff; }
.hsn-fig__row:last-child { border-bottom: 0; }

/* Process flow.
   Numbered steps rather than connector arrows. The arrow was a rotated
   pseudo-element sitting in the flex gap: too faint at 2px of --hsn-line,
   never quite centred, and — the real problem — it still pointed sideways
   when steps wrapped onto a second row, implying a link that was not there.
   A counter is correct at every width and needs nothing from the model. */
.hsn-fig__flow {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 1em;
    counter-reset: hsn-step;
}
/* A heading is a grid item too, so without this it becomes a column and the
   steps wrap around it instead of sitting under it. */
.hsn-fig__flow > *:not(.hsn-fig__step) { grid-column: 1 / -1; }
.hsn-fig__step {
    counter-increment: hsn-step;
    position: relative;
    display: flex;
    gap: .75em;
    align-items: flex-start;
    border: 1px solid var(--hsn-line);
    border-radius: 12px;
    padding: 1em 1.1em 1em .95em;
    background: #fff;
}
/* The number badge doubles as the ordering cue, so no connector is needed. */
.hsn-fig__step::before {
    content: counter(hsn-step);
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75em;
    height: 1.75em;
    border-radius: 50%;
    background: var(--hsn-accent);
    color: #fff;
    font-size: .82em;
    font-weight: 700;
    line-height: 1;
}
.hsn-fig__step > *:not(.hsn-fig__icon) { flex: 1; margin: 0; }
/* An icon inside a step would compete with the number; keep it quiet. */
.hsn-fig__step .hsn-fig__icon {
    width: 1.6em; height: 1.6em; background: transparent;
    color: var(--hsn-text); opacity: .75;
}

.hsn-fig__time { border-top: 1px solid var(--hsn-line); }
.hsn-fig__ev {
    padding-left: 1.4em; position: relative; margin-bottom: .9em;
    border-left: 2px solid var(--hsn-line);
}
.hsn-fig__ev::before {
    content: ""; position: absolute; left: -6px; top: .45em;
    width: 10px; height: 10px; border-radius: 50%; background: var(--hsn-accent);
}

/* Two bar shapes, because the model builds them both ways.
   `style` is stripped from generated markup, so it cannot set a fill width on a
   div — it reaches for <svg><rect width="60"> instead, which IS expressible in
   the allowed SVG attributes. An SVG rect takes `fill`, not `background`, so
   styling only the div shape left those bars rendering solid black. */
/* Bar chart as a figure in its own right. `.hsn-fig__stats` is a stat GRID and
   gave each bar a 140px column; a chart wants full-width rows. */
.hsn-fig__chart { padding: 1.5em 1.6em; display: grid; gap: .35em; }
.hsn-fig__chart > *:not(.hsn-fig__bar) { grid-column: 1 / -1; }

.hsn-fig__bar {
    display: flex; align-items: center; gap: .6em; margin: .55em 0;
    font-size: .9em;
}
/* Fixed height, not `auto`. The generated viewBox is "0 0 100 10", so an auto
   height scaled the bar to a tenth of the column — a ~60px slab. The rect is
   drawn with preserveAspectRatio="none", so it stretches to whatever height is
   set here. */
/* Two classes, because the generic `.hsn-fig svg { height: auto }` below is
   equally specific and comes later — it was resetting the height straight back. */
.hsn-fig .hsn-fig__bar > svg { flex: 1 1 auto; width: 100%; height: 1.5em; }
.hsn-fig__bar .hsn-fig__lab,
.hsn-fig__bar .hsn-fig__num {
    flex: 0 0 auto; display: inline; font-size: 1em; margin: 0;
    color: var(--hsn-text); white-space: nowrap;
}
.hsn-fig__bar .hsn-fig__num { color: var(--hsn-ink); font-weight: 700; }

/* The plain div track, when there is no svg to lay out. */
.hsn-fig__bar:not(:has(svg)):not(:has(.hsn-fig__bartrack)) {
    display: block; height: 12px; background: var(--hsn-line);
    border-radius: 999px; overflow: hidden;
}
div.hsn-fig__barfill { background: var(--hsn-accent); height: 100%; border-radius: 999px; }
/* The svg rect shape. */
rect.hsn-fig__barfill, .hsn-fig__bar svg .hsn-fig__barfill { fill: var(--hsn-accent); }
.hsn-fig__bar svg text { fill: var(--hsn-text); }
.hsn-fig--warn div.hsn-fig__barfill { background: var(--hsn-warn); }
.hsn-fig--warn rect.hsn-fig__barfill { fill: var(--hsn-warn); }

.hsn-fig svg { max-width: 100%; height: auto; display: block; }
/* Wide SVG charts scroll inside the figure; the page body never does. */
.hsn-fig__scroll { overflow-x: auto; }

/* ── the comparison table ─────────────────────────────────────────────── */
/*
 * Its own rules rather than .hsn-table's. That class styles the tables the
 * ANSWER pipeline emits into article prose — hairline borders on a white page,
 * sized to sit between paragraphs. Inside a figure the table is the figure: it
 * needs the frame's padding, the heading above it, and a header row that reads
 * as part of the same object as the filled blocks on the rest of the page.
 *
 * The horizontal scroll is kept from .hsn-table and matters for the same reason:
 * three columns of regime text will not fit a phone, and the PAGE must never
 * scroll sideways to accommodate a figure.
 */
.hsn-fig__table { padding: 1.5em 1.6em; }
.hsn-fig__table > h4 { margin-bottom: .9em; }
.hsn-fig.hsn-fig--solid .hsn-fig__table table {
    border-collapse: collapse;
    width: 100%;
    font-size: .92em;
    margin: 0;
}
/* The first column asks the question and the rest answer it, so the row header
   carries the ink colour and the answers sit back a step. */
.hsn-fig.hsn-fig--solid .hsn-fig__table th,
.hsn-fig.hsn-fig--solid .hsn-fig__table td {
    padding: .7em .9em;
    text-align: left;
    vertical-align: top;
    border-bottom: 1px solid var(--hsn-line);
}
.hsn-fig.hsn-fig--solid .hsn-fig__table thead th {
    background: var(--hsn-series, var(--hsn-accent-v, var(--hsn-accent)));
    color: #fff;
    font-weight: 600;
    border-bottom: 0;
}
.hsn-fig.hsn-fig--solid .hsn-fig__table thead th:first-child { border-radius: 8px 0 0 0; }
.hsn-fig.hsn-fig--solid .hsn-fig__table thead th:last-child { border-radius: 0 8px 0 0; }
.hsn-fig.hsn-fig--solid .hsn-fig__table tbody th {
    font-weight: 600;
    color: var(--hsn-ink);
    white-space: normal;
}
.hsn-fig.hsn-fig--solid .hsn-fig__table tbody td { color: var(--hsn-text); }
/* Zebra, at a fraction of the accent so it separates rows without competing
   with the header. */
.hsn-fig.hsn-fig--solid .hsn-fig__table tbody tr:nth-child(even) { background: var(--hsn-wash); }
.hsn-fig.hsn-fig--solid .hsn-fig__table tbody tr:last-child th,
.hsn-fig.hsn-fig--solid .hsn-fig__table tbody tr:last-child td { border-bottom: 0; }

@media (max-width: 600px) {
    .hsn-fig__table { padding: 1.1em; overflow-x: auto; -webkit-overflow-scrolling: touch; }
    .hsn-fig.hsn-fig--solid .hsn-fig__table table { min-width: 420px; }
}

/* ── how a block of equal items is arranged ───────────────────────────── */
/*
 * Stamped by scripts/lib/infographic-layout.js on the FIGURE, from the row id
 * and only where the item count and length allow it. The forms were varied and
 * the arrangement was not — cards, who and flow all came out as the same column
 * of full-width slabs on every article, three templates with one silhouette.
 *
 * Each rule needs .hsn-fig--solid to match the specificity of the filled-block
 * rules it is overriding, which are declared later in this file.
 */

/* Two columns. Only ever stamped on an EVEN count of four or more, so the last
   row is never one item beside a hole. */
.hsn-fig.hsn-fig--solid.hsn-fig--grid2 .hsn-fig__cards,
.hsn-fig.hsn-fig--solid.hsn-fig--grid2 .hsn-fig__who {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1.3em;
    align-items: stretch;
}
.hsn-fig.hsn-fig--solid.hsn-fig--grid2 .hsn-fig__cards > *:not(.hsn-fig__card),
.hsn-fig.hsn-fig--solid.hsn-fig--grid2 .hsn-fig__who > *:not(.hsn-fig__row) {
    grid-column: 1 / -1;
}
/* The who block draws a hairline between stacked rows; side by side that rule
   would underline the left column and not the right. */
.hsn-fig.hsn-fig--solid.hsn-fig--grid2 .hsn-fig__row { border-bottom: 0; }

/* Across the page in one row. Two or three short items only — a fourth column
   in an 800px article is 160px, which fits about three words. */
.hsn-fig.hsn-fig--solid.hsn-fig--rail .hsn-fig__cards,
.hsn-fig.hsn-fig--solid.hsn-fig--rail .hsn-fig__who,
.hsn-fig.hsn-fig--solid.hsn-fig--rail .hsn-fig__flow {
    display: flex;
    flex-wrap: wrap;
    align-items: stretch;
    gap: 1.9em;
}
.hsn-fig.hsn-fig--solid.hsn-fig--rail .hsn-fig__cards > *:not(.hsn-fig__card),
.hsn-fig.hsn-fig--solid.hsn-fig--rail .hsn-fig__who > *:not(.hsn-fig__row),
.hsn-fig.hsn-fig--solid.hsn-fig--rail .hsn-fig__flow > *:not(.hsn-fig__step) {
    flex: 1 0 100%;
}
.hsn-fig.hsn-fig--solid.hsn-fig--rail .hsn-fig__card,
.hsn-fig.hsn-fig--solid.hsn-fig--rail .hsn-fig__row,
.hsn-fig.hsn-fig--solid.hsn-fig--rail .hsn-fig__flow > .hsn-fig__step {
    flex: 1 1 0;
    min-width: 8em;
    max-width: none;
    margin: 0;
}
.hsn-fig.hsn-fig--solid.hsn-fig--rail .hsn-fig__row { border-bottom: 0; }
/* A rail runs left to right, so the arrow between steps has to turn with it and
   move out of the bottom margin into the gap on the right. */
.hsn-fig.hsn-fig--solid.hsn-fig--rail .hsn-fig__flow > .hsn-fig__step:not(:last-child) {
    margin-bottom: 0;
}
.hsn-fig.hsn-fig--solid.hsn-fig--rail .hsn-fig__flow > .hsn-fig__step:not(:last-child)::after {
    content: "";
    top: 50%;
    bottom: auto;
    left: auto;          /* the stacked rule sets left:0; without this the box */
    right: -1.7em;       /* stretches the step's full width and the arrow hides */
    margin: 0;
    width: 1.5em;
    height: .66em;
    transform: translateY(-50%);
    clip-path: polygon(0 31%, 62% 31%, 62% 0, 100% 50%, 62% 100%, 62% 69%, 0 69%);
}

/* A ring of four, arrows clockwise. This is the one arrangement that says
   something the stacked version does not: that the fourth step leads back to
   the first. Only ever stamped on a flow of exactly four. */
.hsn-fig.hsn-fig--solid.hsn-fig--cycle .hsn-fig__flow {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 2.2em 2.6em;
    align-items: stretch;
}
/* The heading is pinned to row 1 and the four steps to rows 2 and 3 EXPLICITLY.
   Placing only steps 3 and 4 left the first two to auto-place, which put them in
   the same row the explicit ones had claimed; the browser resolved the collision
   by pushing row 2 above row 1, and the ring rendered upside down. */
.hsn-fig.hsn-fig--solid.hsn-fig--cycle .hsn-fig__flow > *:not(.hsn-fig__step) {
    grid-column: 1 / -1;
    grid-row: 1;
}
.hsn-fig.hsn-fig--solid.hsn-fig--cycle .hsn-fig__flow > .hsn-fig__step {
    width: auto;
    max-width: none;
    margin: 0;
    position: relative;
}
/* Reading order is 1 2 / 4 3, so the ring runs right, down, left and back up.
   The DOM order stays 1 2 3 4 — only the third and fourth swap cells, which
   keeps the markup honest for a screen reader following the steps in order. */
.hsn-fig.hsn-fig--solid.hsn-fig--cycle .hsn-fig__flow > .hsn-fig__step:nth-of-type(1) { grid-area: 2 / 1; }
.hsn-fig.hsn-fig--solid.hsn-fig--cycle .hsn-fig__flow > .hsn-fig__step:nth-of-type(2) { grid-area: 2 / 2; }
.hsn-fig.hsn-fig--solid.hsn-fig--cycle .hsn-fig__flow > .hsn-fig__step:nth-of-type(3) { grid-area: 3 / 2; }
.hsn-fig.hsn-fig--solid.hsn-fig--cycle .hsn-fig__flow > .hsn-fig__step:nth-of-type(4) { grid-area: 3 / 1; }
/* The stacked flow puts `left: 0; right: 0` on this pseudo-element, and every
   horizontal arrow here has to beat BOTH halves of that or it renders inside the
   filled block, invisible against the fill — which is how the ring came to look
   like it had lost two of its four arrows.

   This base rule cannot do it. It ties the stacked rule on specificity (five
   classes and a pseudo-element each) and is declared earlier in the file, so the
   stacked rule wins every property they share. It is kept because it is what
   sets the properties the stacked rule does NOT set; the resets that matter are
   repeated on each :nth-of-type rule below, which carries one class more. */
.hsn-fig.hsn-fig--solid.hsn-fig--cycle .hsn-fig__flow > .hsn-fig__step::after {
    position: absolute;
    top: auto;
    right: auto;
    bottom: auto;
    left: auto;
    width: auto;
    height: auto;
    margin: 0;
    content: "";
}
/* 1 -> 2 across the top, 2 -> 3 down the right, 3 -> 4 back across, 4 -> 1 up. */
.hsn-fig.hsn-fig--solid.hsn-fig--cycle .hsn-fig__flow > .hsn-fig__step:nth-of-type(1)::after {
    /* right, centred in the 2.6em column gap: (2.6 + 1.5) / 2 */
    top: 50%; left: auto; right: -2.05em; width: 1.5em; height: .66em;
    transform: translateY(-50%);
    clip-path: polygon(0 31%, 62% 31%, 62% 0, 100% 50%, 62% 100%, 62% 69%, 0 69%);
}
.hsn-fig.hsn-fig--solid.hsn-fig--cycle .hsn-fig__flow > .hsn-fig__step:nth-of-type(2)::after {
    /* down, centred in the 2.2em row gap */
    bottom: -1.85em; left: 0; right: 0; margin-inline: auto; width: .66em; height: 1.5em;
    clip-path: polygon(31% 0, 69% 0, 69% 62%, 100% 62%, 50% 100%, 0 62%, 31% 62%);
}
.hsn-fig.hsn-fig--solid.hsn-fig--cycle .hsn-fig__flow > .hsn-fig__step:nth-of-type(3)::after {
    /* left */
    top: 50%; right: auto; left: -2.05em; width: 1.5em; height: .66em;
    transform: translateY(-50%);
    clip-path: polygon(100% 31%, 38% 31%, 38% 0, 0 50%, 38% 100%, 38% 69%, 100% 69%);
}
.hsn-fig.hsn-fig--solid.hsn-fig--cycle .hsn-fig__flow > .hsn-fig__step:nth-of-type(4)::after {
    /* up */
    top: -1.85em; left: 0; right: 0; margin-inline: auto; width: .66em; height: 1.5em;
    clip-path: polygon(31% 100%, 69% 100%, 69% 38%, 100% 38%, 50% 0, 0 38%, 31% 38%);
}

@media (max-width: 600px) {
    /* Every arrangement collapses to the stack on a phone. Two columns of
       120px, or a four-cell ring, is unreadable at that width. */
    .hsn-fig.hsn-fig--solid.hsn-fig--grid2 .hsn-fig__cards,
    .hsn-fig.hsn-fig--solid.hsn-fig--grid2 .hsn-fig__who,
    .hsn-fig.hsn-fig--solid.hsn-fig--cycle .hsn-fig__flow { grid-template-columns: 1fr; }
    .hsn-fig.hsn-fig--solid.hsn-fig--cycle .hsn-fig__flow > .hsn-fig__step { grid-area: auto; }
    /* Stacked on a phone, so every arrow points down again. */
    .hsn-fig.hsn-fig--solid.hsn-fig--cycle .hsn-fig__flow > .hsn-fig__step::after,
    .hsn-fig.hsn-fig--solid.hsn-fig--rail .hsn-fig__flow > .hsn-fig__step:not(:last-child)::after {
        top: auto; bottom: -1.9em; left: 0; right: 0; margin-inline: auto;
        width: .66em; height: 1.5em; transform: none;
        clip-path: polygon(31% 0, 69% 0, 69% 62%, 100% 62%, 50% 100%, 0 62%, 31% 62%);
    }
    .hsn-fig.hsn-fig--solid.hsn-fig--cycle .hsn-fig__flow > .hsn-fig__step:last-child::after { content: none; }
    .hsn-fig.hsn-fig--solid.hsn-fig--rail .hsn-fig__cards,
    .hsn-fig.hsn-fig--solid.hsn-fig--rail .hsn-fig__who,
    .hsn-fig.hsn-fig--solid.hsn-fig--rail .hsn-fig__flow { display: block; }
}

/* ── the figure that sits beside the prose ────────────────────────────── */
/*
 * Stamped by scripts/news-infographics.js on ONE narrow figure per article, and
 * only on shapes that lose nothing at half width — a donut, a two-chip stat
 * pair, a short flow. A timeline runs across the page and a bar chart needs room
 * for its labels; neither is ever floated.
 *
 * Below 780px it goes back to full width. A float that narrow leaves a column of
 * two-word lines beside it, which is worse than the slab it was avoiding.
 */
@media (min-width: 781px) {
    .hsn-fig--side {
        float: right;
        width: 46%;
        margin: .35em 0 1.2em 1.8em;
    }
    /* A float must never bleed past its own section. Without this the next
       heading tucks itself into the gap beside the figure and the article looks
       like it lost a paragraph. */
    .hsn-fig--side + * { margin-top: 0; }
    .entry-content h2, .entry-content h3, .hsn-refs-title { clear: both; }
    /* At half width the donut's legend cannot sit beside the ring. */
    .hsn-fig--side .hsn-fig__pie { grid-template-columns: 1fr; justify-items: center; }
    .hsn-fig.hsn-fig--solid.hsn-fig--side .hsn-fig__pie .hsn-fig__key { align-items: flex-start; }
    .hsn-fig--side .hsn-fig__hero { padding: 1.3em 1.2em; }

    /* Half width is a narrow CONTAINER inside a wide viewport, which no
       max-width media query can see. Everything the 600px breakpoint does for a
       phone has to be repeated here, or a floated chart keeps its full-size
       track and type and bursts its own box. */
    .hsn-fig--side .hsn-fig__cols,
    .hsn-fig--side .hsn-fig__chart,
    .hsn-fig--side .hsn-fig__cards,
    .hsn-fig--side .hsn-fig__stats,
    .hsn-fig--side .hsn-fig__who,
    .hsn-fig--side .hsn-fig__flow,
    .hsn-fig--side .hsn-fig__pie { padding: 1.2em 1.1em; }
    .hsn-fig.hsn-fig--solid.hsn-fig--side .hsn-fig__coltrack { height: 92px; }
    .hsn-fig.hsn-fig--solid.hsn-fig--side .hsn-fig__col > span.hsn-fig__num { font-size: .95em; }
    .hsn-fig.hsn-fig--solid.hsn-fig--side .hsn-fig__col > span.hsn-fig__lab { font-size: .72em; }
    .hsn-fig.hsn-fig--solid.hsn-fig--side .hsn-fig__bar > .hsn-fig__lab { flex-basis: 6em; }
    /* A hero headline set for a full-width panel is three words a line here. */
    .hsn-fig--side .hsn-fig__headline { font-size: 1.25em; }
    /* Half width has room for one column, so a floated figure keeps the stack
       whatever arrangement it was stamped with. */
    .hsn-fig.hsn-fig--solid.hsn-fig--side.hsn-fig--grid2 .hsn-fig__cards,
    .hsn-fig.hsn-fig--solid.hsn-fig--side.hsn-fig--grid2 .hsn-fig__who,
    .hsn-fig.hsn-fig--solid.hsn-fig--side.hsn-fig--cycle .hsn-fig__flow { grid-template-columns: 1fr; }
    .hsn-fig.hsn-fig--solid.hsn-fig--side.hsn-fig--rail .hsn-fig__cards,
    .hsn-fig.hsn-fig--solid.hsn-fig--side.hsn-fig--rail .hsn-fig__who,
    .hsn-fig.hsn-fig--solid.hsn-fig--side.hsn-fig--rail .hsn-fig__flow { display: block; }
}

/* ── donut ────────────────────────────────────────────────────────────── */
/*
 * Drawn by scripts/lib/infographic-chart.js, never by the model. The arc
 * geometry is arithmetic — a model asked to compute it produced wedges that
 * disagreed with their own labels — and a figure may carry no CSS of its own, so
 * the slices arrive as bare <path> elements and take their colour from the
 * palette slot stamped on each one.
 *
 * Offered only when the values genuinely partition a whole. Three duty rates of
 * 50%, 25% and 10% add up to nothing; a donut of them invents a total that does
 * not exist, so partsOfWhole() refuses and the series is drawn as bars.
 */
.hsn-fig__pie {
    padding: 1.5em 1.6em;
    display: grid;
    grid-template-columns: 9.5em minmax(0, 1fr);
    gap: .3em 1.5em;
    align-items: center;
}
.hsn-fig__pie > h4 { grid-column: 1 / -1; }
.hsn-fig__pie > svg { width: 9.5em; max-width: 100%; height: auto; }
.hsn-fig__slice {
    fill: var(--hsn-series, var(--hsn-accent-v, var(--hsn-accent)));
    stroke: #fff;          /* a hairline between wedges, so touching slots read apart */
    stroke-width: .8;
}
/* Beside the donut the legend is a column, not the centred row it is elsewhere.
   Specificity has to match the .hsn-fig--solid rule it is overriding. */
.hsn-fig.hsn-fig--solid .hsn-fig__pie .hsn-fig__key {
    flex-direction: column;
    justify-content: center;
    align-items: flex-start;
    padding: 0;
    gap: .5em;
}

@media (max-width: 600px) {
    .hsn-fig__pie { grid-template-columns: 1fr; justify-items: center; padding: 1.1em; }
    .hsn-fig.hsn-fig--solid .hsn-fig__pie .hsn-fig__key { align-items: flex-start; }
}

@media (max-width: 600px) {
    .hsn-fig__hero { padding: 1.4em 1.1em; }
    .hsn-fig__headline { font-size: 1.4em; }
    .hsn-fig__cards, .hsn-fig__who, .hsn-fig__flow, .hsn-fig__time,
    .hsn-fig__chart { padding: 1.1em; }
}

/* The site has no dark mode today; if the theme ever adds one this keeps the
   figure legible rather than white-on-white. */
@media (prefers-color-scheme: dark) {
    .hsn-fig[data-theme-aware] { background: #14161d; }
}


/* ── filled blocks: the flow, the stat row, the timeline ──────────────────
 *
 * These three were outlined white cards with an icon chip on the left and a
 * sentence beside it — a styled list, which is what "the graphics look too
 * texty" meant. The shape they are now is taken from the reference the client
 * pointed at, and its grammar is narrow enough to state:
 *
 *   - a SOLID filled block of colour, not an outline
 *   - NO icon
 *   - centred, two lines: a bold primary and a muted secondary, 3-6 words each
 *   - colour is the grouping. When two blocks share a colour they are the same
 *     phase of the same process, and a legend under the figure says which
 *   - the timeline runs ACROSS, not down
 *
 * EVERY RULE BELOW IS SCOPED TO .hsn-fig.hsn-fig--solid, AND THAT MATTERS.
 *
 * The doubled .hsn-fig is not redundant — do not "simplify" it away. The legacy
 * variant rules at the foot of this file (.hsn-fig--v2 .hsn-fig__card,
 * .hsn-fig--v4 .hsn-fig__stat, ...) are one class + one class, exactly the same
 * specificity as a bare .hsn-fig--solid .hsn-fig__card, and they are declared
 * LATER — so they won. A --v2 card kept its near-transparent legacy background
 * while this block's `color: #fff` still applied, and the text rendered white on
 * white. Two classes here beats one variant class there, whatever gets added to
 * the variants section later.
 *
 * This stylesheet ships once for all 528 articles, so restyling `.hsn-fig__card`
 * and `.hsn-fig__stat` in place silently repainted the whole archive the moment
 * the file was copied to the server — including the ~520 figures whose markup
 * was written for the outlined-card look, with an icon in every block and a
 * sentence rather than two short lines. Those turned into a wall of solid
 * colour with no internal hierarchy. Nothing had regenerated; one CSS file had
 * changed under them.
 *
 * The marker is stamped by news-infographics.js on figures it has just
 * generated, alongside the --v1..--v4 variant. So a figure gets this treatment
 * only once its markup has actually been written for it, and the archive keeps
 * the look it was built with until it is regenerated. The rules above this
 * block are the legacy ones and must stay intact for exactly that reason.
 */

/* The filled block itself, shared by the flow step and the stat chip. Colour
   comes from the series slot when the model is grouping, and falls back to the
   article's variant accent when it is not — so a figure with no grouping still
   varies article to article the way it always did. */
.hsn-fig.hsn-fig--solid .hsn-fig__step,
.hsn-fig.hsn-fig--solid .hsn-fig__stat,
.hsn-fig.hsn-fig--solid .hsn-fig__card,
.hsn-fig.hsn-fig--solid .hsn-fig__row {
    /* display is reset, not inherited. The legacy rules above lay a card and a
       row out as `display: flex` — icon chip on the left, sentence beside it —
       and they have to stay for the ~520 archive figures written that way. Left
       alone, that flex leaked in here and put the block's two lines side by
       side instead of stacking them, so a filled card read differently from a
       filled flow step on the same page. */
    display: block;
    background: var(--hsn-series, var(--hsn-accent-v, var(--hsn-accent)));
    border: 0;
    border-radius: 10px;
    padding: 1.05em 1.2em;
    text-align: center;
    color: #fff;
}
/* THE ARROW IS DRAWN, NOT TYPED.
 *
 * It was a "\2193" glyph. Enlarging it and giving it the block's colour helped,
 * but a text arrow is a hairline stem in most faces and font-weight does not
 * thicken it — the theme's serif renders 700 identically to 400 for U+2193. A
 * clipped box is a solid shape whose weight this file controls, needs no glyph
 * coverage from whatever font the theme loads, and cannot be re-rendered as a
 * colour emoji on a platform that decides U+2193 is one.
 *
 * Four separate shapes rather than one rotated: rotation would compose with the
 * translate() that centres each arrow, and the two interact differently per
 * direction. Four polygons are longer to read and impossible to get wrong.
 */
.hsn-fig.hsn-fig--solid .hsn-fig__flow .hsn-fig__step::after {
    content: "";
    background: var(--hsn-series, var(--hsn-accent-v, var(--hsn-accent)));
    opacity: 1;
    /* em is the STEP's here, since the pseudo-element keeps its font-size. */
    font-size: 1em;
}
/* THE GAP BETWEEN TWO BLOCKS MUST EXCEED THE PADDING INSIDE ONE.
 *
 * Measured on a published article: stacked cards sat 13px apart while each card
 * carried 14.7px of padding. The space between two blocks was smaller than the
 * space within one, so the eye grouped them as a single slab with lines through
 * it rather than as three separate rules — the proximity is doing the opposite
 * of what the layout intends.
 *
 * The filled block above is padded 1.05em, so every stacked gap here clears it.
 * Solid-scoped, like the rest of this section, so the ~520 archive figures keep
 * the spacing they were built with.
 */
.hsn-fig.hsn-fig--solid .hsn-fig__cards { display: grid; gap: 1.4em; }
/* The legacy who block separates rows with a hairline and no gap at all. Under
   --solid the row is a filled block and the border is removed, which left the
   rows touching edge to edge. */
.hsn-fig.hsn-fig--solid .hsn-fig__who { display: grid; gap: 1.4em; }
.hsn-fig.hsn-fig--solid .hsn-fig__cards > *:not(.hsn-fig__card),
.hsn-fig.hsn-fig--solid .hsn-fig__who > *:not(.hsn-fig__row) { grid-column: 1 / -1; }

/* A ban, a suspension, a penalty keeps its own colour whatever the grouping —
   it must never read as routine. Written with the block class AND the modifier
   (0,4,0) so it outranks the general fill above (0,3,0) no matter which order
   the two end up in. White on #C2410C is 5.18:1. */
.hsn-fig.hsn-fig--solid .hsn-fig__card.hsn-fig--warn,
.hsn-fig.hsn-fig--solid .hsn-fig__row.hsn-fig--warn,
.hsn-fig.hsn-fig--solid .hsn-fig__step.hsn-fig--warn,
.hsn-fig.hsn-fig--solid .hsn-fig__stat.hsn-fig--warn {
    background: var(--hsn-warn);
}

/* Theme rules paint every <p> and <span> inside the content wrapper, so the
   block's own text has to be claimed explicitly or it renders dark on dark. */
.hsn-fig.hsn-fig--solid .hsn-fig__step *,
.hsn-fig.hsn-fig--solid .hsn-fig__stat *,
.hsn-fig.hsn-fig--solid .hsn-fig__card *,
.hsn-fig.hsn-fig--solid .hsn-fig__row * { color: #fff; }
.hsn-fig.hsn-fig--solid .hsn-fig__step strong,
.hsn-fig.hsn-fig--solid .hsn-fig__stat strong,
.hsn-fig.hsn-fig--solid .hsn-fig__card strong,
.hsn-fig.hsn-fig--solid .hsn-fig__row strong,
.hsn-fig.hsn-fig--solid .hsn-fig__stat > span.hsn-fig__num {
    display: block;
    font-size: 1.02em;
    font-weight: 700;
    line-height: 1.3;
    color: #fff;
}
/* The second line. Tinted rather than a different colour: it has to read as the
   same block, quieter. */
.hsn-fig.hsn-fig--solid .hsn-fig__step > p,
.hsn-fig.hsn-fig--solid .hsn-fig__step > span,
.hsn-fig.hsn-fig--solid .hsn-fig__card > p,
.hsn-fig.hsn-fig--solid .hsn-fig__card > span,
.hsn-fig.hsn-fig--solid .hsn-fig__row > p,
.hsn-fig.hsn-fig--solid .hsn-fig__row > span,
.hsn-fig.hsn-fig--solid .hsn-fig__stat > span.hsn-fig__lab {
    display: block;
    margin: .2em 0 0;
    font-size: .84em;
    line-height: 1.35;
    color: #fff;
}
/* An icon inside a filled block competes with the text and the reference has
   none. Legacy figures still carry one, so it is quietened rather than hidden —
   hiding it would drop content some article's meaning rests on. */
.hsn-fig.hsn-fig--solid .hsn-fig__step .hsn-fig__icon,
.hsn-fig.hsn-fig--solid .hsn-fig__stat .hsn-fig__icon,
.hsn-fig.hsn-fig--solid .hsn-fig__card .hsn-fig__icon,
.hsn-fig.hsn-fig--solid .hsn-fig__row .hsn-fig__icon {
    background: rgba(255, 255, 255, .16);
    color: #fff;
    width: 1.6em;
    height: 1.6em;
    margin: 0 auto .5em;
}
/* The flow runs DOWN one centred column with an arrow between steps. It used to
   be a 2-3 column grid with a numbered badge, which read as a card deck: at
   three columns the reader has to work out that it is even a sequence. One
   column with an arrow cannot be misread. */
.hsn-fig.hsn-fig--solid .hsn-fig__flow {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    counter-reset: none;
}
.hsn-fig.hsn-fig--solid .hsn-fig__flow > *:not(.hsn-fig__step) { width: 100%; }
.hsn-fig.hsn-fig--solid .hsn-fig__flow > .hsn-fig__step {
    width: 100%;
    max-width: 360px;
    margin: 0 auto;
    display: block;
}
/* The number badge goes with the grid: a single column with arrows already
   says "in this order", and the badge was the loudest thing in the block. */
.hsn-fig.hsn-fig--solid .hsn-fig__step::before { content: none; }
/* The arrow sits in the GAP between two blocks, on the figure's own
   background. As a plain block-level ::after it rendered INSIDE the filled
   step, as a white chevron on the fill — so it is taken out of flow and the
   room for it is made with the step's own margin. */
.hsn-fig.hsn-fig--solid .hsn-fig__flow > .hsn-fig__step { position: relative; }
.hsn-fig.hsn-fig--solid .hsn-fig__flow > .hsn-fig__step:not(:last-child) { margin-bottom: 2.3em; }
/* The arrow is the only thing in a flow that says the blocks are a SEQUENCE, and
   at 1.05em in 60%-opacity body grey it was the faintest mark on a figure built
   out of solid colour — a reader saw four boxes and had to infer the order.
   It now takes the colour of the block it leads out of, so the connector reads
   as part of the same object, at a size that survives being glanced at.
   Offsets are in the ARROW's own em, which is 1.7x the step's, so a -0.85em here
   is ~1.45em of the step and stays inside the 2.3em margin below it. */
.hsn-fig.hsn-fig--solid .hsn-fig__flow > .hsn-fig__step:not(:last-child)::after {
    content: "";
    position: absolute;
    /* centred in the 2.3em margin below: (2.3 + 1.5) / 2 */
    bottom: -1.9em;
    left: 0;
    right: 0;
    margin-inline: auto;
    width: .66em;
    height: 1.5em;
    clip-path: polygon(31% 0, 69% 0, 69% 62%, 100% 62%, 50% 100%, 0 62%, 31% 62%);
}
/* The stat row: filled chips across, not a bordered grid with hairline gaps. */
.hsn-fig.hsn-fig--solid .hsn-fig__stats {
    display: flex;
    flex-wrap: wrap;
    gap: 1.05em;
    background: none;
    padding: 1.5em 1.6em;
}
.hsn-fig.hsn-fig--solid .hsn-fig__stats > *:not(.hsn-fig__stat) { flex: 1 0 100%; background: none; padding: 0; }
.hsn-fig.hsn-fig--solid .hsn-fig__stats > .hsn-fig__stat { flex: 1 1 150px; }
.hsn-fig.hsn-fig--solid .hsn-fig__stats > .hsn-fig__stat > span.hsn-fig__num { font-size: 1.15em; }
/* The timeline runs ACROSS: date above the dot, label below it. The old
   .hsn-fig__time list runs down a left rule and is left in place for the
   figures already written against it. */
.hsn-fig.hsn-fig--solid .hsn-fig__axis {
    display: flex;
    /* wrap, or the heading's 100% basis takes the whole line and shoves every
       dated point off the right edge instead of onto the next row. */
    flex-wrap: wrap;
    align-items: flex-start;
    gap: .4em;
    padding: 1.6em 1.6em 1.4em;
}
.hsn-fig.hsn-fig--solid .hsn-fig__axis > *:not(.hsn-fig__ev) { flex: 1 0 100%; margin-bottom: .6em; }
.hsn-fig.hsn-fig--solid .hsn-fig__axis > .hsn-fig__ev {
    flex: 1 1 0;
    min-width: 92px;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: .1em;
    padding: 0;
    margin: 0;
    border: 0;
    position: relative;
}
/* The date sits ABOVE the dot, the label below it. order:-1 lifts it past the
   ::before dot, which is a flex item too.
   The fixed height and nowrap are still needed, but for a different reason than
   before: the dot's alignment to its own rule is now guaranteed by the paint,
   and this is what keeps every COLUMN's dot level with its neighbours' — a date
   that wrapped to two lines would push its own dot below the rest of the row. */
.hsn-fig.hsn-fig--solid .hsn-fig__axis > .hsn-fig__ev > span.hsn-fig__evdate {
    order: -1;
    font-weight: 700;
    font-size: .95em;
    color: var(--hsn-ink);
    height: 22px;
    line-height: 22px;
    margin-bottom: 8px;
    white-space: nowrap;
}
/* The dot AND the rule it sits on are painted into ONE box, as two background
   layers both centred on that box's own middle. They are therefore aligned by
   construction and there is no offset to get wrong.
   
   The first version positioned the rule absolutely at a `top` worked out by
   hand — 22px date + 8px margin + half the 11px dot = 35px — and the dot came
   out a pixel low, because the column is a flex box with `gap: .1em` and that
   1.4px was not in the sum. Any of those four numbers changing broke it again.
   Nothing here reads any of them.
   
   The radial layer is listed first so the dot paints over the rule. The hard
   98%/100% stop keeps the circle's edge clean. */
.hsn-fig.hsn-fig--solid .hsn-fig__axis > .hsn-fig__ev::before {
    content: "";
    /* The old vertical .hsn-fig__time list styles `.hsn-fig__ev::before` as an
       absolutely-placed 10px dot at top:.45em; left:-6px. That rule is still
       live for the figures that use it, and it cascades into this one for every
       property this one does not set — which put the dot on top of the date.
       Reset what is inherited rather than reaching for !important. */
    position: static;
    top: auto;
    left: auto;
    border-radius: 0;
    width: 100%;
    height: 11px;
    margin-bottom: .55em;
    background:
        radial-gradient(circle 5.5px at 50% 50%,
            var(--hsn-series, var(--hsn-accent-v, var(--hsn-accent))) 98%,
            transparent 100%) 0 0 / 100% 100% no-repeat,
        linear-gradient(var(--hsn-line), var(--hsn-line)) 0 50% / 100% 2px no-repeat;
}
/* The rule stops at the outer dots rather than running off the ends.
   NOT :first-child / :last-child — the figure's <h4> is the first child of
   .hsn-fig__axis, so :first-child never matches an event at all and the rule
   ran off the left edge. "An event with no event before it" is the actual
   condition, and it holds whether or not the heading is there. */
.hsn-fig.hsn-fig--solid .hsn-fig__axis > .hsn-fig__ev:not(.hsn-fig__ev ~ .hsn-fig__ev)::before {
    background:
        radial-gradient(circle 5.5px at 50% 50%,
            var(--hsn-series, var(--hsn-accent-v, var(--hsn-accent))) 98%,
            transparent 100%) 0 0 / 100% 100% no-repeat,
        linear-gradient(var(--hsn-line), var(--hsn-line)) 100% 50% / 50% 2px no-repeat;
}
.hsn-fig.hsn-fig--solid .hsn-fig__axis > .hsn-fig__ev:not(:has(~ .hsn-fig__ev))::before {
    background:
        radial-gradient(circle 5.5px at 50% 50%,
            var(--hsn-series, var(--hsn-accent-v, var(--hsn-accent))) 98%,
            transparent 100%) 0 0 / 100% 100% no-repeat,
        linear-gradient(var(--hsn-line), var(--hsn-line)) 0 50% / 50% 2px no-repeat;
}
/* A lone point has nothing to connect to. */
.hsn-fig.hsn-fig--solid .hsn-fig__axis > .hsn-fig__ev:not(.hsn-fig__ev ~ .hsn-fig__ev):not(:has(~ .hsn-fig__ev))::before {
    background: radial-gradient(circle 5.5px at 50% 50%,
        var(--hsn-series, var(--hsn-accent-v, var(--hsn-accent))) 98%,
        transparent 100%) 0 0 / 100% 100% no-repeat;
}
.hsn-fig.hsn-fig--solid .hsn-fig__axis > .hsn-fig__ev > span.hsn-fig__evlab {
    font-size: .82em;
    line-height: 1.35;
    color: var(--hsn-ink);
}
.hsn-fig.hsn-fig--solid .hsn-fig__axis > .hsn-fig__ev > span.hsn-fig__evsub {
    font-size: .78em;
    line-height: 1.35;
    color: var(--hsn-text);
}
/* The legend. Present ONLY when colour is carrying a grouping — two steps in
   one colour mean one phase, and without this the reader has to guess what the
   phase is. Identity is never colour alone. */
.hsn-fig.hsn-fig--solid .hsn-fig__key {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: .4em 1.4em;
    padding: 0 1.6em 1.5em;
    font-size: .82em;
    color: var(--hsn-text);
}
.hsn-fig.hsn-fig--solid .hsn-fig__keyitem { display: inline-flex; align-items: center; gap: .45em; }
.hsn-fig.hsn-fig--solid .hsn-fig__keyitem::before {
    content: "";
    width: 11px;
    height: 11px;
    border-radius: 3px;
    background: var(--hsn-series, var(--hsn-accent-v, var(--hsn-accent)));
}
@media (max-width: 600px) {
    .hsn-fig__axis { padding: 1.2em 1em; }
    .hsn-fig.hsn-fig--solid .hsn-fig__axis > .hsn-fig__ev { min-width: 76px; }
}
/* ── charts: two orientations, one mechanism ──────────────────────────────
 *
 * The figures used to be almost all text — seven forms and only one of them
 * drew anything, so an "infographic" was a styled list with an icon beside it.
 * These two are real charts, and the prompt now has to reach for one whenever
 * the section carries comparable numbers.
 *
 * `style` is stripped from generated markup, so a fill cannot carry its own
 * width. `data-v` does, quantised to 5% — twenty-one custom-property rules
 * serve BOTH orientations, since horizontal reads it as a width and vertical
 * as a height. The sanitiser snaps whatever the model writes to the nearest
 * step and clamps it, so a bar always renders at a sane size even when the
 * model does the arithmetic badly.
 *
 * Horizontal (.hsn-fig__bar) is for long category labels — countries, product
 * groups, agencies. Vertical (.hsn-fig__col) is for a short axis, usually time
 * or two or three states of the same measure.
 *
 * The <svg><rect> bar above is untouched: ~500 already-published figures were
 * generated with it and must keep rendering.
 */

.hsn-fig.hsn-fig--solid [data-v="0"] { --hsn-v: 0%; }
.hsn-fig.hsn-fig--solid [data-v="5"] { --hsn-v: 5%; }
.hsn-fig.hsn-fig--solid [data-v="10"] { --hsn-v: 10%; }
.hsn-fig.hsn-fig--solid [data-v="15"] { --hsn-v: 15%; }
.hsn-fig.hsn-fig--solid [data-v="20"] { --hsn-v: 20%; }
.hsn-fig.hsn-fig--solid [data-v="25"] { --hsn-v: 25%; }
.hsn-fig.hsn-fig--solid [data-v="30"] { --hsn-v: 30%; }
.hsn-fig.hsn-fig--solid [data-v="35"] { --hsn-v: 35%; }
.hsn-fig.hsn-fig--solid [data-v="40"] { --hsn-v: 40%; }
.hsn-fig.hsn-fig--solid [data-v="45"] { --hsn-v: 45%; }
.hsn-fig.hsn-fig--solid [data-v="50"] { --hsn-v: 50%; }
.hsn-fig.hsn-fig--solid [data-v="55"] { --hsn-v: 55%; }
.hsn-fig.hsn-fig--solid [data-v="60"] { --hsn-v: 60%; }
.hsn-fig.hsn-fig--solid [data-v="65"] { --hsn-v: 65%; }
.hsn-fig.hsn-fig--solid [data-v="70"] { --hsn-v: 70%; }
.hsn-fig.hsn-fig--solid [data-v="75"] { --hsn-v: 75%; }
.hsn-fig.hsn-fig--solid [data-v="80"] { --hsn-v: 80%; }
.hsn-fig.hsn-fig--solid [data-v="85"] { --hsn-v: 85%; }
.hsn-fig.hsn-fig--solid [data-v="90"] { --hsn-v: 90%; }
.hsn-fig.hsn-fig--solid [data-v="95"] { --hsn-v: 95%; }
.hsn-fig.hsn-fig--solid [data-v="100"] { --hsn-v: 100%; }
/* Categorical slots. Four, not eight: this is a 700px figure inside an article,
   and the fifth series is always better folded into "Other". The hues are the
   stylesheet's own variant accents, so a chart still reads as part of the site
   rather than as a pasted-in dashboard.

   THESE FILLS CARRY WHITE TEXT, which is a stricter job than the palette was
   first picked for. The original set came straight from the chart-mark palette,
   where the requirement is only >= 3:1 against the light SURFACE — fine for a bar,
   not for a panel with words on it. #0891B2 cyan gave white text 3.68:1 and the
   second line, then at 82% opacity, fell to 3.58. Every fill below now clears
   4.5:1 against white at FULL opacity (violet 4.52, green 5.02, blue 5.93, amber
   5.02, warn 5.18), which is why the second line has no opacity any more and
   takes its hierarchy from size and weight instead. Any alpha at all would put
   the violet back under the line.

   Still validated as a categorical palette against the light surface (dataviz
   validate_palette.js, adjacent pairlist): chroma floor, CVD dE 17.8, normal-vision
   dE 18.8, all four >= 3:1 contrast. Across ALL pairs the
   green/amber pair sits at 6.8 (the 6-8 band), which is legal only with
   secondary encoding — hence the prompt's hard rule that EVERY bar and column
   carries its own visible text label. Identity is never colour alone.

   Assign in fixed order and never cycle. The colour follows the thing, not its
   rank, so a chart that drops a row must not repaint the rows that remain. */
.hsn-fig.hsn-fig--solid {
    --hsn-s1: #7A5AF8;   /* violet — the house accent */
    --hsn-s2: #15803D;   /* green  */
    --hsn-s3: #0369A1;   /* blue   */
    --hsn-s4: #B45309;   /* amber  */
}
.hsn-fig.hsn-fig--solid [data-series="1"] { --hsn-series: var(--hsn-s1); }
.hsn-fig.hsn-fig--solid [data-series="2"] { --hsn-series: var(--hsn-s2); }
.hsn-fig.hsn-fig--solid [data-series="3"] { --hsn-series: var(--hsn-s3); }
.hsn-fig.hsn-fig--solid [data-series="4"] { --hsn-series: var(--hsn-s4); }
/* Horizontal. The label column is capped so bars start at the same x and stay
   comparable; a long country name wraps rather than shoving the axis right. */
.hsn-fig.hsn-fig--solid .hsn-fig__bar > .hsn-fig__bartrack {
    flex: 1 1 auto;
    height: 1.05em;
    background: var(--hsn-line);
    border-radius: 999px;
    overflow: hidden;
}
.hsn-fig.hsn-fig--solid .hsn-fig__bar > .hsn-fig__lab {
    flex: 0 0 8.5em;
    white-space: normal;
    text-align: right;
}
span.hsn-fig__barfill {
    display: block;
    height: 100%;
    width: var(--hsn-v, 100%);
    /* 4px on the data end only: the baseline end stays square so the bar reads
       as anchored to zero rather than floating. */
    border-radius: 0 4px 4px 0;
    background: var(--hsn-series, var(--hsn-accent-v, var(--hsn-accent)));
}
/* Vertical. align-items:flex-end puts every column on one baseline whatever
   its fill height; the track is what holds that baseline steady. */
.hsn-fig.hsn-fig--solid .hsn-fig__cols {
    padding: 1.5em 1.6em;
    display: flex;
    align-items: flex-end;
    flex-wrap: wrap;
    gap: .7em;
}
.hsn-fig.hsn-fig--solid .hsn-fig__cols > *:not(.hsn-fig__col) { flex: 1 0 100%; }
.hsn-fig.hsn-fig--solid .hsn-fig__col {
    flex: 1 1 0;
    min-width: 54px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .45em;
    text-align: center;
}
.hsn-fig.hsn-fig--solid .hsn-fig__coltrack {
    width: 100%;
    height: 130px;
    display: flex;
    align-items: flex-end;
    border-bottom: 2px solid var(--hsn-line);
}
.hsn-fig.hsn-fig--solid .hsn-fig__colfill {
    /* Capped, not full-bleed. A two-column chart in an 800px article rendered
       two slabs the width of the page — the eye reads that as a block of
       colour, not as a measurement. */
    width: 100%;
    max-width: 96px;
    margin: 0 auto;
    height: var(--hsn-v, 0%);
    min-height: 3px;
    border-radius: 4px 4px 0 0;
    background: var(--hsn-series, var(--hsn-accent-v, var(--hsn-accent)));
}
/* The stat grid sizes .hsn-fig__num for a hero number; inside a column it is a
   data label sitting on top of a 130px bar. */
/* A chart's value is TEXT and wears the ink token, never the colour of the bar
   beside it — a purple "1%" reads as a fourth thing to decode. The `span`
   qualifier is what makes these outrank the variant block's blanket
   `.hsn-fig__num { color: var(--hsn-accent-v) }`, which is declared later.
   The coloured mark next to the number is what carries identity. */
.hsn-fig.hsn-fig--solid .hsn-fig__col > span.hsn-fig__num {
    font-size: 1.05em;
    font-weight: 700;
    color: var(--hsn-ink);
    order: -1;
}
.hsn-fig.hsn-fig--solid .hsn-fig__col > span.hsn-fig__lab {
    margin-top: 0;
    font-size: .78em;
    color: var(--hsn-text);
}
.hsn-fig.hsn-fig--solid .hsn-fig__bar > span.hsn-fig__num { color: var(--hsn-ink); }
.hsn-fig.hsn-fig--solid .hsn-fig__bar > span.hsn-fig__lab { color: var(--hsn-text); }
@media (max-width: 600px) {
    .hsn-fig__cols { padding: 1.1em; }
    .hsn-fig.hsn-fig--solid .hsn-fig__coltrack { height: 96px; }
    .hsn-fig.hsn-fig--solid .hsn-fig__bar > .hsn-fig__lab { flex-basis: 6em; }
}


/* ── figure variants ──────────────────────────────────────────────────────
 *
 * Same markup, four presentations. Before these, every article on the index
 * and every figure inside an article looked identical: one dark hero, one
 * accent, one card style, 507 times. A news section is supposed to look like
 * many hands made it.
 *
 * The importer stamps --v1..--v4 on the figure from the row id, so the choice
 * is deterministic and is never a per-country or per-topic branch in the
 * prompt. Each variant only re-paints and re-flows what is already there —
 * no variant may hide content, or the figure would say different things to
 * different readers.
 *
 * --hsn-accent-v is the per-variant accent; the rules below consume it so a
 * variant needs one declaration, not a rewrite of every accented element.
 */

.hsn-fig--v1 { --hsn-accent-v: var(--hsn-accent); }                 /* house purple */
.hsn-fig--v2 { --hsn-accent-v: #0E7490; }                           /* teal */
.hsn-fig--v3 { --hsn-accent-v: #B45309; }                           /* amber */
.hsn-fig--v4 { --hsn-accent-v: #15803D; }                           /* green */

.hsn-fig[class*="hsn-fig--v"] .hsn-fig__num,
.hsn-fig[class*="hsn-fig--v"] .hsn-fig__icon { color: var(--hsn-accent-v); }
/* The bar is the one accented thing the variant palette was missing: a v3 figure
   painted its numbers amber and its bars house purple. */
.hsn-fig[class*="hsn-fig--v"] rect.hsn-fig__barfill { fill: var(--hsn-accent-v); }
.hsn-fig[class*="hsn-fig--v"] div.hsn-fig__barfill,
.hsn-fig[class*="hsn-fig--v"] span.hsn-fig__barfill {
    background: var(--hsn-series, var(--hsn-accent-v));
}
.hsn-fig[class*="hsn-fig--v"] .hsn-fig__card { border-left-color: var(--hsn-accent-v); }
.hsn-fig[class*="hsn-fig--v"] .hsn-fig__who { background: color-mix(in srgb, var(--hsn-accent-v) 7%, transparent); }
/* --warn keeps its own colour in every variant: a ban must not read as routine. */
.hsn-fig[class*="hsn-fig--v"] .hsn-fig__card.hsn-fig--warn { border-left-color: var(--hsn-warn); }
.hsn-fig[class*="hsn-fig--v"] .hsn-fig__icon { background: color-mix(in srgb, var(--hsn-accent-v) 10%, transparent); }
.hsn-fig[class*="hsn-fig--v"] .hsn-fig--warn > .hsn-fig__icon { color: var(--hsn-warn); background: rgba(194, 65, 12, .10); }

/* v2 — light hero with a rule instead of a dark slab. */
.hsn-fig--v2 .hsn-fig__hero {
    background: #fff; color: var(--hsn-ink);
    border-bottom: 3px solid var(--hsn-accent-v);
    padding-bottom: 1.4em;
}
.hsn-fig.hsn-fig--v2 .hsn-fig__headline { color: var(--hsn-ink); font-weight: 700; }
.hsn-fig--v2 .hsn-fig__kicker { color: var(--hsn-accent-v); opacity: 1; font-weight: 700; }
.hsn-fig--v2 .hsn-fig__stand { color: var(--hsn-text); opacity: 1; }
.hsn-fig--v2 .hsn-fig__hero .hsn-fig__icon { background: color-mix(in srgb, var(--hsn-accent-v) 10%, transparent); color: var(--hsn-accent-v); }
.hsn-fig--v2 .hsn-fig__card { border-left-width: 1px; background: rgba(24, 29, 39, .02); }

/* v3 — accent hero, stats stacked in a single column, flat cards. */
.hsn-fig--v3 .hsn-fig__hero { background: var(--hsn-accent-v); }
.hsn-fig--v3 .hsn-fig__stat { flex-basis: 100%; display: flex; align-items: baseline; gap: .8em; flex-wrap: wrap; }
.hsn-fig--v3 .hsn-fig__num { font-size: 1.7em; }
.hsn-fig--v3 .hsn-fig__lab { margin-top: 0; }
.hsn-fig--v3 .hsn-fig__card {
    border: 0; border-left: 0; border-radius: 0; padding: .8em 0;
    border-bottom: 1px solid var(--hsn-line);
}
.hsn-fig--v3 .hsn-fig__card:last-child { border-bottom: 0; }

/* v4 — squared off, serif headline, filled cards. */
.hsn-fig--v4 { border-radius: 0; }
.hsn-fig--v4 .hsn-fig__hero { border-left: 6px solid var(--hsn-accent-v); }
.hsn-fig--v4 .hsn-fig__stat { background: rgba(24, 29, 39, .02); }
.hsn-fig--v4 .hsn-fig__card {
    border: 0; border-radius: 0;
    background: color-mix(in srgb, var(--hsn-accent-v) 6%, transparent);
    border-left: 3px solid var(--hsn-accent-v);
}
.hsn-fig.hsn-fig--v4 .hsn-fig__headline { font-family: Georgia, "Times New Roman", serif; font-weight: 700; }
.hsn-fig--v4 .hsn-fig__icon { border-radius: 0; }
