/* Local styles only. Consumes custom properties from tokens.css (light Mint
 * two-scheme; feeds stay semantic teal, distinguished from mint sleep marks
 * by lightness AND shape, never color alone). Must include
 * prefers-reduced-motion rules once motion exists. No external fonts,
 * images, or imports — CSP style-src 'self'. Mobile-first single column;
 * 44x44 CSS-pixel targets; visible focus; 4.5:1 normal-text contrast. */

body {
    background: var(--background);
    color: var(--text-1);
    font-family: var(--font);
    margin: 0;
}

/* === ui-flow structural (owned by ui-flow task) ===
 * Structure and accessibility only: box model, state hiding, the visually-
 * hidden and skip-link recipes, focus visibility, target size, and the
 * reduced-motion guard. No colour, spacing, or layout design — those belong
 * to the content-seo and charts blocks appended after this one. This block
 * defines no animation of its own: state changes are instant swaps. */

*,
*::before,
*::after {
    box-sizing: border-box;
}

/* JS toggles the hidden attribute to switch state panels, so this must beat
 * any display rule a later block sets on a panel or a mount. */
[hidden] {
    display: none !important;
}

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

.skip {
    position: absolute;
    left: 12px;
    top: -60px;
    z-index: 100;
    padding: 9px 16px;
    background: var(--elevated);
    color: var(--text-1);
    border: 1px solid var(--hairline);
    border-radius: var(--r-pill);
}

.skip:focus {
    top: 12px;
}

:focus-visible {
    outline: 2px solid var(--accent-bright);
    outline-offset: 3px;
    border-radius: 4px;
}

/* The file input is visually hidden and activated through its label, so the
 * label has to carry the input's focus ring. Relies on #csv-input being the
 * immediately preceding sibling of #csv-label. */
#csv-input:focus-visible + #csv-label {
    outline: 2px solid var(--accent-bright);
    outline-offset: 3px;
}

/* 44x44 CSS px is the Nova product target, well above WCAG 2.2's 24x24
 * minimum. inline-flex is required, not decoration: a bare <label> or <a> is
 * display:inline and would ignore min-height entirely. */
.btn,
button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    min-width: 44px;
}

progress {
    display: block;
    width: 100%;
    max-width: 32rem;
}

/* Belt and braces: this block adds no motion, but every later block inherits
 * the guard whether or not it remembers to write one. */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
        scroll-behavior: auto !important;
    }
}

/* === end ui-flow structural === */

/* ── charts.js styles (owned by charts task) ── */
/* Everything charts.js renders, and nothing else. Colour comes from
 * tokens.css through var(); the only literal hexes are the two --ch-feed-r
 * fallbacks for browsers without color-mix. The alert token never appears
 * here: it is reserved app-wide for alerts and is never a data colour. The
 * dimmest of the three text tokens never appears either — it fails 4.5:1 on
 * these surfaces, so chart text uses only --text-1 and --text-2. (Both names
 * are spelled out nowhere in this block on purpose, so a raw substring lint
 * reads the same answer as one that strips comments first.)
 *
 * Two chart-local aliases exist because the landed dark scheme collapses
 * --accent-bright and --accent-soft onto the same hex, which would make night
 * and nap identical in dark. --ch-night therefore points at --accent-bright in
 * light and --accent in dark; --ch-nap is --accent-soft in both. The hatch on
 * naps is the non-colour channel and holds in either scheme.
 *
 * .tnum is defined here rather than in the ui-flow block above: index.html
 * already uses the class on #parse-status and #methods-version but nothing
 * defined it. */

.chart-card {
    --ch-night: var(--accent-bright);
    --ch-nap: var(--accent-soft);
    --ch-feed-l: var(--feed);
    --ch-feed-r: #57AA98;

    background: var(--card);
    border: 1px solid var(--hairline);
    border-radius: var(--r-card-lg);
    padding: 16px;
    margin: 16px 0;
}

