/*
 * Funnel design system.
 *
 * Mobile-first to the point of being mobile-only in practice: this traffic is
 * ~all iPhone, so the layout is built for a 375–430pt viewport first and merely
 * kept sane above that.
 */

/*
 * PT Sans, served from this host rather than from fonts.googleapis.com.
 *
 * The Google stylesheet was a render-blocking request to a third party: two
 * extra DNS lookups and TLS handshakes before the first character could be
 * drawn, and one more hop that has to be up and reachable from wherever the
 * visitor is. Served from here it rides the connection the page already has.
 *
 * Subsets and unicode-ranges are copied verbatim from what Google served, so a
 * browser still downloads only the ranges its text actually uses: an English
 * funnel takes the two latin files and never asks for the cyrillic ones. The
 * funnel's locale is a per-funnel column, so the cyrillic subsets are declared
 * even though nothing seeded uses them yet — an unused @font-face costs
 * nothing until something matches it.
 *
 * font-display: swap, as Google had it: the text is the screen, and a funnel
 * that shows nothing for 300ms reads as broken far more than one that reflows.
 *
 * PT Sans is licensed under the SIL Open Font License 1.1 — see
 * public/fonts/pt-sans/LICENSE.md.
 */
@font-face {
    font-family: 'PT Sans';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('../fonts/pt-sans/pt-sans-400-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'PT Sans';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('../fonts/pt-sans/pt-sans-700-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'PT Sans';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('../fonts/pt-sans/pt-sans-400-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'PT Sans';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('../fonts/pt-sans/pt-sans-700-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'PT Sans';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('../fonts/pt-sans/pt-sans-400-cyrillic.woff2') format('woff2');
    unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

@font-face {
    font-family: 'PT Sans';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('../fonts/pt-sans/pt-sans-700-cyrillic.woff2') format('woff2');
    unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

@font-face {
    font-family: 'PT Sans';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('../fonts/pt-sans/pt-sans-400-cyrillic-ext.woff2') format('woff2');
    unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}

@font-face {
    font-family: 'PT Sans';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('../fonts/pt-sans/pt-sans-700-cyrillic-ext.woff2') format('woff2');
    unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}

:root {
    --accent: #ff5e7d;
    --accent-press: #ef4d6c;
    --accent-soft: rgba(255, 209, 209, 0.6);
    --ink: #262626;
    --ink-muted: #6b6b6b;
    --surface: #fff;
    --line: #ececec;

    --radius-card: 16px;
    --radius-pill: 1000px;

    --gutter: 20px;
    --tap: 44px; /* Apple's minimum comfortable target */
    /* Declared rather than measured: what sticks below the header has to be
       told where it ends, and what scrolls under both has to be told how much
       of the screen they cover. Nothing in CSS can ask. */
    --hdr-h: var(--tap);
    --offerbar-h: 58px;

    /* Safari's toolbars overlay the viewport; env() is 0 on everything else. */
    --safe-top: env(safe-area-inset-top, 0px);
    --safe-bottom: env(safe-area-inset-bottom, 0px);
}

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

html {
    -webkit-text-size-adjust: 100%; /* stop Safari resizing text in landscape */
}

body {
    margin: 0;
    /* dvh, not vh: vh on iOS is the tallest possible viewport, so a sticky
       footer sits under the address bar until the user scrolls. */
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
    font-family: 'PT Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-size: 17px;
    line-height: 1.45;
    color: var(--ink);
    background: var(--surface);
    -webkit-font-smoothing: antialiased;
    -webkit-tap-highlight-color: transparent; /* no grey flash on tap */
    overscroll-behavior-y: contain; /* no rubber-band past the funnel */
}

/* ─── Header ──────────────────────────────────────────────────────────── */

.hdr {
    position: sticky;
    top: 0;
    z-index: 10;
    display: grid;
    grid-template-columns: var(--tap) 1fr var(--tap);
    align-items: center;
    /* Fixed height, not whatever the contents come to: the offer bar sticks
       directly below and has to be given the number. */
    min-height: calc(var(--safe-top) + var(--hdr-h));
    padding-top: var(--safe-top);
    background: var(--surface);
}

.hdr__back {
    display: flex;
    align-items: center;
    justify-content: center;
    width: var(--tap);
    height: var(--tap);
    padding: 0;
    border: 0;
    background: none;
    color: var(--ink);
    cursor: pointer;
    touch-action: manipulation; /* drop the 300ms double-tap delay */
}

.hdr__back svg {
    width: 11px;
    height: 20px;
}

.hdr__title {
    margin: 0;
    font-size: 17px;
    font-weight: 400;
    text-align: center;
}

/* ─── Progress ────────────────────────────────────────────────────────── */

.progress {
    display: flex;
    gap: 6px;
    padding: 6px var(--gutter) 0;
}

.progress__seg {
    flex: 1;
    height: 4px;
    border-radius: var(--radius-pill);
    background: var(--accent-soft);
}

.progress__seg--on {
    background: var(--accent);
}

/* Announced but not drawn. For headings a page needs to have and a reader
   needs to hear, where showing them would repeat what the artwork already
   says — clip rather than display:none, which takes them out of the tree. */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* ─── Offer clock ─────────────────────────────────────────────────────── */

/* The paywall's only chrome. It draws no title bar of its own, so this sits at
   the top of the screen and pays the notch inset itself. */
.offerbar {
    position: sticky;
    top: 0;
    z-index: 10;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    min-height: calc(var(--safe-top) + var(--offerbar-h));
    padding: 6px var(--gutter);
    padding-top: calc(6px + var(--safe-top));
    background: var(--surface);
}

.offerbar__time,
.offer__timer {
    margin: 0;
    color: var(--accent);
    font-weight: 700;
    line-height: 1.1;
    /* Digits of equal width: with proportional ones the line twitches every
       second as the numbers change under it. */
    font-variant-numeric: tabular-nums;
}

.offerbar__time {
    font-size: 28px;
}

/* The same clock again inside the offer blocks, where the price it applies to
   is on screen next to it. */
.offer__timer {
    margin-bottom: 10px;
    font-size: 36px;
    text-align: center;
}

/* ─── Layout ──────────────────────────────────────────────────────────── */

.screen {
    flex: 1;
    display: flex;
    flex-direction: column;
    padding: 24px var(--gutter) 0;
}

/*
 * A step being fetched. funnel.js sets this on <html> while it waits, in place
 * of the browser's own loading indicator, which a page that never reloads
 * never shows.
 *
 * The delay on the transition is the whole point: a step that lands inside
 * 180ms — which is most of them, the artwork having arrived a screen early —
 * finishes before the fade has begun, and the visitor sees an answer commit
 * instantly rather than a screen blinking at them. Only a wait long enough to
 * be noticed gets acknowledged.
 */
.is-navigating .screen {
    opacity: 0.55;
    transition: opacity 0.15s ease 0.18s;
}

.screen--centered {
    text-align: center;
    align-items: center;
}

h1 {
    margin: 0 0 8px;
    font-size: 28px;
    font-weight: 700;
    line-height: 1.3;
    letter-spacing: -0.2px;
    text-wrap: balance;
}

/* Every other screen ends in the sticky footer, which is what clears the home
   indicator. The offer has no footer, so it buys that room itself. */
.screen--offer {
    padding-bottom: calc(24px + var(--safe-bottom));
}

/* The landing carries no header, so it needs its own breathing room up top. */
.screen--hero {
    padding-top: calc(32px + var(--safe-top));
}

.screen--hero h1 {
    text-transform: uppercase;
}

.lede {
    margin: 0 0 4px;
    color: var(--ink-muted);
    font-size: 17px;
}

.hint {
    margin: 0 0 12px;
    color: var(--ink-muted);
    font-size: 15px;
}

.note,
.legal {
    margin: 12px 0 0;
    color: var(--ink-muted);
    font-size: 13px;
    line-height: 1.4;
}

.err {
    margin: 0 0 12px;
    color: #c0392b;
    font-size: 15px;
}

/* ─── Question: options left, illustration bleeding right ─────────────── */

.quiz {
    position: relative;
    /* `flex: 1` does nothing here — the parent is the form, which is not a flex
       container — so this box is only as tall as the answer cards inside it.
       The picture hangs out of flow against its bottom edge, so on a screen
       with three short answers the box was shorter than the photograph and the
       photograph grew upward into the question. Tall enough for the picture,
       and the question keeps its own air. */
    min-height: 320px;
    flex: 1;
}

.quiz__figure {
    position: absolute;
    right: calc(var(--gutter) * -1);
    bottom: 0;
    width: 52%;
    max-width: 240px;
    pointer-events: none;
}

/* No vertical margin inside the column: it only pushes the picture further up
   towards the question, and the column already spaces itself. */
.quiz__figure .figure {
    margin: 0;
}

.quiz__options {
    position: relative;
    z-index: 1;
    width: 62%;
    min-width: 190px;
}

.options {
    list-style: none;
    margin: 16px 0 0;
    padding: 0;
    display: grid;
    gap: 10px;
}

.options--wide {
    width: 100%;
}

.opt {
    display: block;
    min-height: var(--tap);
    padding: 14px 16px;
    border: 1px solid var(--line);
    border-radius: var(--radius-card);
    background: var(--surface);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
    cursor: pointer;
    touch-action: manipulation;
    transition: border-color 0.12s ease, transform 0.12s ease;
}

.opt:active {
    transform: scale(0.985);
}

.opt input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}

.opt__title {
    display: block;
    font-weight: 700;
    font-size: 17px;
}

/* A bare label centres; one carrying a description reads as a block and stays
   left-aligned, so the two kinds of card do not fight each other. */
.opt:not(:has(.opt__desc)) {
    text-align: center;
}

.opt__desc {
    display: block;
    margin-top: 6px;
    color: var(--ink-muted);
    font-size: 15px;
}

/* Tinted, not just outlined: at arm's length a 1px border change is easy to
   miss, and this is the confirmation that a tap registered. */
.opt:has(:checked) {
    border-color: var(--accent);
    background: color-mix(in srgb, var(--accent) 8%, var(--surface));
}

/* Multi-select needs a visible box, since nothing advances on tap. */
.opt--multi:has(:checked)::after {
    content: '✓';
    float: right;
    margin-top: -22px;
    color: var(--accent);
    font-weight: 700;
}

/* ─── Weight curve ────────────────────────────────────────────────────── */

.chart {
    position: relative;
    width: 100%;
    height: 260px;
    margin: 44px 0 8px;
}

.chart__plot {
    width: 100%;
    height: 100%;
    overflow: visible;
}

.chart__grid {
    stroke: var(--line);
    stroke-width: 0.6;
    vector-effect: non-scaling-stroke;
}

.chart__line {
    fill: none;
    stroke: var(--accent);
    stroke-width: 4;
    stroke-linecap: round;
    stroke-linejoin: round;
    /* The box is stretched to fit, so scale the stroke back out. */
    vector-effect: non-scaling-stroke;
}

.chart__dot {
    position: absolute;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--accent);
    transform: translate(-50%, -50%);
}

.chart__dot--start { left: 0; top: 0; }
.chart__dot--end { left: 100%; top: 100%; }

.chart__pin {
    position: absolute;
    z-index: 1;
    padding: 8px 14px;
    border-radius: 12px;
    background: var(--accent);
    color: #fff;
    font-size: 14px;
    line-height: 1.25;
    text-align: center;
}

.chart__pin b {
    font-size: 16px;
}

.chart__pin--start {
    left: 0;
    top: -44px;
}

.chart__pin--end {
    right: 0;
    bottom: 26px;
}

.chart__caption {
    width: 100%;
    margin: 16px 0 0;
    color: var(--ink-muted);
    font-size: 13px;
    line-height: 1.45;
    text-align: left;
}

/* ─── Notice: a reassurance screen that argues its case ───────────────── */

.notice {
    width: 100%;
    text-align: left;
}

.notice p {
    margin: 0 0 16px;
    font-size: 17px;
    line-height: 1.5;
}

.notice p strong {
    font-weight: 700;
}

/* A notice reads as prose, so the heading and lede sit left with it rather
   than centred over it. */
.screen--notice {
    align-items: stretch;
    text-align: left;
}

/* ─── Hero picture with compact answers ───────────────────────────────── */

.slot--hero {
    aspect-ratio: 4 / 3;
    width: 100%;
    margin: 4px 0 16px;
}

/* ─── Artwork ─────────────────────────────────────────────────────────── */

/*
 * Each of these stands exactly where its placeholder stood, so the box is
 * copied from the slot it replaces. Real pictures carry their own proportions,
 * though, so where a placeholder had to be told an aspect ratio these are left
 * to their intrinsic one — a 1:2 cut-out letterboxed into a 3:4 frame would be
 * a smaller picture in the same grey box.
 */
.figure {
    display: block;
    width: 100%;
    height: auto;
    margin: 20px 0;
}

.figure--hero {
    margin: 4px 0 16px;
}

.choices {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    width: 100%;
}

.choice {
    display: flex;
    align-items: center;
    height: 100%;
    min-height: 64px;
    padding: 14px 16px;
    border: 1px solid var(--line);
    border-radius: var(--radius-card);
    font-size: 16px;
    font-weight: 700;
    line-height: 1.25;
    text-align: left;
    cursor: pointer;
    touch-action: manipulation;
    transition: border-color 0.12s ease, background 0.12s ease;
}

.choice input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}

.choice:has(:checked) {
    border-color: var(--accent);
    background: color-mix(in srgb, var(--accent) 8%, var(--surface));
}

/* ─── Fields ──────────────────────────────────────────────────────────── */

.field {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin: 20px 0 0;
}

.field input {
    flex: 1;
    min-height: var(--tap);
    padding: 12px 16px;
    border: 1px solid var(--line);
    border-radius: var(--radius-card);
    background: var(--surface);
    color: inherit;
    font: inherit;
    /* Never below 16px: Safari zooms the page when a smaller field is focused
       and does not zoom back out. */
    font-size: 17px;
}

.field input:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 1px var(--accent);
}