@supports (color: color-mix(in srgb, red, blue)) {
    .chart-card {
        --ch-feed-r: color-mix(in srgb, var(--feed) 75%, #FFFFFF);
    }
}

@media (prefers-color-scheme: dark) {
    .chart-card {
        --ch-night: var(--accent);
        --ch-feed-r: #A8E3D5;
    }

    @supports (color: color-mix(in srgb, red, blue)) {
        .chart-card {
            --ch-feed-r: color-mix(in srgb, var(--feed) 55%, var(--text-1));
        }
    }
}

/* The Ribbon is the hero; ui-flow marks its mount with data-chart="ribbon". */
[data-chart="ribbon"] > .chart-card {
    background: var(--elevated);
}

.tnum {
    font-variant-numeric: tabular-nums;
}

.chart-summary {
    color: var(--text-1);
    margin: 0 0 10px;
}

.chart-stat {
    color: var(--text-1);
    font-size: 1.15rem;
    font-weight: 600;
    margin: 0 0 4px;
}

.chart-stat-line {
    color: var(--text-2);
    margin: 0 0 4px;
}

svg.chart-svg {
    width: 100%;
    max-width: 100%;
    height: auto;
    display: block;
    margin: 4px 0 8px;
}

/* The dial and the orbit are square scenes: left to fill a wide card they
 * become absurd discs. The wide scenes (ribbon, shape-shift, weave) do want
 * the full width. renderChart stamps data-chart-id from the spec, which is
 * the hook. */
[data-chart-id="sleep-dial"] svg.chart-svg,
[data-chart-id="clock-orbit"] svg.chart-svg {
    max-width: 290px;
    margin-inline: auto;
}

.chart-legend {
    list-style: none;
    margin: 0 0 8px;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 6px 16px;
    color: var(--text-2);
    font-size: .84rem;
}

.chart-legend li {
    display: flex;
    align-items: center;
    gap: 7px;
}

.swatch {
    flex: none;
    width: 15px;
    height: 15px;
    border-radius: 3px;
    border: 1px solid var(--hairline);
}

.chart-insufficient {
    color: var(--text-2);
    border-left: 3px solid var(--hairline);
    padding-left: 10px;
    margin: 0 0 8px;
}

.chart-table {
    margin: 0 0 8px;
    max-width: 100%;
}

.chart-table > summary {
    display: flex;
    align-items: center;
    min-height: 44px;
    cursor: pointer;
    color: var(--text-2);
}

.chart-table > summary:focus-visible {
    outline: 2px solid var(--accent-bright);
    outline-offset: 3px;
}

/* Wide tables scroll here rather than widening the card and taking the whole
 * page sideways with them at 320 px. */
.chart-table-scroll {
    overflow-x: auto;
    max-width: 100%;
}

.chart-table-scroll:focus-visible {
    outline: 2px solid var(--accent-bright);
    outline-offset: 2px;
}

.chart-table table {
    width: 100%;
    border-collapse: collapse;
    font-size: .82rem;
}

.chart-table caption {
    text-align: left;
    color: var(--text-2);
    padding-bottom: 6px;
}

.chart-table th,
.chart-table td {
    border-bottom: 1px solid var(--hairline);
    padding: 5px 7px;
    text-align: left;
    vertical-align: top;
}

.chart-table thead th {
    color: var(--text-2);
    font-weight: 600;
}

.chart-footnote {
    color: var(--text-2);
    font-size: .8rem;
    margin: 0 0 4px;
}

/* Opacity only, and switched off twice: once here under the media query and
 * once by charts.js, which omits the class when it is told motion is
 * reduced. */
.chart-reveal {
    animation: ch-fade 240ms ease-out both;
}

@keyframes ch-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    .chart-reveal {
        animation: none;
    }
}

/* ── SVG data classes ───────────────────────────────────────────────────── */

.ch-night {
    fill: var(--ch-night);
}

.ch-nap {
    fill: var(--ch-nap);
}

/* Drawn over .ch-nap with the same path data; the pattern fill arrives as a
 * presentation attribute, so this rule must not set fill. --text-1 flips with
 * the scheme, which keeps the hatch legible on the pastel mint either way and
 * lifts the band's contrast against the card. */
.ch-nap-hatch {
    opacity: .4;
    stroke: none;
}

.ch-hatch-line {
    fill: none;
    stroke: var(--text-1);
    stroke-width: .9;
}

.ch-night-stroke {
    fill: none;
    stroke: var(--ch-night);
    stroke-width: 9;
    stroke-linecap: butt;
}

.ch-nap-stroke {
    fill: none;
    stroke: var(--ch-nap);
    stroke-width: 9;
    stroke-linecap: butt;
}

/* Feed marks: teal, and never told apart from the mint sleep bands by hue
 * alone. Every tick is drawn twice — a halo underneath in --on-accent, then
 * the mark itself — so a tick keeps an edge wherever it lands. */
.ch-feed-halo {
    fill: var(--on-accent);
    stroke: none;
    opacity: .65;
}

.ch-feed-l {
    fill: var(--ch-feed-l);
    stroke: none;
}

.ch-feed-r {
    fill: none;
    stroke: var(--ch-feed-r);
    stroke-width: .55;
}

/* Side not distinguished: centred on the column axis rather than offset. */
.ch-feed-x {
    fill: var(--ch-feed-l);
    stroke: none;
    opacity: .85;
}

.ch-feed-line {
    fill: none;
    stroke: var(--ch-feed-l);
    stroke-width: 2;
    stroke-linejoin: round;
}

.ch-uncovered {
    fill: var(--subtle-fill);
}

.ch-axis {
    fill: none;
    stroke: var(--hairline);
    stroke-width: 1;
}

.ch-axis-text {
    fill: var(--text-2);
    font-family: var(--font);
    font-size: 10.5px;
    font-variant-numeric: tabular-nums;
}

.ch-micro {
    fill: var(--text-2);
    font-family: var(--font);
    font-size: 9.5px;
    letter-spacing: 1px;
    font-variant-numeric: tabular-nums;
}