.field__unit {
    color: var(--ink-muted);
}

/* ─── Illustration placeholder ────────────────────────────────────────── */

.slot {
    display: grid;
    place-content: center;
    gap: 4px;
    margin: 20px 0;
    padding: 24px 16px;
    border: 1px dashed #d6d6d6;
    border-radius: var(--radius-card);
    color: var(--ink-muted);
    font-size: 13px;
    text-align: center;
    /* Specs are long sentences and the figure column is narrow; clip rather
       than let them spill over the option cards. */
    overflow: hidden;
}

.slot--figure {
    aspect-ratio: 3 / 4;
    width: 100%;
    align-content: center;
    padding: 12px 8px;
    font-size: 11px;
    line-height: 1.35;
    hyphens: auto;
}

.slot--figure .slot__note {
    display: -webkit-box;
    -webkit-line-clamp: 8;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.slot__spec {
    font-weight: 700;
}

/* ─── Footer CTA ──────────────────────────────────────────────────────── */

.footer {
    position: sticky;
    bottom: 0;
    z-index: 8; /* above everything scrolling past it — the attrs list carries
                   its own z-index:1 and would otherwise paint over the button */
    padding: 12px var(--gutter);
    /* Clear the home indicator on Face ID phones. */
    padding-bottom: calc(12px + var(--safe-bottom));
    background: linear-gradient(to top, var(--surface) 72%, transparent);
}

.btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    min-height: 56px;
    padding: 16px 24px;
    border: 0;
    border-radius: var(--radius-pill);
    background: var(--accent);
    color: #fff;
    font: inherit;
    font-size: 17px;
    font-weight: 700;
    /* The offer's buttons are anchors that scroll to the card form, and a
       button with an underline through it reads as a broken link. */
    text-decoration: none;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    cursor: pointer;
    touch-action: manipulation;
    transition: background 0.12s ease, transform 0.12s ease;
}