.ch-value-text {
    fill: var(--text-1);
    font-family: var(--font);
    font-size: 15px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.ch-milestone {
    fill: none;
    stroke: var(--text-2);
    stroke-width: .6;
    stroke-dasharray: 2 3;
    opacity: .6;
}

/* Its own scale, so it is deliberately not a sleep or feed colour. */
.ch-step {
    fill: none;
    stroke: var(--text-1);
    stroke-width: 1.6;
    stroke-linejoin: round;
}

.ch-braid-l {
    fill: none;
    stroke: var(--ch-feed-l);
    stroke-width: 2.4;
    stroke-linecap: round;
}

/* Same hue as the L strand on purpose: the strands are told apart by the dash
 * and by the L/R labels at their ends, never by colour. */
.ch-braid-r {
    fill: none;
    stroke: var(--ch-feed-l);
    stroke-width: 2.4;
    stroke-dasharray: 5 3.5;
    stroke-linecap: butt;
}

/* ── Legend swatches (HTML spans, so they need background, not fill) ────── */

.swatch.ch-night {
    background: var(--ch-night);
}

.swatch.ch-nap {
    background: var(--ch-nap);
    background-image: repeating-linear-gradient(45deg,
        var(--text-1) 0 1px, transparent 1px 4px);
}

.swatch.ch-feed-l {
    background: var(--ch-feed-l);
}

.swatch.ch-feed-r {
    background: transparent;
    border: 2px solid var(--ch-feed-r);
}

.swatch.ch-feed-x {
    background: var(--ch-feed-l);
    opacity: .85;
}

.swatch.ch-uncovered {
    background: var(--subtle-fill);
}

.swatch.ch-feed-line,
.swatch.ch-braid-l {
    height: 5px;
    border-radius: 999px;
    background: var(--ch-feed-l);
}

.swatch.ch-braid-r {
    height: 5px;
    border-radius: 0;
    background: repeating-linear-gradient(90deg,
        var(--ch-feed-l) 0 5px, transparent 5px 9px);
    border-color: transparent;
}

.swatch.ch-step {
    height: 5px;
    border-radius: 999px;
    background: var(--text-1);
}

/* ── end charts.js styles ── */

/* === share-card UI (hero-and-share) === */
/* Everything share-card.js renders, and nothing else. Colour comes from
 * tokens.css through var(); this block introduces no literal hex and no
 * literal rgba — the modal backdrop tints with a token plus opacity rather
 * than a hand-mixed colour.
 *
 * DELIBERATELY NOT REDEFINED HERE, because earlier blocks already own them:
 *   - 44x44 targets and inline-flex centring: the `.btn, button` rule in the
 *     ui-flow block covers every control below, so only the labels wrapping a
 *     radio need their own target size;
 *   - the focus ring: ui-flow's `:focus-visible` applies inside the dialog
 *     like anywhere else;
 *   - tabular figures: the caption textarea carries the charts block's .tnum
 *     class rather than repeating font-variant-numeric.
 *
 * The canvas is never in the document — it is drawn detached and read back as
 * a PNG — so nothing here styles it. This block declares no animation; the
 * reduced-motion guard in the ui-flow block covers it regardless. */

.share-block {
    margin: 20px 0;
}

.share-trigger,
.share-action {
    padding: 10px 18px;
    border: 1px solid var(--hairline);
    border-radius: var(--r-pill);
    background: var(--elevated);
    color: var(--text-1);
    font: inherit;
    cursor: pointer;
}

.share-dialog {
    width: min(34rem, calc(100vw - 32px));
    max-height: min(90dvh, 90vh);
    overflow-y: auto;
    padding: 20px;
    border: 1px solid var(--hairline);
    border-radius: var(--r-sheet);
    background: var(--card);
    color: var(--text-1);
}

/* A token plus opacity, so the scrim follows the scheme without a literal. */
.share-dialog::backdrop {
    background: var(--text-1);
    opacity: .55;
}

.share-heading {
    margin: 0 0 14px;
    font-size: 1.15rem;
}

.share-picker {
    margin: 0 0 14px;
    padding: 8px 14px 12px;
    border: 1px solid var(--hairline);
    border-radius: var(--r-card);
}

.share-picker legend {
    padding: 0 6px;
    color: var(--text-2);
    font-size: .84rem;
}

/* A <label> is display:inline and would ignore min-height, the same reason
 * the ui-flow block gives for its own inline-flex rule. */
.share-pick {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 44px;
    margin-right: 18px;
}

/* The width and height attributes carry the 4:5 backing store, so height:auto
 * already preserves the ratio; aspect-ratio holds it if the image is missing. */
.share-preview {
    display: block;
    width: 100%;
    max-width: 340px;
    height: auto;
    aspect-ratio: 4 / 5;
    margin: 0 auto 14px;
    border: 1px solid var(--hairline);
    border-radius: var(--r-card);
}

/* Always visible, never collapsed behind a disclosure. */
.share-warning {
    margin: 0 0 14px;
    padding: 10px 14px;
    border: 1px solid var(--hairline);
    border-left: 3px solid var(--alert);
    border-radius: var(--r-card);
    background: var(--sheet);
    color: var(--text-2);
    font-size: .88rem;
}

/* The status region is never display:none — a live region hidden at load time
 * is not reliably announced when it later gains text. Empty, it simply takes
 * no vertical space. */
.share-status:empty {
    margin: 0;
}

.share-status,
.share-note {
    margin: 0 0 12px;
    color: var(--text-2);
    font-size: .88rem;
}

.share-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

.share-caption {
    margin-top: 14px;
}

.share-caption label {
    display: block;
    margin-bottom: 6px;
    color: var(--text-2);
    font-size: .84rem;
}

.share-caption textarea {
    width: 100%;
    padding: 8px 10px;
    border: 1px solid var(--hairline);
    border-radius: var(--r-card);
    background: var(--sheet);
    color: var(--text-1);
    font: inherit;
    resize: vertical;
}

/* === end share-card UI === */

/* ── content & SEO pages (content-seo task) ── */
/* The visual layer for everything a crawler and a first-time visitor sees:
 * the shared header and footer, the landing page's pre-import sections, the
 * export guide, and the methods page. Colour comes from tokens.css through
 * var() — this block introduces no literal colour at all, so the light
 * default and the dark alternate both follow the token file.
 *
 * Deliberately NOT redefined here, because earlier blocks own them:
 *   - the 44x44 target and inline-flex centring on .btn/button (ui-flow);
 *   - :focus-visible and the .skip recipe (ui-flow);
 *   - .chart-card, .chart-legend, .swatch, .tnum and every .ch-* SVG class
 *     (charts) — the example ribbon reuses them verbatim so the static
 *     example and the real ribbon cannot drift apart.
 *
 * Two classes are new because the example ribbon draws feed starts as
 * triangles rather than the ribbon's rectangles: .ex-feed and .ex-feed-halo.
 * The halo is a stroke here rather than a second filled path, which lets one
 * <path> in <defs> serve both marks through <use> and keeps the committed
 * markup small. */

/* ── shared shell ───────────────────────────────────────────────────────── */

body {
    font-size: 16px;
    line-height: 1.55;
    -webkit-font-smoothing: antialiased;
}

.wrap {
    max-width: 860px;
    margin: 0 auto;
    padding: 0 20px;
}

/* A long word or a wide table must never take the page sideways at 320px. */
:where(p, h1, h2, h3, li, figcaption, td, th, dd, dt) {
    overflow-wrap: anywhere;
}

:where(img, svg) {
    max-width: 100%;
    height: auto;
}

header.site {
    border-bottom: 1px solid var(--hairline);
}

.site__bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    padding-block: 14px;
}