.btn:active {
    background: var(--accent-press);
    transform: scale(0.99);
}

/* The offer bar's button: sized to its words rather than to the strip, and
   pushed right so it holds its place whether or not a clock sits beside it.
   A modifier and not a rule in the bar's own section, because plain `.btn`
   comes later in this file and would otherwise win on source order. */
.btn--bar {
    width: auto;
    min-height: 46px;
    margin-left: auto;
    padding: 10px 24px;
    font-size: 16px;
}

/* ─── Hero grid (age picker on the landing) ───────────────────────────── */

.tiles {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
    width: 100%;
    margin-top: 20px;
}

.tile {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    overflow: hidden;
    aspect-ratio: 3 / 4;
    border-radius: var(--radius-card);
    background: #f4f4f4;
    cursor: pointer;
    touch-action: manipulation;
    border: 0;
    padding: 0;
}

.tile__slot {
    flex: 1;
    display: grid;
    place-content: center;
    padding: 8px;
    color: var(--ink-muted);
    font-size: 11px;
    line-height: 1.3;
    text-align: center;
}

/* Fills the card rather than sitting above the label, so the label reads as a
   band over the picture. Card and art are both 3:4, so cover crops nothing —
   and the top anchor keeps it that way if a replacement is ever squarer. */
.tile__img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: top center;
}

.tile__label {
    position: relative; /* over the picture, not beside it */
    padding: 12px 8px;
    background: var(--accent);
    color: #fff;
    font-size: 17px;
    font-weight: 700;
}

/* ─── Derived summary ─────────────────────────────────────────────────── */

.gauge__title {
    width: 100%;
    margin: 16px 0 28px;
    font-size: 20px;
    font-weight: 700;
    text-align: left;
}

.gauge {
    position: relative;
    width: 100%;
}

/* The pin sits above the strip and is nudged back by half its own width, so it
   points at the value rather than starting from it. */
.gauge__pin {
    position: absolute;
    top: -30px;
    transform: translateX(-50%);
    padding: 5px 12px;
    border-radius: var(--radius-pill);
    background: var(--ink);
    color: #fff;
    font-size: 14px;
    font-weight: 700;
    white-space: nowrap;
}

.gauge__scale {
    position: relative;
    display: flex;
    height: 10px;
    border-radius: var(--radius-pill);
    overflow: hidden;
}