.brand {
    display: flex;
    align-items: center;
    gap: 10px;
    text-decoration: none;
    color: var(--text-1);
}

.brand__mark {
    width: 26px;
    height: 26px;
    border-radius: 7px;
    flex: none;
}

.brand__word {
    font-size: 16px;
    font-weight: 680;
    letter-spacing: -.01em;
}

.brand__tag {
    border: 1px solid var(--hairline);
    border-radius: 5px;
    padding: 2px 7px;
}

.brand__by {
    color: var(--text-2);
    text-decoration: none;
    /* The link sits in a dense bar, so it earns its target height with
     * padding rather than by growing the header. */
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding-inline: 4px;
}

.brand__by:hover {
    color: var(--accent-bright);
    text-decoration: underline;
}

.micro {
    font-size: 12.5px;
    color: var(--text-2);
    letter-spacing: .01em;
}

/* The dimmest of the three text tokens never carries text in this block. It
 * measures about 2.3:1 on these surfaces, less than half the 4.5:1 floor, and
 * none of the small type here is decorative — the eyebrows are what keep
 * Nova's conventions visually apart from clinical guidance, the SVG stamp is
 * what marks the example as invented, and the footer paragraphs are the
 * not-medical-advice and affiliation statements. --text-2 clears the floor in
 * both schemes (5.45:1 light, 6.27:1 dark) and is what the neighbouring
 * .micro and .ch-axis-text rules already use. --text-3 survives here only as
 * a border colour, where no contrast minimum applies. */
.eyebrow {
    font-size: 11.5px;
    font-weight: 680;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--text-2);
    margin: 0 0 10px;
}

h1 {
    font-size: clamp(30px, 5.4vw, 44px);
    line-height: 1.08;
    letter-spacing: -.022em;
    font-weight: 740;
    margin: 0 0 14px;
}

h2 {
    font-size: 22px;
    font-weight: 700;
    letter-spacing: -.012em;
    margin: 0 0 10px;
}

h2.eyebrow {
    font-size: 11.5px;
    font-weight: 680;
    letter-spacing: .14em;
}

h3 {
    font-size: 16px;
    font-weight: 660;
    margin: 22px 0 6px;
}

p.sub {
    color: var(--text-2);
    font-size: 17.5px;
    max-width: 34em;
    margin: 0 0 26px;
}

main a {
    color: var(--accent-bright);
}

/* ── buttons ────────────────────────────────────────────────────────────── */

.btn {
    font: inherit;
    font-weight: 640;
    text-decoration: none;
    padding: 13px 22px;
    border-radius: var(--r-card);
    border: 1px solid var(--hairline);
    color: var(--text-1);
    background: var(--card);
    cursor: pointer;
    transition: background-color 140ms ease-out;
}

/* CONTRAST FLOOR: the emphasis mint is the RESTING fill, not the hover fill.
 * The base --accent pairs with --on-accent at only 4.24:1 for this label,
 * under the 4.5:1 minimum for normal text; --accent-bright clears it in both
 * schemes (5.89:1 light, 12.73:1 dark). Token values are design-owned — this
 * is a local pairing fix, not a palette change. */
.btn--accent {
    background: var(--accent-bright);
    border-color: var(--accent-bright);
    color: var(--on-accent);
}

/* Hover mixes the fill toward --text-1, which in either scheme is the colour
 * furthest from --on-accent — darker mint under white in light, lighter mint
 * under near-black in dark. So the hover state can only ever RAISE contrast
 * (8.20:1 light, 13.74:1 dark, both measured), and 70% keeps the step the
 * same size the design already had between its rest and hover fills.
 * Browsers without color-mix simply hold the resting fill, which is the safe
 * way to fail. */
@supports (background: color-mix(in srgb, red, blue)) {
    .btn--accent:hover {
        background: color-mix(in srgb, var(--accent-bright) 70%, var(--text-1));
        border-color: color-mix(in srgb, var(--accent-bright) 70%, var(--text-1));
    }
}

/* This block is the first to introduce a transition, so it carries its own
 * guard as well as inheriting ui-flow's blanket rule. */
@media (prefers-reduced-motion: reduce) {
    .btn {
        transition: none;
    }
}

/* ── landing hero + import control ──────────────────────────────────────── */

.hero {
    padding: 40px 0 8px;
}

#dropzone {
    background: var(--card);
    border: 1px solid var(--hairline);
    border-radius: var(--r-card-lg);
    padding: 20px;
    margin: 0 0 30px;
}

#dropzone.is-dragover {
    border-color: var(--accent);
    background: var(--elevated);
}

#dropzone p {
    margin: 10px 0 0;
}

.badge-row {
    margin: 12px 0 0;
}

.badge {
    display: inline-block;
    font-size: 11.5px;
    font-weight: 680;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--accent-bright);
    border: 1px solid var(--hairline);
    border-radius: var(--r-pill);
    padding: 5px 12px;
}

#landing-inline-alert {
    border-left: 3px solid var(--alert);
    padding-left: 12px;
    color: var(--text-1);
}

.strip {
    list-style: none;
    margin: 0 0 34px;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: 14px;
}

.strip li {
    background: var(--card);
    border: 1px solid var(--hairline);
    border-radius: var(--r-card);
    padding: 14px 16px;
    font-size: 13.5px;
    color: var(--text-2);
}

.strip strong {
    color: var(--text-1);
}

/* ── the synthetic example ──────────────────────────────────────────────── */

figure.example {
    margin: 0 0 44px;
}

figure.example .chart-legend {
    margin: 10px 0 0;
}

figure.example figcaption {
    font-size: 13px;
    color: var(--text-2);
    margin-top: 8px;
}

figure.example figcaption strong {
    color: var(--text-1);
}