.gauge__band--0 { background: #7fb8e6; }
.gauge__band--1 { background: #7ec98a; }
.gauge__band--2 { background: #f0c04a; }
.gauge__band--3 { background: #e8785e; }

.gauge__dot {
    position: absolute;
    top: 50%;
    width: 20px;
    height: 20px;
    transform: translate(-50%, -50%);
    border: 3px solid var(--surface);
    border-radius: 50%;
    background: var(--ink);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
}

.gauge__marks {
    display: flex;
    list-style: none;
    margin: 8px 0 0;
    padding: 0;
    color: var(--ink-muted);
    font-size: 12px;
}

.gauge__marks li {
    text-align: center;
}

/* ─── Verdict ─────────────────────────────────────────────────────────── */

.verdict {
    width: 100%;
    margin: 22px 0 0;
    padding: 16px;
    border-radius: var(--radius-card);
    text-align: left;
}

.verdict--good {
    background: #eaf7ee;
}

.verdict--watch {
    background: color-mix(in srgb, var(--accent) 10%, var(--surface));
}

/* Neither good news nor a warning: a note about the number just typed. */
.verdict--plain {
    background: color-mix(in srgb, var(--ink) 5%, var(--surface));
}

.verdict__title {
    margin: 0 0 4px;
    font-size: 17px;
    font-weight: 700;
}

.verdict--good .verdict__title { color: #2e7d4f; }
.verdict--watch .verdict__title { color: var(--accent-press); }
.verdict--plain .verdict__title { color: var(--ink); }

.verdict__note {
    margin: 0;
    color: var(--ink-muted);
    font-size: 15px;
    line-height: 1.4;
}

/* ─── Attributes, with the figure behind them ─────────────────────────── */

.attrs {
    position: relative;
    width: 100%;
    /* Same floor as the quiz column, and for the same reason: the picture hangs
       out of flow against the bottom of this box, and the rows above it are
       built from the visitor's answers — a run that only knows her weight
       leaves one row here, which is shorter than the photograph. */
    min-height: 320px;
    margin-top: 22px;
}

.attrs__figure {
    position: absolute;
    right: calc(var(--gutter) * -1);
    bottom: 0;
    width: 46%;
    max-width: 210px;
    pointer-events: none;
}

.attrs__list {
    position: relative;
    z-index: 1;
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 16px;
    width: 62%;
    min-width: 190px;
}

.attr {
    display: grid;
    grid-template-columns: 44px 1fr;
    align-items: center;
    gap: 12px;
    text-align: left;
}

.attr__img {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    object-fit: cover;
    flex: none;
}

.attr__icon {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: #f1f1f1;
}

.attr__text {
    display: grid;
    gap: 2px;
}

.attr__label {
    color: var(--ink-muted);
    font-size: 14px;
}

.attr__value {
    font-size: 17px;
    font-weight: 700;
    line-height: 1.25;
}

.metrics {
    list-style: none;
    margin: 20px 0 0;
    padding: 0;
    display: grid;
    gap: 10px;
    width: 100%;
}

.metric {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: baseline;
    row-gap: 2px;
    padding: 14px 16px;
    border: 1px solid var(--line);
    border-radius: var(--radius-card);
    text-align: left;
}

.metric__label {
    font-weight: 700;
    font-size: 16px;
}

.metric__value {
    grid-row: 1 / 3;
    grid-column: 2;
    align-self: center;
    font-size: 22px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.metric__note {
    color: var(--ink-muted);
    font-size: 14px;
}

.metric--good .metric__value {
    color: #2e9e6b;
}

.metric--watch .metric__value {
    color: var(--accent);
}

/* ─── Question: picture grid ──────────────────────────────────────────── */

.grid {
    list-style: none;
    margin: 20px 0 0;
    padding: 0;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
    width: 100%;
}

.gcard {
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border: 1px solid var(--line);
    border-radius: var(--radius-card);
    background: var(--surface);
    cursor: pointer;
    touch-action: manipulation;
    transition: border-color 0.12s ease, transform 0.12s ease;
}

.gcard:active {
    transform: scale(0.985);
}

.gcard input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}

.gcard:has(:checked) {
    border-color: var(--accent);
    box-shadow: 0 0 0 1px var(--accent);
}

.gcard__figure {
    display: grid;
    place-content: center;
    gap: 2px;
    aspect-ratio: 1 / 1;
    padding: 8px;
    background: #f5f5f5;
    color: var(--ink-muted);
    font-size: 10px;
    line-height: 1.3;
    text-align: center;
    overflow: hidden;
}

.gcard__img {
    display: block;
    width: 100%;
    height: auto;
}

.gcard__label {
    padding: 12px 10px;
    font-size: 16px;
    font-weight: 700;
    text-align: center;
}

/* ─── Question: icon rows ─────────────────────────────────────────────── */

.rows {
    list-style: none;
    margin: 16px 0 0;
    padding: 0;
    display: grid;
    gap: 10px;
    width: 100%;
}

.row {
    display: grid;
    grid-template-columns: 48px 1fr;
    align-items: center;
    gap: 14px;
    min-height: var(--tap);
    padding: 12px 16px;
    border: 1px solid var(--line);
    border-radius: var(--radius-card);
    background: var(--surface);
    text-align: left;
    cursor: pointer;
    touch-action: manipulation;
    transition: border-color 0.12s ease, transform 0.12s ease;
}

.row:active {
    transform: scale(0.99);
}

.row input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}

/* Selected rows tint the whole card, not just the edge: at arm's length on a
   phone a 1px border change is easy to miss. */
.row:has(:checked) {
    border-color: var(--accent);
    background: color-mix(in srgb, var(--accent) 8%, var(--surface));
}

.row__img {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    /* Square source into a square plate, so cover crops nothing. */
    object-fit: cover;
    flex: none;
}

.row__icon {
    display: grid;
    place-content: center;
    width: 48px;
    height: 48px;
    border-radius: 50%;
    background: #f1f1f1;
    color: var(--ink-muted);
    font-size: 10px;
    overflow: hidden;
}

.row__text {
    display: grid;
    gap: 3px;
}

.row__label {
    font-size: 16px;
    font-weight: 700;
}

.row__desc {
    color: var(--ink-muted);
    font-size: 15px;
    line-height: 1.3;
}

/* Heading over a set of related rows. Sits tight to the group it introduces
   and loose from the one above, so the grouping reads without a divider. */
.group {
    margin: 22px 0 8px;
    color: var(--ink-muted);
    font-size: 13px;
    letter-spacing: 0.6px;
    text-transform: uppercase;
    text-align: left;
    width: 100%;
}

.group:first-of-type {
    margin-top: 8px;
}

.rows + .group {
    margin-top: 22px;
}

/* Photo-led rows: the picture fills the card's left edge rather than sitting
   in a plate, and the label centres in what is left. */
.row--photo {
    grid-template-columns: 132px 1fr;
    gap: 0;
    padding: 0;
    overflow: hidden;
}

.row--photo .row__img {
    width: 132px;
    /* Stated outright. An image ignores the grid's stretch and keeps its own
       3:4 height, so leaving this to `auto` gave every row a 176px strip with
       the picture stranded at the top of it. */
    height: 132px;
    border-radius: 0;
    /* Tall art into a square strip: crop rather than letterbox, which is what
       the briefs were written for. Anchored high, so the crop loses feet
       rather than faces. */
    object-fit: cover;
    object-position: top center;
}

.row--photo .row__icon {
    width: 132px;
    height: 100%;
    min-height: 96px;
    border-radius: 0;
    font-size: 10px;
    padding: 6px;
    text-align: center;
}

/* Pad the text block, not the label: a description is a sibling of the label,
   so padding on the label alone leaves it flush against the picture. */
.row--photo .row__text {
    padding: 18px 16px;
    text-align: center;
}

/* A title with a description reads as a block and stays left-aligned; a bare
   label centres in the space beside the picture. */
.row--photo .row__text:has(.row__desc) {
    text-align: left;
}

.row--multi:has(:checked) .row__label::after {
    content: ' ✓';
    color: var(--accent);
}

/* ─── Measurement with a unit toggle ──────────────────────────────────── */

.measure {
    width: 100%;
    margin-top: 20px;
}

.units {
    display: inline-flex;
    gap: 4px;
    margin-bottom: 16px;
    padding: 4px;
    border-radius: var(--radius-pill);
    background: color-mix(in srgb, currentColor 6%, transparent);
}

.unit {
    min-height: 36px;
    padding: 8px 20px;
    border: 0;
    border-radius: var(--radius-pill);
    background: none;
    color: var(--ink-muted);
    font: inherit;
    font-size: 15px;
    font-weight: 700;
    cursor: pointer;
    touch-action: manipulation;
}

.unit.is-on {
    background: var(--surface);
    color: var(--ink);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}

.measure__pane {
    display: grid;
    gap: 10px;
}

.measure__pane[hidden] {
    display: none;
}

/* ─── The reading under a measurement ─────────────────────────────────── */

.reading {
    width: 100%;
}

/* The band itself is a .verdict, so it already carries the tone colours. */
.reading__band {
    display: flex;
    gap: 12px;
    align-items: flex-start;
}

/* [hidden] only sets display in the UA sheet, which any author rule beats. */
.reading__band[hidden] {
    display: none;
}

.reading__icon {
    flex: none;
    display: grid;
    place-items: center;
    width: 20px;
    height: 20px;
    margin-top: 3px;
    border-radius: 50%;
    color: var(--surface);
    font-size: 13px;
    font-weight: 700;
    line-height: 1;
}

.verdict--good .reading__icon { background: #2e7d4f; }
.verdict--watch .reading__icon { background: var(--accent-press); }
.verdict--plain .reading__icon { background: var(--ink-muted); }

/* ─── Processing ──────────────────────────────────────────────────────── */

.proc {
    display: grid;
    justify-items: center;
    gap: 28px;
    margin-top: 32px;
    width: 100%;
}

.proc__dial {
    position: relative;
    width: 160px;
    height: 160px;
}

.proc__dial svg {
    width: 100%;
    height: 100%;
    /* Start the sweep at twelve o'clock instead of three. */
    transform: rotate(-90deg);
}

.proc__track,
.proc__fill {
    fill: none;
    stroke-width: 8;
    stroke-linecap: round;
}

.proc__track {
    stroke: var(--accent-soft);
}

.proc__fill {
    stroke: var(--accent);
}

.proc__pct {
    position: absolute;
    inset: 0;
    display: grid;
    place-content: center;
    font-size: 32px;
    font-weight: 700;
    font-variant-numeric: tabular-nums; /* no width jitter as digits change */
}

.proc__stages {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 14px;
    width: 100%;
    max-width: 320px;
    text-align: left;
}

.proc__stage {
    display: grid;
    grid-template-columns: 24px 1fr;
    align-items: center;
    gap: 10px;
    color: var(--ink-muted);
    transition: color 0.2s ease;
}

.proc__stage.is-active,
.proc__stage.is-done {
    color: var(--ink);
}

.proc__tick {
    width: 20px;
    height: 20px;
    border: 2px solid var(--accent-soft);
    border-radius: 50%;
    transition: background 0.2s ease, border-color 0.2s ease;
}

.proc__stage.is-done .proc__tick {
    border-color: var(--accent);
    background: var(--accent);
}

/* ─── Prompts asked mid-processing ────────────────────────────────────── */

.prompt {
    width: 100%;
    margin-top: 28px;
    padding: 20px 16px;
    border: 1px solid var(--line);
    border-radius: var(--radius-card);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
    animation: prompt-in 0.18s ease-out;
}

.prompt[hidden] {
    display: none;
}

.prompt__text {
    margin: 0 0 16px;
    font-size: 18px;
    font-weight: 700;
    line-height: 1.35;
    text-wrap: balance;
}

.prompt__actions {
    display: grid;
    grid-auto-flow: column;
    gap: 10px;
}

.btn--ghost {
    background: transparent;
    border: 1px solid var(--accent);
    color: var(--accent);
    min-height: 50px;
}

.btn--ghost:active {
    background: color-mix(in srgb, var(--accent) 10%, transparent);
}

@keyframes prompt-in {
    from { opacity: 0; transform: translateY(6px); }
    to { opacity: 1; transform: none; }
}

/* ─── Paywall: a long page, so it repeats its offer ───────────────────── */

/* No title bar above it and no headline of its own: the offer opens on the
   before/after, which is what the visitor came this far to see. Less room up
   top than a titled screen takes, but not none — flush against the clock the
   labels read as part of the bar rather than as the start of the page. */
.screen--offer {
    padding-top: 16px;
}

.section {
    width: 100%;
    margin: 36px 0 16px;
    font-size: 26px;
    font-weight: 700;
    line-height: 1.3;
    text-align: center;
    text-wrap: balance;
}

/* ─── Before and after ────────────────────────────────────────────────── */

/* Runs edge to edge: the two figures are the page's opening image, and a
   gutter around them would frame them as an illustration inside an article. */
.compare {
    width: calc(100% + var(--gutter) * 2);
    margin-inline: calc(var(--gutter) * -1);
}

/* Labels, not a control. Both figures are on screen at once — the point is
   the difference between them, and a toggle showing one at a time would ask
   the visitor to hold the other in their head. */
.compare__tabs {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    padding: 0 var(--gutter) 10px;
}

.compare__tab {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 40px;
    padding: 8px;
    border-radius: 8px;
    background: var(--surface);
    box-shadow: 0 2px 10px rgba(5, 29, 51, 0.1);
    font-size: 18px;
    font-weight: 700;
    color: var(--ink);
}

/* The goal is the one being sold, so it is the one in the funnel's colour. */
.compare__tab--goal {
    color: var(--accent);
}

.compare__panes {
    display: grid;
    grid-template-columns: 1fr 1fr;
    /* The cut-outs are shot on their own near-white ground, so the two sit
       flush and read as one photograph split down the middle. */
    background: #f6f6f6;
}

.compare__figure {
    display: block;
    width: 100%;
    height: auto;
}

/* One row per trait, in the same two columns and the same order as the
   figures above, so the eye carries straight down from one to the other. */
.stats {
    width: 100%;
    border-collapse: collapse;
    table-layout: fixed;
}

.stats__row {
    border-bottom: 1px solid var(--line);
}

.stats__cell {
    display: table-cell;
    padding: 12px var(--gutter);
    text-align: left;
    vertical-align: top;
}

.stats__label {
    display: block;
    color: var(--ink-muted);
    font-size: 15px;
    line-height: 1.3;
}

.stats__value {
    display: block;
    margin-top: 2px;
    font-size: 19px;
    font-weight: 700;
    line-height: 1.2;
}

/* Three notches, filled to the level this side sits at. Decoration for the
   words above them rather than information of its own, so it is hidden from
   the accessibility tree and never needs a label. */
.stats__meter {
    display: flex;
    gap: 6px;
    margin-top: 8px;
}

.stats__notch {
    flex: 1;
    height: 7px;
    border-radius: var(--radius-pill);
    background: #f3c5b4;
}

.stats__notch.is-on {
    background: #dd6438;
}

/* ─── What they get ───────────────────────────────────────────────────── */

.benefits {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 22px;
    width: 100%;
}

.benefit {
    display: grid;
    grid-template-columns: 72px 1fr;
    align-items: center;
    gap: 16px;
    text-align: left;
}

.benefit__icon {
    width: 72px;
    height: 72px;
    border-radius: 50%;
    background: #f1f1f1;
}

.benefit__img {
    width: 72px;
    height: 72px;
    border-radius: 50%;
    object-fit: cover;
    flex: none;
}

.benefit__text {
    display: grid;
    gap: 2px;
}

.benefit__title {
    font-size: 16px;
    font-weight: 700;
    line-height: 1.3;
}

/* The half of the row that is about this visitor — their water figure, their
   calories, how soon they see it — carries the funnel's colour. */
.benefit__note {
    color: var(--accent);
    font-size: 16px;
    font-weight: 700;
    line-height: 1.3;
}

/* ─── Food scanner ────────────────────────────────────────────────────── */

.scanner {
    width: 100%;
    margin-top: 34px;
    padding: 16px;
    border: 2px solid var(--accent);
    border-radius: 20px;
}

.scanner__title {
    margin: 0 0 14px;
    font-size: 20px;
    font-weight: 700;
    line-height: 1.25;
    text-align: center;
    text-wrap: balance;
}

.scanner__body {
    display: grid;
    grid-template-columns: 1fr 1fr;
    align-items: center;
    gap: 14px;
}

/* The corner brackets are drawn here rather than baked into the picture, so
   swapping the photograph does not mean re-cutting the frame with it. */
.scanner__frame {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    aspect-ratio: 1;
    padding: 8px;
    border-radius: 12px;
    text-align: center;
}

.scanner__frame::before,
.scanner__frame::after {
    content: '';
    position: absolute;
    width: 34px;
    height: 34px;
    border: 3px solid #2fc46b;
}

.scanner__frame::before {
    top: 0;
    left: 0;
    border-right: 0;
    border-bottom: 0;
    border-radius: 10px 0 0 0;
}

.scanner__frame::after {
    right: 0;
    bottom: 0;
    border-top: 0;
    border-left: 0;
    border-radius: 0 0 10px 0;
}

/* Square, to sit inside the corner brackets: a circle reads as a portrait
   avatar, not as something a scanner is framing. */
.scanner__img {
    width: 100%;
    height: 100%;
    aspect-ratio: 1;
    border-radius: 10px;
    object-fit: cover;
}

.scanner__rows {
    margin: 0;
    display: grid;
    gap: 6px;
}

.scanner__row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    color: var(--accent);
    font-size: 17px;
    font-weight: 700;
}

.scanner__row dt,
.scanner__row dd {
    margin: 0;
    /* "76/94 г" is one figure; broken over two lines it reads as two. */
    white-space: nowrap;
}

.scanner__note {
    width: 100%;
    margin: 14px 0 0;
    color: var(--ink-muted);
    font-size: 15px;
    line-height: 1.4;
    text-align: left;
}

/* ─── The run's own answers, read back ────────────────────────────────── */

.chips {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
    width: 100%;
}

.chip {
    display: grid;
    grid-template-columns: 34px 1fr;
    align-items: center;
    gap: 10px;
    text-align: left;
}

.chip__icon {
    font-size: 28px;
    line-height: 1;
}

.chip__text {
    display: grid;
    gap: 1px;
}

.chip__label {
    font-size: 16px;
    font-weight: 700;
}

.chip__value {
    color: var(--ink-muted);
    font-size: 16px;
}

/* ─── The offer block ─────────────────────────────────────────────────── */

.offer {
    width: 100%;
    margin-top: 32px;
}

/* Deadline on one side, price on the other. Side by side rather than stacked
   because they are one argument: this much, until this runs out. */
.offer__deal {
    display: grid;
    grid-template-columns: 1fr 1fr;
    align-items: center;
    gap: 14px;
    margin-bottom: 18px;
}

.offer__urgency {
    text-align: center;
}

.offer__deadline {
    margin: 0;
    font-size: 22px;
    font-weight: 700;
    line-height: 1.3;
}

.offer__price {
    display: flex;
    align-items: baseline;
    justify-content: center;
    gap: 8px;
    margin: 0 0 14px;
}

.offer--repeat {
    margin-top: 8px;
}

/* ─── The price plaque ────────────────────────────────────────────────── */

.price {
    position: relative;
    display: grid;
    justify-items: center;
    gap: 2px;
    margin: 0;
    padding: 14px 12px 10px;
    border: 2px solid #f6ccd0;
    border-radius: 8px;
    /* The ribbon overhangs the top-left corner; without this it is clipped by
       whatever the plaque happens to sit next to. */
    overflow: visible;
}

/* No old price to compare against: the plaque has nothing to shout about, so
   it stops being a plaque. */
.price--plain {
    border: 0;
    padding: 0;
}

/* Crosses the top-left corner, which is why the struck price sets itself to
   the right: the two overlap otherwise and neither can be read. */
.price__ribbon {
    position: absolute;
    top: 14px;
    left: -16px;
    z-index: 1;
    padding: 4px 12px;
    background: #d32f2f;
    color: #fff;
    font-size: 13px;
    font-weight: 700;
    line-height: 1.1;
    text-transform: uppercase;
    transform: rotate(-20deg);
    white-space: nowrap;
}

.price__was {
    justify-self: end;
    color: #8a2b23;
    font-size: 18px;
    font-weight: 700;
    /* Struck by the ribbon's own angle rather than a flat line, which is what
       makes it read as crossed out by hand. */
    text-decoration: line-through;
    text-decoration-color: #d32f2f;
    text-decoration-thickness: 2px;
}

.price__now {
    color: #d32f2f;
    font-size: 38px;
    font-weight: 700;
    line-height: 1.05;
}

.price--plain .price__now {
    color: var(--ink);
    font-size: 40px;
}

.price__period {
    color: var(--ink-muted);
    font-size: 15px;
    line-height: 1.2;
    text-align: center;
}

/* The figure above is not what they go on paying, so this is set to be read
   rather than skipped: same colour as the price, just smaller. */
.price__renews {
    margin-top: 2px;
    color: var(--ink);
    font-size: 13px;
    font-weight: 700;
    line-height: 1.2;
    text-align: center;
}

/* ─── Payment block ───────────────────────────────────────────────────── */

.pay {
    width: 100%;
    /* The offer bar links here and covers the top of the screen: without this
       the anchor lands on the card fields with the heading behind the bar. */
    scroll-margin-top: calc(var(--safe-top) + var(--offerbar-h) + 12px);
}

.pay__methods {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 10px;
    width: 100%;
}

.pay__method {
    display: grid;
    grid-template-columns: 44px 1fr;
    align-items: center;
    gap: 12px;
    width: 100%;
    min-height: 60px;
    padding: 12px 16px;
    border: 1px solid var(--line);
    border-radius: var(--radius-card);
    background: var(--surface);
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
    touch-action: manipulation;
    transition: border-color 0.12s ease, background 0.12s ease;
}

.pay__method:active {
    border-color: var(--accent);
    background: color-mix(in srgb, var(--accent) 6%, var(--surface));
}

.pay__mark {
    width: 44px;
    height: 28px;
    border-radius: 6px;
    background: #f1f1f1;
}

.pay__name {
    font-size: 16px;
    font-weight: 700;
}

.pay__stripe {
    width: 100%;
    margin-bottom: 14px;
    text-align: left;
}

/* The methods, as a list of radios with one panel open at a time. Card fields
   folded away behind a row rather than laid out in the open: the wallet above
   them is one press, and a form on screen is what makes it look like work. */
.paylist {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 10px;
    width: 100%;
}

.paylist__item {
    border: 1px solid var(--line);
    border-radius: var(--radius-card);
    background: var(--surface);
}

.paylist__item[hidden] {
    display: none;
}

.paylist__head {
    display: flex;
    align-items: center;
    gap: 14px;
    width: 100%;
    min-height: 56px;
    padding: 12px 16px;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
    touch-action: manipulation;
}

/* Drawn rather than an <input>: the row is a button, and a real radio inside a
   button is a control inside a control. aria-checked on the head carries the
   state to anything not looking at the page. */
.paylist__radio {
    position: relative;
    flex: none;
    width: 22px;
    height: 22px;
    border: 2px solid #c9c9c9;
    border-radius: 50%;
}

.is-on > .paylist__head .paylist__radio {
    border-color: var(--ink);
}

.is-on > .paylist__head .paylist__radio::after {
    content: '';
    position: absolute;
    inset: 3px;
    border-radius: 50%;
    background: var(--ink);
}

.paylist__label {
    font-size: 16px;
    font-weight: 700;
}

/* A strip of card marks, sized by height so the artwork can be any width. */
.paylist__brands {
    height: 26px;
    width: auto;
    max-width: 100%;
}

.paylist__body {
    display: none;
    padding: 0 16px 16px;
}

.is-on > .paylist__body {
    display: block;
}

.paylist__body .btn {
    margin-top: 14px;
}

/* Stripe renders its own fields inside an iframe; this only reserves the room
   so the block does not jump as it loads. */
.pay__element {
    min-height: 220px;
}

.pay__error {
    margin: 10px 0 0;
    color: #c0392b;
    font-size: 14px;
    line-height: 1.4;
}

.pay__error:empty {
    display: none;
}

/* Under the button that commits the money, where the reassurance is wanted. */
.pay__note {
    width: 100%;
    margin: 14px 0 0;
    font-size: 15px;
    line-height: 1.4;
    text-align: center;
}

/* The billing terms sit directly under the reassurance line, so they are set
   the same way. Elsewhere .legal runs left under a form field. */
.pay .legal {
    margin-top: 8px;
    text-align: center;
}

/* ─── Reviews ─────────────────────────────────────────────────────────── */

/*
 * One review at a time, the rest turning over behind it. Three reviews down the
 * page is three screenfuls between the offer and the guarantee; one card costs
 * a third of that, and the reader keeps their place in the page.
 *
 * A card fills the column rather than leaving a sliver of the next one: with
 * the rail turning over by itself the overhang is no longer what says there is
 * more to read — the dots underneath say it, and a single centred card reads
 * cleaner. Snapping is mandatory so a flick always lands on a card rather than
 * halfway between two.
 */
.reviews {
    list-style: none;
    margin: 0;
    /* Room on all four sides for the card's shadow. Without the side padding
       the scroll box clips it, and the halo ends in a straight grey edge that
       reads as a panel behind the card rather than as a shadow under it. */
    padding: 6px 12px 12px;
    display: flex;
    /* Wider than it looks like it needs to be: the next card's shadow reaches
       back about 16px, and anything less lets that halo creep past the right
       edge of the one on screen. */
    gap: 36px;
    width: 100%;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    /* The bar is noise on a three-card rail: the overhang already says it
       scrolls, and on a phone there is no bar to hide anyway. */
    scrollbar-width: none;
}

.reviews::-webkit-scrollbar {
    display: none;
}

/* Stretched to the tallest card by the flex default rather than sized to its
   own text: a rail that changed height every few seconds would push the whole
   page around under the reader. */
.review {
    flex: 0 0 100%;
    scroll-snap-align: center;
    padding: 20px;
    border-radius: 12px;
    background: var(--surface);
    box-shadow: 0 6px 24px 4px rgba(5, 29, 51, 0.08);
    text-align: left;
}

/* No wide variant on purpose: the screen column is capped near a phone's width
   whatever the viewport does, so three cards abreast would be three slivers.
   The rail is the layout everywhere. */

/* Says the rail can be dragged, on the one input that needs telling. */
.reviews {
    cursor: grab;
}

.reviews.is-dragging {
    cursor: grabbing;
    /* A drag across text is a drag, not a selection. */
    user-select: none;
}

/* ─── Rail dots ───────────────────────────────────────────────────────── */

.rail-dots {
    list-style: none;
    display: flex;
    justify-content: center;
    gap: 8px;
    margin: 4px 0 0;
    padding: 0;
    width: 100%;
}

.rail-dots[hidden] {
    display: none;
}

/* Bigger than it looks: the dot is 8px, the button around it is a thumb. */
.rail-dots__dot {
    display: block;
    width: 24px;
    height: 24px;
    padding: 8px;
    border: 0;
    background: none;
    cursor: pointer;
    touch-action: manipulation;
}

.rail-dots__dot::before {
    content: '';
    display: block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #d9d9d9;
    transition: background 0.15s ease;
}

.rail-dots__dot.is-on::before {
    background: var(--accent);
}

.review__title {
    margin: 0 0 8px;
    font-size: 20px;
    font-weight: 700;
    line-height: 1.2;
}

.review__stars {
    display: flex;
    gap: 2px;
    margin: 0 0 8px;
}

.star {
    width: 20px;
    height: 20px;
    /* Amber rather than the funnel's pink: a rating people recognise at a
       glance is the one that looks like every other rating they have seen. */
    fill: #ffa230;
}

.star--empty {
    fill: #e2e2e2;
}

.review__body {
    margin: 0 0 12px;
    color: var(--ink-muted);
    font-size: 16px;
    line-height: 1.5;
}

.review__by {
    margin: 0;
    font-size: 16px;
    font-weight: 700;
}

/* The claim the reviews imply, stated plainly and in the small print it
   belongs in. */
.reviews__note {
    width: 100%;
    margin: 20px 0 0;
    font-size: 16px;
    line-height: 1.45;
    text-align: left;
}

/* ─── Questions ───────────────────────────────────────────────────────── */

.faq {
    list-style: none;
    margin: 0;
    padding: 0;
    width: 100%;
}

.faq__item {
    padding: 14px 0;
    border-bottom: 1px solid var(--line);
    text-align: left;
}

.faq__item summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    font-size: 20px;
    font-weight: 700;
    line-height: 1.35;
    cursor: pointer;
    list-style: none;
}

.faq__item summary::-webkit-details-marker {
    display: none;
}

/* A chevron drawn from two borders, so it can be rotated on open rather than
   swapped for a different glyph. */
.faq__item summary::after {
    content: '';
    flex: none;
    width: 11px;
    height: 11px;
    margin-bottom: 4px;
    border-right: 2px solid var(--ink);
    border-bottom: 2px solid var(--ink);
    transform: rotate(45deg);
    transition: transform 0.15s ease;
}

.faq__item[open] summary::after {
    margin-bottom: 0;
    transform: rotate(225deg);
}

.faq__item p {
    margin: 10px 0 0;
    color: var(--ink-muted);
    font-size: 16px;
    line-height: 1.5;
}

/* ─── Guarantee ───────────────────────────────────────────────────────── */

.guarantee-badge {
    display: grid;
    justify-items: center;
    width: 100%;
    margin-top: 32px;
    padding-top: 28px;
    border-top: 1px solid var(--line);
    text-align: center;
}

.guarantee-badge__img {
    width: 160px;
    height: 160px;
    object-fit: contain;
}

.guarantee-badge__mark {
    width: 160px;
    height: 160px;
    border-radius: 50%;
    background: #e6f2ea;
}

.guarantee-badge__title {
    margin: 16px 0 12px;
    font-size: 22px;
    font-weight: 700;
    line-height: 1.25;
    text-wrap: balance;
}

.guarantee-badge p {
    margin: 0;
    color: var(--ink-muted);
    font-size: 16px;
    line-height: 1.5;
}

/* ─── Page foot ───────────────────────────────────────────────────────── */

.sitefoot {
    width: 100%;
    margin-top: 28px;
    padding-top: 20px;
    border-top: 1px solid var(--line);
    text-align: center;
}

.sitefoot__links {
    list-style: none;
    margin: 0 0 6px;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 6px 24px;
}

.sitefoot a {
    color: inherit;
}

.sitefoot li,
.sitefoot p {
    margin: 0;
    font-size: 16px;
    line-height: 1.5;
}

/* ─── Paywall: shared bits ────────────────────────────────────────────── */

.timer {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    margin: 16px 0 4px;
    padding: 10px 16px;
    border-radius: var(--radius-pill);
    background: rgba(255, 209, 209, 0.35);
    font-size: 15px;
}

.timer__clock {
    font-weight: 700;
    color: var(--accent);
    font-variant-numeric: tabular-nums;
}

.perks {
    list-style: none;
    margin: 16px 0 0;
    padding: 0;
    display: grid;
    gap: 8px;
    width: 100%;
    text-align: left;
}

.perks li {
    display: grid;
    grid-template-columns: 20px 1fr;
    gap: 10px;
    font-size: 15px;
}

.perks li::before {
    content: '✓';
    color: var(--accent);
    font-weight: 700;
}

.plans {
    list-style: none;
    margin: 20px 0 0;
    padding: 0;
    display: grid;
    gap: 10px;
    width: 100%;
}

.plan {
    position: relative;
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    row-gap: 2px;
    min-height: var(--tap);
    padding: 16px;
    border: 1px solid var(--line);
    border-radius: var(--radius-card);
    text-align: left;
    cursor: pointer;
    touch-action: manipulation;
    transition: border-color 0.12s ease;
}

.plan input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}

.plan:has(:checked) {
    border-color: var(--accent);
    box-shadow: 0 0 0 1px var(--accent);
}

/* A featured plan needs room for the badge sitting on its top edge. */
.plan--featured {
    margin-top: 10px;
}

.plan__badge {
    position: absolute;
    top: -10px;
    left: 16px;
    padding: 2px 10px;
    border-radius: var(--radius-pill);
    background: var(--accent);
    color: #fff;
    font-size: 12px;
    font-weight: 700;
}

.plan__title {
    font-weight: 700;
    font-size: 17px;
}

.plan__price {
    grid-row: 1 / 3;
    grid-column: 2;
    text-align: right;
}

.plan__price b {
    font-size: 19px;
}

.plan__old {
    display: block;
    color: var(--ink-muted);
    font-size: 14px;
}

.plan__perday {
    color: var(--ink-muted);
    font-size: 14px;
}

.guarantee {
    margin: 16px 0 0;
    color: var(--ink-muted);
    font-size: 14px;
    line-height: 1.4;
}

/* ─── Upsell ──────────────────────────────────────────────────────────── */

.slot--wide {
    aspect-ratio: 4 / 3;
    width: 100%;
}

.upsell__price {
    display: flex;
    align-items: baseline;
    justify-content: center;
    gap: 10px;
    margin: 20px 0 0;
}

.upsell__price b {
    font-size: 28px;
}

.upsell__price s {
    color: var(--ink-muted);
}

.upsell__actions {
    display: grid;
    gap: 10px;
    width: 100%;
    margin-top: 20px;
}

.btn--quiet {
    background: transparent;
    color: var(--ink-muted);
    font-weight: 400;
    text-transform: none;
    letter-spacing: 0;
    min-height: var(--tap);
}

.btn--quiet:active {
    background: rgba(0, 0, 0, 0.04);
}

/* ─── Larger screens: keep it a phone-shaped column ───────────────────── */

@media (min-width: 520px) {
    body {
        max-width: 420px;
        margin-inline: auto;
        border-inline: 1px solid var(--line);
    }
}

@media (prefers-reduced-motion: reduce) {
    * {
        transition: none !important;
    }
}