/* Wide scene, narrow phone: the ribbon scrolls inside its own card rather
 * than shrinking to illegibility or widening the page. Only the drawing
 * scrolls — the legend below it must stay where a reader can find it, and it
 * has to sit inside the card to inherit the --ch-* aliases charts.js declares
 * there, which is what colours its swatches. */
.ex-scroll {
    overflow-x: auto;
}

.ex-scroll > svg.chart-svg {
    min-width: 520px;
}

.ex-scroll:focus-visible {
    outline: 2px solid var(--accent-bright);
    outline-offset: 2px;
}

.ex-stamp {
    fill: var(--text-2);
    font-family: var(--font);
    font-size: 10.5px;
    font-weight: 680;
    letter-spacing: .14em;
}

/* Feed starts, drawn once in <defs> and painted twice: the halo underneath
 * keeps a tick legible wherever it lands on a band, and the triangle is what
 * separates a feed from sleep for anyone who cannot use the hue. */
.ex-feed-halo {
    fill: var(--on-accent);
    stroke: var(--on-accent);
    stroke-width: 1.3;
    stroke-linejoin: round;
    opacity: .72;
}

.ex-feed {
    fill: var(--feed);
    stroke: none;
}

.swatch--tri {
    background: var(--feed);
    border: 0;
    border-radius: 0;
    clip-path: polygon(0 0, 100% 50%, 0 100%);
}

/* ── prose sections ─────────────────────────────────────────────────────── */

.prose {
    padding-top: 34px;
}

.block {
    margin: 0 0 40px;
    max-width: 42em;
}

.block ul,
.block ol {
    padding-left: 20px;
}

.block li {
    margin: 6px 0;
}

.steps {
    list-style: decimal;
}

.steps li {
    margin: 10px 0;
}

/* The three quoted blocks — the verbatim trust text, the honest limit, and
 * the "not a medical threshold" notice — share one treatment so a reader
 * learns to recognise them as promises rather than prose. */
.trust,
.caveat,
.callout,
.verified {
    background: var(--sheet);
    border: 1px solid var(--hairline);
    border-left: 3px solid var(--accent);
    border-radius: var(--r-card);
    padding: 14px 16px;
    margin: 0 0 14px;
}

.caveat {
    border-left-color: var(--text-3);
    color: var(--text-2);
}

#faq h3 {
    margin-top: 26px;
}

#faq p {
    color: var(--text-2);
    margin: 0;
}

.conventions h3,
.clinical h3 {
    margin-top: 24px;
}

.sources li {
    margin: 10px 0;
}

/* ── footer ─────────────────────────────────────────────────────────────── */

.site-footer {
    border-top: 1px solid var(--hairline);
    margin-top: 56px;
    padding: 22px 0 40px;
}

.footer-nav {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 20px;
    margin-bottom: 12px;
}

.footer-nav a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    color: var(--text-2);
    font-size: 13.5px;
}

.footer-nav a:hover {
    color: var(--accent-bright);
}

.site-footer p {
    font-size: 12.5px;
    color: var(--text-2);
    margin: 4px 0;
}

.affiliation strong {
    color: var(--text-2);
}

/* ── end content & SEO pages ── */

/* == receipt-and-fallback:begin == */
/* The coverage line and the data-quality receipt, both directly under the
 * report heading. Colour comes from .micro and from --text-2, the same token
 * the neighbouring small type uses; the dimmest text token is never painted
 * here. The Methods link inherits its colour from the `main a` rule above, so
 * it stays visibly a link. */

#coverage-line {
    margin: 2px 0 0;
}

/* A list of plain facts, not a content list: no marker, no indent, so it
 * reads as a continuation of the header rather than page copy. */
.receipt {
    list-style: none;
    margin: 14px 0 0;
    padding: 0;
    font-size: 12.5px;
    color: var(--text-2);
    max-width: 42em;
}

.receipt li {
    margin: 4px 0;
}
/* == receipt-and-fallback:end == */
