/* ============================================================================
   site_landing.css — the landing page at `/`.

   Deliberately self-contained and namespaced `lp-`. The ads landing page at
   /main still runs on site_main.css, and the two must not be able to break each
   other: a page that paid traffic lands on should never regress because of an
   edit to the organic one.
   ========================================================================== */

:root {
    /* Straight off the logo (static/images/logo_igni.svg): the flame is a radial
       gradient from #EA7455 to #A33A97, and the wordmark is black. Those two stops
       are the whole brand palette — nothing else on this page invents a hue.

       The division of labour between them is a contrast one, not a taste one.
       Coral on white is about 2.9:1, which is unreadable for text at any size, so
       coral is only ever used for fills, washes, rules and the warm end of a
       gradient. Plum is 4.6:1 and carries every piece of colored text. */
    --lp-coral:         #EA7455;
    --lp-plum:          #A33A97;
    --lp-plum-deep:     #8C3181;   /* hover / pressed */

    /* The flame's gradient. The coral stop is placed off the left edge at -70% on
       purpose: pure coral under white text is 2.9:1, so the button never actually
       reaches it. What is painted runs from roughly #BC4F80 to plum, which keeps
       white legible across the whole control while still reading as the warm-to-cool
       sweep of the logo. Do not move that stop back to 0%. */
    --lp-brand-grad:    linear-gradient(100deg, var(--lp-coral) -70%, var(--lp-plum) 58%);

    --lp-tint:          #FAEFF7;   /* plum wash  */
    --lp-tint-warm:     #FDF0EA;   /* coral wash */

    --lp-ink:           #16181D;
    --lp-ink-2:         #3A3F47;
    --lp-muted:         #6B7280;
    --lp-line:          #E7E3DE;

    --lp-paper:         #FFF8F4;   /* warm hero paper, tinted with the flame's coral */
    --lp-bg:            #FAF8F5;
    --lp-card:          #FFFFFF;

    --lp-radius:        18px;
    --lp-radius-lg:     28px;
    --lp-shadow:        0 2px 4px rgba(22, 24, 29, 0.04),
                        0 12px 32px rgba(22, 24, 29, 0.07);
    --lp-shadow-lg:     0 4px 10px rgba(22, 24, 29, 0.05),
                        0 28px 70px rgba(22, 24, 29, 0.12);

    --lp-wrap:          1120px;
    --lp-gutter:        24px;
    --lp-header-h:      68px;

    /* The split hero is one screenful: header + padding + film = the viewport. The
       film is then sized by HEIGHT and its width derived, which is the only way a
       portrait film can be guaranteed to land fully on screen. --lp-ar is that
       film's width/height, replaced by the real figure once the file loads. */
    --lp-hero-pad-y:    clamp(32px, 4.5vh, 56px);
    --lp-media-max:     480px;
    --lp-ar:            0.8;       /* 4:5 — see static/videos/README.md */

    --lp-sans:          -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
}

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

html {
    scroll-behavior: smooth;
    /* Anchor links (#how-it-works, #faq) must not slide under the sticky header. */
    scroll-padding-top: calc(var(--lp-header-h) + 16px);
    -webkit-text-size-adjust: 100%;
}

body {
    margin: 0;
    font-family: var(--lp-sans);
    color: var(--lp-ink);
    background: var(--lp-bg);
    overflow-x: hidden;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
}

img, svg, video { display: block; max-width: 100%; }
a { color: inherit; }

.lp-wrap {
    width: 100%;
    max-width: var(--lp-wrap);
    margin: 0 auto;
    padding: 0 var(--lp-gutter);
}
.lp-wrap-narrow { max-width: 780px; }

/* The graph paper igni is built on. Two grids, 20px and 100px, same as the app. */
.lp-paper-grid {
    background-image:
        linear-gradient(rgba(234, 116, 85, 0.08) 1px, transparent 1px),
        linear-gradient(90deg, rgba(234, 116, 85, 0.08) 1px, transparent 1px),
        linear-gradient(rgba(234, 116, 85, 0.04) 1px, transparent 1px),
        linear-gradient(90deg, rgba(234, 116, 85, 0.04) 1px, transparent 1px);
    background-size: 20px 20px, 20px 20px, 100px 100px, 100px 100px;
}

.lp-skip {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 1000;
    padding: 12px 18px;
    background: var(--lp-ink);
    color: #fff;
    border-radius: 0 0 10px 0;
    text-decoration: none;
}
.lp-skip:focus { left: 0; }

/* ── Buttons ──────────────────────────────────────────────────────────────── */

.lp-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 9px;
    padding: 12px 22px;
    border: 1px solid transparent;
    border-radius: 999px;
    font-family: inherit;
    font-size: 0.95rem;
    font-weight: 600;
    line-height: 1.2;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    transition: transform 0.18s ease, background-color 0.18s ease,
                box-shadow 0.18s ease, color 0.18s ease;
}
.lp-btn svg {
    width: 18px;
    height: 18px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.lp-btn-dark {
    background: var(--lp-ink);
    color: #fff;
}
.lp-btn-dark:hover { background: #000; transform: translateY(-1px); }

.lp-btn-primary {
    background: var(--lp-brand-grad);
    /* The gradient is painted larger than the button so the hover can slide it
       rather than cross-fade two backgrounds — a gradient cannot be transitioned,
       but background-position can. */
    background-size: 160% 100%;
    background-position: 0% 0;
    color: #fff;
    box-shadow: 0 6px 18px rgba(163, 58, 151, 0.3);
    transition: transform 0.18s ease, background-position 0.4s ease,
                box-shadow 0.18s ease;
}
.lp-btn-primary:hover {
    background-position: 100% 0;
    transform: translateY(-1px);
    box-shadow: 0 10px 26px rgba(163, 58, 151, 0.38);
}

.lp-btn-lg { padding: 16px 30px; font-size: 1.05rem; }

.lp-btn:focus-visible,
.lp-faq-q:focus-visible,
.lp-header-link:focus-visible,
a:focus-visible {
    outline: 3px solid var(--lp-plum);
    outline-offset: 3px;
}

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

.lp-header {
    position: sticky;
    top: 0;
    z-index: 100;
    height: var(--lp-header-h);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 0 clamp(16px, 4vw, 44px);
    background: rgba(255, 249, 245, 0.82);
    backdrop-filter: saturate(160%) blur(12px);
    -webkit-backdrop-filter: saturate(160%) blur(12px);
    border-bottom: 1px solid transparent;
    transition: border-color 0.2s ease, background-color 0.2s ease;
}
/* Set by site_landing.js once the page is scrolled: the header only needs to
   separate itself from the content when there is content behind it. */
.lp-header.is-stuck {
    border-bottom-color: var(--lp-line);
    background: rgba(255, 249, 245, 0.94);
}

.lp-header-logo { display: block; line-height: 0; }
.lp-header-logo img { width: 104px; height: auto; }

.lp-header-nav {
    display: flex;
    align-items: center;
    gap: clamp(8px, 2vw, 26px);
}

.lp-header-link {
    font-size: 0.93rem;
    font-weight: 500;
    color: var(--lp-ink-2);
    text-decoration: none;
    transition: color 0.18s ease;
}
.lp-header-link:hover { color: var(--lp-plum); }

/* ── Part 1: hero ─────────────────────────────────────────────────────────── */

.lp-hero {
    position: relative;
    background: var(--lp-paper);
    background-image:
        linear-gradient(rgba(234, 116, 85, 0.08) 1px, transparent 1px),
        linear-gradient(90deg, rgba(234, 116, 85, 0.08) 1px, transparent 1px),
        linear-gradient(rgba(234, 116, 85, 0.04) 1px, transparent 1px),
        linear-gradient(90deg, rgba(234, 116, 85, 0.04) 1px, transparent 1px);
    background-size: 20px 20px, 20px 20px, 100px 100px, 100px 100px;
    padding: clamp(40px, 7vw, 86px) 0 clamp(48px, 7vw, 92px);
    overflow: hidden;
}

.lp-hero-inner {
    width: 100%;
    max-width: var(--lp-wrap);
    margin: 0 auto;
    padding: 0 var(--lp-gutter);
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: clamp(32px, 4.5vw, 52px);
}

/* The copy is centered but still measured: a 1120px-wide line of body text is
   unreadable however nicely it is centered. */
.lp-hero-copy {
    max-width: 760px;
}

/* ── Split hero (hero_video.frame == 'phone') ───────────────────────────────
   Copy left, phone right. The copy column gets the larger share because the
   phone is a fixed 320px and does not benefit from more room, while the
   headline does. */
.lp-hero-split .lp-hero-inner {
    display: grid;
    grid-template-columns: minmax(0, 1.12fr) minmax(0, 0.88fr);
    align-items: center;
    text-align: left;
    gap: clamp(28px, 4.6vw, 68px);
}

/* The hero alone runs wider than the 1120px the rest of the page uses. At 1120 the
   two columns plus the gutter came to 1067 of the 1072 available — the row was
   full to the edges, which is what made it feel cramped rather than composed. The
   film is capped at 480 and centers in its column, so the extra width all goes to
   the headline and to the space between them. */
.lp-hero-split .lp-hero-inner { max-width: 1180px; }
.lp-hero-split .lp-hero-copy { max-width: none; }
.lp-hero-split .lp-hero-actions { justify-content: flex-start; }
.lp-hero-split .lp-sub { margin-left: 0; margin-right: 0; max-width: 36ch; }
/* The split headline lives in a ~520-560px column, not a 760px one. */
.lp-hero-split .lp-h1 { font-size: clamp(2.3rem, 4.9vw, 3.5rem); }

/* Without the phone there is no fixed 320px object on the right, so the film can
   take a fairer share of the row — and it needs it: a portrait film that carries
   its own titles is only legible from about 460px up. */
.lp-hero-plain .lp-hero-inner {
    grid-template-columns: minmax(0, 1.04fr) minmax(0, 0.96fr);
}

.lp-h1 {
    margin: 0 0 18px;
    /* Capped so the hard break after "a" is the only break: any larger and the
       first line stops fitting the 760px copy column and the browser wraps it
       again, stranding "a" on a line of its own. */
    font-size: clamp(2.3rem, 5.4vw, 4.1rem);
    font-weight: 700;
    line-height: 1.05;
    letter-spacing: -0.03em;
}
/* The accent word in each headline. It used to be set in a serif italic, which
   gave the page an editorial, newspaper voice igni does not have. One typeface
   now runs the whole page and the accent is carried by the logo's gradient
   instead — the same two stops as the flame, read left to right.

   background-clip: text needs a transparent fill to show through, and a browser
   that does not support it would paint nothing at all, so the plum is declared
   first as the fallback and only overridden inside @supports. */
.lp-h1 em,
.lp-h2 em {
    font-style: normal;
    font-weight: 700;
    letter-spacing: inherit;
    color: var(--lp-plum);
}
@supports (background-clip: text) or (-webkit-background-clip: text) {
    .lp-h1 em,
    .lp-h2 em {
        background: linear-gradient(96deg, var(--lp-coral) 0%, var(--lp-plum) 72%);
        -webkit-background-clip: text;
        background-clip: text;
        color: transparent;
        /* A descender sitting on the clip edge gets shaved off in WebKit; the
           padding gives it room and the matching negative margin keeps the word
           on the same baseline rhythm as the rest of the line. */
        padding-right: 0.06em;
        margin-right: -0.06em;
    }
}

.lp-sub {
    margin: 0 auto 32px;
    max-width: 46ch;
    font-size: clamp(1.05rem, 1.7vw, 1.2rem);
    color: var(--lp-muted);
}

.lp-hero-actions {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 14px 24px;
}
.lp-hero-secondary {
    font-size: 0.97rem;
    font-weight: 600;
    color: var(--lp-ink-2);
    text-decoration: none;
    border-bottom: 1.5px solid rgba(22, 24, 29, 0.2);
    padding-bottom: 2px;
    transition: color 0.18s ease, border-color 0.18s ease;
}
.lp-hero-secondary:hover {
    color: var(--lp-plum);
    border-bottom-color: var(--lp-plum);
}

/* The hero film.

   It arrives already designed — rounded corners, its own pale lavender ground, a
   coral-to-plum edge — so the page adds almost nothing around it. A heavy frame
   here would be a second frame around a frame. Just a soft shadow to lift it off
   the paper, and a brand-tinted wash behind it so the film's own edge glow has
   something to melt into rather than stopping dead on the grid. */
.lp-hero-media {
    position: relative;
    width: 100%;
    max-width: 980px;
}

/* ── Bare film, beside the copy ──────────────────────────────────────────────
   No bezel: the film is simply a card. That is the right call whenever the film
   has a design of its own — a drawn phone around a piece that already has its own
   frame is a frame around a frame, and it costs the picture a third of its width
   for nothing.

   The same reasoning governs everything else here, and it is the whole rule for
   this slot: **the film arrives finished, so the page adds as little as possible
   around it.** It brings its own pale ground, its own rounded corners and its own
   coral-to-plum edge. A halo behind it put a second gradient against that one and
   the two fought; a heavy drop shadow made a designed asset look pasted onto the
   page; a large radius cropped the corners the artwork already had, leaving a
   double round; an inset hairline added a third line beside the film's own border.
   All four are gone. What is left is a radius close to the artwork's own and a
   shadow soft enough to seat the card on the paper without announcing itself.

   The trade is height. A portrait film 480px wide is around 600px tall, so the
   hero is a tall row; the copy sits centered against it rather than trying to
   fill it. */
.lp-hero-media-plain {
    max-width: none;
    display: flex;
    justify-content: center;
}

.lp-video-plain {
    position: relative;
    z-index: 2;
    width: 100%;
    max-width: var(--lp-media-max);
    border-radius: 18px;            /* close to the artwork's own corners */
    box-shadow: 0 1px 2px rgba(22, 24, 29, 0.04),
                0 14px 36px rgba(22, 24, 29, 0.09);
    background: transparent;        /* a designed film brings its own ground */
    aspect-ratio: 4 / 5;            /* replaced by the file's real ratio on load */
}

/* ── The phone ──────────────────────────────────────────────────────────────
   A drawn device, so what goes inside it has to be a plain screen recording.
   The screen is 300 CSS px wide: anything composited around the app — a logo, a
   chapter title, a paragraph, a photo of a desk — lands at single-digit pixel
   sizes in here, and a photographed device inside a drawn one reads as an error.
   See static/videos/README.md for the recording spec this slot implies. */
.lp-hero-media-phone {
    max-width: none;
    display: flex;
    justify-content: center;
}

.lp-phone {
    position: relative;
    z-index: 2;
    width: min(320px, 78vw);
    padding: 10px;
    border-radius: 46px;
    background: linear-gradient(165deg, #2B2F36 0%, #15171B 60%);
    box-shadow: var(--lp-shadow-lg), 0 0 0 1px rgba(0, 0, 0, 0.3) inset;
}
.lp-phone-notch {
    position: absolute;
    top: 20px;
    left: 50%;
    transform: translateX(-50%);
    width: 88px;
    height: 20px;
    border-radius: 999px;
    background: #0B0C0E;
    z-index: 4;
}

.lp-video-framed {
    aspect-ratio: 9 / 19.5;
    border-radius: 36px;
    overflow: hidden;
    background: #EFEAE4;
}

/* The brand halo behind the phone. Decorative, and it sits under the frame. */
/* Only the phone keeps the halo: a drawn bezel has no ground of its own, so it
   needs something behind it. A finished film does not — see above. */
.lp-hero-media-phone::before {
    content: "";
    position: absolute;
    z-index: 1;
    top: 50%;
    left: 50%;
    width: min(620px, 150%);
    aspect-ratio: 1;
    transform: translate(-50%, -50%);
    background:
        radial-gradient(circle at 60% 40%, rgba(234, 116, 85, 0.3) 0%, rgba(234, 116, 85, 0) 58%),
        radial-gradient(circle at 40% 62%, rgba(163, 58, 151, 0.24) 0%, rgba(163, 58, 151, 0) 60%);
    pointer-events: none;
}

.lp-video-hero {
    position: relative;
    z-index: 2;
    border-radius: var(--lp-radius-lg);
    box-shadow: var(--lp-shadow-lg);
    background: transparent;   /* the film brings its own ground */
    /* Replaced by the film's true ratio on loadedmetadata (site_landing.js). This
       is only here so the page does not jump when it arrives. */
    aspect-ratio: 16 / 9;
}

.lp-video-hero::after {
    /* The film's corners are rounded in the artwork as well as by this rule, and a
       1px seam of raw video can show between the two on fractional device pixels.
       A hairline inset ring covers it without darkening the image. */
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    box-shadow: inset 0 0 0 1px rgba(22, 24, 29, 0.07);
    pointer-events: none;
}

.lp-hero-media-wide::before {
    content: "";
    position: absolute;
    z-index: 1;
    inset: -14% -8%;
    background:
        radial-gradient(60% 55% at 72% 30%, rgba(234, 116, 85, 0.26) 0%, rgba(234, 116, 85, 0) 70%),
        radial-gradient(60% 55% at 28% 72%, rgba(163, 58, 151, 0.22) 0%, rgba(163, 58, 151, 0) 72%);
    pointer-events: none;
}

/* ── Sound toggle ───────────────────────────────────────────────────────────
   The film carries narration, but it has to start muted — no browser will
   autoplay audio, and one that did would be worse. So the control is not a
   decoration: it is the only way the sound is ever reachable, which is why it
   is a real labeled button rather than a bare icon. */
.lp-video-sound {
    position: absolute;
    z-index: 3;
    right: 14px;
    bottom: 14px;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 9px 15px;
    border: 1px solid rgba(255, 255, 255, 0.5);
    border-radius: 999px;
    background: rgba(22, 24, 29, 0.6);
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
    color: #fff;
    font-family: inherit;
    font-size: 0.82rem;
    font-weight: 600;
    line-height: 1;
    cursor: pointer;
    transition: background-color 0.18s ease, transform 0.18s ease;
}
.lp-video-sound:hover { background: rgba(22, 24, 29, 0.8); transform: translateY(-1px); }
.lp-video-framed .lp-video-sound {
    right: 10px;
    bottom: 14px;
    padding: 7px 12px;
    font-size: 0.74rem;
    gap: 6px;
}
.lp-video-framed .lp-video-sound svg { width: 14px; height: 14px; }
.lp-video-sound svg {
    width: 17px;
    height: 17px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.9;
    stroke-linecap: round;
    stroke-linejoin: round;
}
/* aria-pressed is the single source of truth for which icon shows, so the button's
   accessible state and its picture cannot drift apart. */
.lp-video-sound .lp-icon-loud,
.lp-video-sound[aria-pressed="true"] .lp-icon-muted { display: none; }
.lp-video-sound[aria-pressed="true"] .lp-icon-loud { display: block; }

/* Hidden while the slot has fallen back to a poster or a placeholder: there is no
   audio to turn on. */
.lp-video.is-fallen-back .lp-video-sound { display: none; }

/* ── Video slots ──────────────────────────────────────────────────────────── */
/*
   Three states, in order of preference, all handled by site_landing.js:
     1. the <video> plays
     2. the file is missing  -> the poster image is shown in its place
     3. the poster is missing too -> a labeled dashed box naming the file
   State 3 is what lets the whole page be reviewed before any asset exists.
*/
.lp-video {
    position: relative;
    width: 100%;
    background: #EFEAE4;
    overflow: hidden;
}
.lp-video video,
.lp-video img.lp-video-poster {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.lp-video-portrait { aspect-ratio: 9 / 19.5; }
.lp-video-landscape {
    aspect-ratio: 4 / 3;
    border-radius: var(--lp-radius);
    border: 1px solid var(--lp-line);
}

.lp-video-fallback {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: 18px;
    text-align: center;
    background:
        repeating-linear-gradient(45deg,
            rgba(234, 116, 85, 0.06) 0 12px,
            rgba(234, 116, 85, 0.13) 12px 24px);
    color: var(--lp-ink-2);
}
.lp-video-fallback::before {
    content: "▶";
    display: grid;
    place-items: center;
    width: 46px;
    height: 46px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.9);
    color: var(--lp-plum);
    font-size: 1.1rem;
    box-shadow: var(--lp-shadow);
}
.lp-video-fallback code {
    font-size: 0.78rem;
    font-weight: 600;
    word-break: break-all;
    opacity: 0.85;
}
.lp-video-fallback span { font-size: 0.75rem; opacity: 0.6; }

/* ── Subject carousel ─────────────────────────────────────────────────────── */
/*
   It sits at the top of the hero copy, where three generic chips used to. The rail
   takes the width of whatever holds it — the copy column in the split hero — so
   nothing about its size is hard-coded here and moving it again is a markup change
   and nothing else.

   Deliberately no card around the pills. A mask applies to an element's own
   background and border as well as its contents, so a container here would have its
   two ends dissolved along with the pills — the edges go soft and the whole thing
   reads as a rendering fault. The pills carry their own fill and the fade is the
   only edge.
*/
.lp-subjects-rail {
    position: relative;
    width: 100%;
    overflow: hidden;
    /* Fades the pills out at both ends instead of cutting them off mid-word. Both
       ends need it: the track travels leftwards, so the left edge is where pills
       leave and the right is where they arrive, and a hard cut at either reads as
       a clipped box rather than a moving strip.

       The fade has to be at least one pill wide, or a pill is still legible at the
       moment it meets the boundary and the strip reads as clipped rather than as
       moving. Pills are ~95px and the rail is ~550px, so 22% is the floor here —
       shrink the pills further and this can come down with them, but the two
       numbers have to move together. */
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 22%, #000 74%, transparent);
    mask-image: linear-gradient(90deg, transparent, #000 22%, #000 74%, transparent);
}

.lp-hero-subjects {
    margin-bottom: 16px;
    padding: 3px 0 5px;   /* room for the pills' shadow, which the mask would clip */
}

.lp-subjects-track {
    display: flex;
    width: max-content;
    animation: lp-marquee 48s linear infinite;
}
.lp-subjects-rail:hover .lp-subjects-track { animation-play-state: paused; }

.lp-subjects-list {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 0;
    padding: 0 6px;
    list-style: none;
}
.lp-subject {
    /* Smaller than they were. Sitting directly above a 3.5rem headline, pills set
       at body size competed with it; at this size they read as a label strip,
       which is what they are. It also lets more of them be legible at once between
       the two fades. */
    padding: 6px 14px;
    border: 1px solid var(--lp-line);
    border-radius: 999px;
    /* White, not the page fill: with no container behind them the pills are the
       only thing separating this strip from the background. */
    background: var(--lp-card);
    box-shadow: 0 1px 2px rgba(22, 24, 29, 0.04);
    font-size: 0.82rem;
    font-weight: 600;
    letter-spacing: 0.005em;
    color: var(--lp-ink-2);
    white-space: nowrap;
}

@keyframes lp-marquee {
    from { transform: translateX(0); }
    to   { transform: translateX(-50%); }   /* exactly one of the two copies */
}

/* ── Part 2: social proof ─────────────────────────────────────────────────── */

.lp-social {
    padding: clamp(52px, 7vw, 86px) 0;
    text-align: center;
}

.lp-social-headline {
    margin: 0 auto 18px;
    max-width: 20ch;
    font-size: clamp(1.75rem, 3.6vw, 2.6rem);
    font-weight: 700;
    line-height: 1.14;
    letter-spacing: -0.025em;
}

.lp-rating {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    justify-content: center;
    margin-bottom: 44px;
}
.lp-rating-laurel { font-size: 1.9rem; transform: scaleX(-1); }
.lp-rating-laurel-r { transform: none; }
.lp-rating-score {
    font-size: clamp(2rem, 4vw, 2.6rem);
    font-weight: 700;
    letter-spacing: -0.02em;
}
.lp-rating-stars { color: var(--lp-coral); letter-spacing: 0.1em; font-size: 1.15rem; }
.lp-rating-count {
    width: 100%;
    font-size: 0.85rem;
    color: var(--lp-muted);
}

/* The section used to jump from its headline straight to the three cards. */
.lp-social-sub {
    max-width: 52ch;
    margin: -6px auto 34px;
    font-size: 1.02rem;
    color: var(--lp-muted);
}

.lp-quotes {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 20px;
    text-align: left;
}
.lp-quote {
    position: relative;
    margin: 0;
    padding: 26px 24px 22px;
    background: var(--lp-card);
    border: 1px solid var(--lp-line);
    border-radius: var(--lp-radius);
    box-shadow: var(--lp-shadow);
}
/* The headline is the line people actually read — a quote card gets about one
   second of attention, and "Incredible for ADHD" is what has to land in it. It
   carries a highlighter stroke rather than a color or a weight change: a marker
   swipe is the thing a student does to a sentence that matters to them, which is
   exactly the claim being made.

   The stroke is a gradient stop, not a background on the text, so it sits behind
   the baseline the way a real marker does and follows the text across a line
   break. box-decoration-break keeps it from reopening the stroke's rounded ends
   mid-sentence on the second line. */
.lp-quote blockquote { margin: 0 0 18px; }

.lp-quote-head {
    margin: 0 0 12px;
    font-size: 1.12rem;
    font-weight: 700;
    line-height: 1.4;
    letter-spacing: -0.015em;
    color: var(--lp-ink);
}
.lp-quote-head span {
    background-image: linear-gradient(transparent 42%, rgba(234, 116, 85, 0.42) 42%);
    -webkit-box-decoration-break: clone;
    box-decoration-break: clone;
    padding: 0 2px;
}

.lp-quote-body {
    margin: 0;
    font-size: 0.97rem;
    color: var(--lp-muted);
}

/* Name and grade, nothing else — see the note in src/landing_content.py. */
.lp-quote figcaption {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--lp-ink-2);
}

/* The only mark left on an invented quote now that the chip is gone. Quiet enough
   to screenshot, and it disappears the moment the `placeholder` flag comes off in
   src/landing_content.py. */
.lp-quote.is-placeholder { border-style: dashed; }

/* ── Part 3: how it works ─────────────────────────────────────────────────── */

.lp-how {
    padding: clamp(56px, 8vw, 100px) 0;
    background: var(--lp-card);
    border-top: 1px solid var(--lp-line);
    border-bottom: 1px solid var(--lp-line);
    text-align: center;
}

.lp-kicker {
    display: inline-block;
    margin: 0 0 18px;
    padding: 5px 15px;
    border-radius: 999px;
    background: var(--lp-tint);
    color: var(--lp-plum-deep);
    font-size: 0.8rem;
    font-weight: 700;
    letter-spacing: 0.04em;
}

.lp-h2 {
    margin: 0 0 clamp(36px, 5vw, 60px);
    font-size: clamp(2rem, 4.6vw, 3.2rem);
    font-weight: 700;
    line-height: 1.08;
    letter-spacing: -0.028em;
}

.lp-steps {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: clamp(22px, 3.5vw, 40px);
    margin: 0 0 clamp(40px, 5vw, 60px);
    padding: 0;
    list-style: none;
    counter-reset: lp-step;
    text-align: left;
}
.lp-step { position: relative; }

/* The connector between the three steps, as in the PRD's reference. Drawn on the
   gap between cards rather than inside them, and dropped entirely once the grid
   stacks — a horizontal line between vertically stacked cards reads as a mistake. */
.lp-step:not(:last-child)::after {
    content: "";
    position: absolute;
    top: calc(50% + 0px);
    right: calc(-1 * clamp(22px, 3.5vw, 40px));
    width: clamp(22px, 3.5vw, 40px);
    border-top: 2px dashed rgba(163, 58, 151, 0.35);
    display: none;
}

.lp-step-text { padding: 20px 4px 0; }
.lp-step-num {
    display: grid;
    place-items: center;
    width: 32px;
    height: 32px;
    margin-bottom: 12px;
    border-radius: 50%;
    background: var(--lp-brand-grad);
    color: #fff;
    font-size: 0.95rem;
    font-weight: 700;
}
.lp-step-text h3 {
    margin: 0 0 8px;
    font-size: 1.22rem;
    font-weight: 700;
    letter-spacing: -0.015em;
}
.lp-step-text p {
    margin: 0;
    font-size: 0.99rem;
    color: var(--lp-muted);
}

.lp-how-footnote {
    max-width: 52ch;
    margin: 0 auto;
    padding: 22px 26px;
    border: 1px solid var(--lp-line);
    border-radius: var(--lp-radius);
    background: var(--lp-bg);
    font-size: 1rem;
    color: var(--lp-muted);
}
.lp-how-footnote strong { color: var(--lp-ink); }

/* ── Why igni, not another app ─────────────────────────────────────────────── */
/*
   This section gets a ground of its own. Two reasons, and the first is mechanical:
   the page alternates so that no two neighbouring sections share a background —

       hero  warm paper · social  page · how  white · why  tint · FAQ  page ·
       start  warm paper · footer  ink

   — and before this rule, `why` and the FAQ were both the page fill and ran into
   each other with no seam at all, so a reader scrolling past could not see that the
   subject had changed. The second reason is that this is the argument section, and
   a wash of the brand's own plum is a cheap way to say so without a heading that
   shouts. */
.lp-why {
    padding: clamp(56px, 8vw, 100px) 0;
    background: var(--lp-tint);
    border-top: 1px solid var(--lp-line);
    border-bottom: 1px solid var(--lp-line);
    text-align: center;
}
.lp-why .lp-h2 { margin-bottom: 20px; max-width: 24ch; margin-inline: auto; }

.lp-why-body {
    max-width: 58ch;
    margin: 0 auto clamp(36px, 5vw, 52px);
    font-size: 1.05rem;
    color: var(--lp-muted);
}

/* ── The comparison table ─────────────────────────────────────────────────── */

.lp-compare-wrap { max-width: 920px; margin: 0 auto; }

.lp-compare {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    text-align: left;
    font-size: 0.97rem;
}
.lp-compare thead th {
    padding: 0 18px 12px;
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--lp-muted);
    vertical-align: bottom;
}
.lp-compare thead .lp-compare-us { color: var(--lp-plum-deep); }
/* The brand's own column is headed by the mark rather than by its name set in the
   same gray caps as the other side — the asymmetry is the point. */
.lp-compare thead .lp-compare-us img {
    width: 62px;
    height: auto;
    margin-bottom: 2px;
}

.lp-compare tbody th {
    width: 1%;
    padding: 18px 18px 18px 0;
    font-weight: 700;
    color: var(--lp-ink);
    white-space: nowrap;
    vertical-align: top;
    border-top: 1px solid var(--lp-line);
}
.lp-compare tbody td {
    padding: 18px;
    color: var(--lp-muted);
    vertical-align: top;
    border-top: 1px solid var(--lp-line);
}

/* The igni column is lifted as one continuous panel rather than per-cell, so it
   reads as a single answer running down the table instead of five tinted boxes.
   The rounding is applied to the first and last cells only, which is what makes
   the column look like one object.

   It is white because the section around it is now the tint: filling it with the
   same wash as its own background would erase the column entirely. The two go
   together — change one and the other has to move. */
.lp-compare tbody .lp-compare-us {
    background: var(--lp-card);
    color: var(--lp-ink-2);
    box-shadow: 0 1px 2px rgba(22, 24, 29, 0.04);
}
.lp-compare tbody tr:first-child .lp-compare-us { border-top-color: transparent; border-radius: 14px 14px 0 0; }
.lp-compare tbody tr:last-child  .lp-compare-us { border-radius: 0 0 14px 14px; }
.lp-compare thead .lp-compare-us { padding-bottom: 10px; }

.lp-why-closer {
    max-width: 34ch;
    margin: clamp(36px, 5vw, 52px) auto 0;
    font-size: clamp(1.15rem, 2.2vw, 1.45rem);
    font-weight: 700;
    line-height: 1.35;
    letter-spacing: -0.02em;
    color: var(--lp-ink);
}
.lp-why-link { margin: 16px 0 0; font-size: 0.95rem; }
.lp-why-link a { color: var(--lp-plum-deep); font-weight: 600; }

@media (max-width: 760px) {
    /* The table keeps its markup and restacks: each row becomes a block with its
       two answers labeled by the data-label the header text was copied into, so
       the pairing survives for anyone reading it without seeing the columns. */
    .lp-compare thead { display: none; }
    .lp-compare, .lp-compare tbody, .lp-compare tr, .lp-compare th, .lp-compare td {
        display: block;
        width: auto;
    }
    .lp-compare tr {
        margin-bottom: 14px;
        border: 1px solid var(--lp-line);
        border-radius: var(--lp-radius);
        overflow: hidden;
        background: var(--lp-card);
    }
    /* Stacked, the igni half cannot be distinguished by being white — the whole
       card already is. It takes the tint instead, which is the inverse of the
       desktop table and the only way round that keeps the two halves apart. */
    .lp-compare tbody .lp-compare-us {
        background: var(--lp-tint);
        box-shadow: none;
    }
    .lp-compare tbody th {
        /* `width: auto` on the blanket `.lp-compare th` rule above does not reach
           this: the desktop `.lp-compare tbody th { width: 1% }` that shrink-wraps
           the label column is one element more specific, so it survives into the
           stacked layout and squeezes every heading to one word per line. */
        width: auto;
        padding: 14px 16px 10px;
        white-space: normal;
        border-top: 0;
    }
    .lp-compare tbody td {
        padding: 0 16px 14px;
        border-top: 0;
    }
    .lp-compare tbody td::before {
        content: attr(data-label);
        display: block;
        margin-bottom: 4px;
        font-size: 0.7rem;
        font-weight: 700;
        letter-spacing: 0.07em;
        text-transform: uppercase;
        color: var(--lp-muted);
    }
    .lp-compare tbody .lp-compare-us {
        padding-top: 12px;
        padding-bottom: 16px;
        border-radius: 0 !important;
    }
    .lp-compare tbody .lp-compare-us::before { color: var(--lp-plum-deep); }
}

/* ── Part 4: FAQ ──────────────────────────────────────────────────────────── */

.lp-faq {
    padding: clamp(56px, 8vw, 100px) 0;
    text-align: center;
}
.lp-faq .lp-h2 { margin-bottom: clamp(30px, 4vw, 46px); }

.lp-faq-items { text-align: left; }

.lp-faq-item {
    border: 1px solid var(--lp-line);
    border-radius: var(--lp-radius);
    background: var(--lp-card);
    margin-bottom: 10px;
    overflow: hidden;
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.lp-faq-item:has(.lp-faq-q[aria-expanded="true"]) {
    border-color: rgba(163, 58, 151, 0.45);
    box-shadow: var(--lp-shadow);
}

.lp-faq-q {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    width: 100%;
    padding: 19px 22px;
    border: 0;
    background: none;
    font-family: inherit;
    font-size: 1.02rem;
    font-weight: 600;
    color: var(--lp-ink);
    text-align: left;
    cursor: pointer;
}

.lp-faq-icon {
    position: relative;
    flex: 0 0 auto;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: var(--lp-ink);
    transition: background-color 0.2s ease, transform 0.25s ease;
}
.lp-faq-icon::before,
.lp-faq-icon::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 11px;
    height: 2px;
    border-radius: 1px;
    background: #fff;
    transform: translate(-50%, -50%);
    transition: opacity 0.2s ease, transform 0.25s ease;
}
.lp-faq-icon::after { transform: translate(-50%, -50%) rotate(90deg); }
.lp-faq-q[aria-expanded="true"] .lp-faq-icon { background: var(--lp-plum); }
.lp-faq-q[aria-expanded="true"] .lp-faq-icon::after {
    transform: translate(-50%, -50%) rotate(0deg);
    opacity: 0;
}

/* Animating grid-template-rows rather than max-height: the answers differ a lot
   in length, and a single max-height guess either clips the long ones or makes
   the short ones close with a visible lag. */
.lp-faq-a {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows 0.28s ease;
}
.lp-faq-a.is-open { grid-template-rows: 1fr; }
.lp-faq-a-inner {
    overflow: hidden;
    padding: 0 22px;
}
.lp-faq-a.is-open .lp-faq-a-inner { padding-bottom: 20px; }
.lp-faq-a-inner p {
    margin: 0 0 12px;
    color: var(--lp-muted);
}
.lp-faq-a-inner p:last-child { margin-bottom: 0; }
.lp-faq-a-inner strong { color: var(--lp-ink-2); }

.lp-faq-contact {
    margin: 30px 0 0;
    font-size: 0.95rem;
    color: var(--lp-muted);
}
.lp-faq-contact a { color: var(--lp-plum-deep); font-weight: 600; }

/* ── Part 5: get started ─────────────────────────────────────────────────────
   The close is still a band of the logo's own gradient, but as a *wash* — the two
   stops at low alpha over the hero's warm paper, rather than at full strength.
   Saturated edge to edge it was the loudest thing on a page that is otherwise
   restrained, and it read as noise rather than as arrival.

   Keeping the gradient as a tint rather than swapping in a flat color matters:
   the hue is still exactly the logo's, so the band belongs to the same family as
   the hero and the plum section, just quieter. Text goes back to ink, which also
   retires the contrast problem that forced the gradient off pure coral while it
   was carrying white type — and the CTA can be the ordinary gradient button again,
   which is the strongest thing on a pale ground.
   ------------------------------------------------------------------------- */
.lp-start {
    position: relative;
    padding: clamp(64px, 9vw, 108px) 0 clamp(68px, 9vw, 112px);
    background:
        linear-gradient(104deg, rgba(234, 116, 85, 0.17) 0%, rgba(163, 58, 151, 0.15) 70%),
        var(--lp-paper);
    border-top: 1px solid var(--lp-line);
    text-align: center;
    overflow: hidden;
}

/* The same squared paper as the hero, in the brand's own hues rather than white
   now that the ground underneath is light again. */
.lp-start::before {
    content: "";
    position: absolute;
    inset: 0;
    background-image:
        linear-gradient(rgba(234, 116, 85, 0.1) 1px, transparent 1px),
        linear-gradient(90deg, rgba(234, 116, 85, 0.1) 1px, transparent 1px),
        linear-gradient(rgba(163, 58, 151, 0.05) 1px, transparent 1px),
        linear-gradient(90deg, rgba(163, 58, 151, 0.05) 1px, transparent 1px);
    background-size: 20px 20px, 20px 20px, 100px 100px, 100px 100px;
    pointer-events: none;
}
.lp-start > * { position: relative; z-index: 1; }

.lp-start-head {
    margin: 0 0 16px;
    font-size: clamp(2rem, 4.6vw, 3.1rem);
    font-weight: 700;
    line-height: 1.08;
    letter-spacing: -0.03em;
    color: var(--lp-ink);
}
/* The accent can be the gradient again now that the band behind it is not. Same
   treatment as the hero's headline, fallback included. */
.lp-start-head em {
    font-style: normal;
    color: var(--lp-plum);
}
@supports (background-clip: text) or (-webkit-background-clip: text) {
    .lp-start-head em {
        background: linear-gradient(96deg, var(--lp-coral) 0%, var(--lp-plum) 72%);
        -webkit-background-clip: text;
        background-clip: text;
        color: transparent;
        padding-right: 0.06em;
        margin-right: -0.06em;
    }
}

.lp-start-sub {
    max-width: 44ch;
    margin: 0 auto clamp(28px, 4vw, 38px);
    font-size: clamp(1rem, 1.8vw, 1.15rem);
    color: var(--lp-muted);
}

.lp-start-points {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 10px 26px;
    margin: 26px 0 0;
    padding: 0;
    list-style: none;
    font-size: 0.88rem;
    color: var(--lp-muted);
}
.lp-start-points li {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}
.lp-start-points li::before {
    content: "";
    width: 16px;
    height: 16px;
    flex: 0 0 auto;
    border-radius: 50%;
    background: var(--lp-plum);
    /* A tick drawn as a mask rather than a glyph: ✓ renders at a different weight
       and baseline in every font on the fallback stack. */
    -webkit-mask: no-repeat center/9px url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2 6.3 4.6 9 10 3.2' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    mask: no-repeat center/9px url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2 6.3 4.6 9 10 3.2' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

/* ── Part 6: footer ───────────────────────────────────────────────────────── */

.lp-footer {
    padding: clamp(44px, 6vw, 72px) 0 32px;
    background: var(--lp-ink);
    color: #C9CCD2;
    font-size: 0.93rem;
}

.lp-footer-top {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
    gap: clamp(32px, 5vw, 60px);
    padding-bottom: 36px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

/* The inlined mark. The wordmark paths are `fill="currentColor"`, so they take the
   color set here, while the flame keeps the coral-to-plum gradient written into the
   file. This is why it is inlined and not an <img>: a filter recolours the whole
   picture, and the flame came out white with everything else. */
.lp-logomark {
    display: block;
    width: 120px;
    height: auto;
}
.lp-footer-brand .lp-logomark { color: #fff; }
.lp-footer-slogan {
    margin: 16px 0 0;
    max-width: 24ch;
    font-size: 1.08rem;
    font-weight: 600;
    line-height: 1.35;
    letter-spacing: -0.01em;
    color: #fff;
}

.lp-socials { display: flex; gap: 12px; margin-top: 22px; }
.lp-socials a {
    display: grid;
    place-items: center;
    width: 38px;
    height: 38px;
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, 0.18);
    color: #fff;
    transition: background-color 0.18s ease, border-color 0.18s ease;
}
.lp-socials a:hover {
    background: var(--lp-plum);
    border-color: var(--lp-plum);
}
.lp-socials svg {
    width: 19px;
    height: 19px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.7;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.lp-footer-cols {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 28px;
}
.lp-footer-col h3 {
    margin: 0 0 14px;
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: #fff;
}
.lp-footer-col a {
    display: block;
    margin-bottom: 9px;
    color: #C9CCD2;
    text-decoration: none;
    transition: color 0.18s ease;
}
.lp-footer-col a:hover { color: var(--lp-coral); }   /* plum is unreadable on the dark footer */

.lp-footer-bottom {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 12px 20px;
    padding-top: 24px;
    font-size: 0.84rem;
    color: #8E939B;
}
.lp-legal {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}
.lp-legal a { color: #8E939B; text-decoration: none; }
.lp-legal a:hover { color: #fff; }

/* Visually hidden, still announced. */
.lp-sr {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* ── Scroll reveal ────────────────────────────────────────────────────────── */
/* Applied by site_landing.js, never in the stylesheet: if JS fails the content
   must still be visible, so the hidden state is only ever added by the script
   that also knows how to remove it. */
.lp-reveal {
    opacity: 0;
    transform: translateY(18px);
    transition: opacity 0.6s ease, transform 0.6s ease;
}
.lp-reveal.is-in { opacity: 1; transform: none; }

/* Printing never scrolls, so nothing would ever intersect and a printed copy of
   the page would come out with the FAQ and the steps blank. */
@media print {
    .lp-reveal { opacity: 1 !important; transform: none !important; }
}

/* ── Responsive ───────────────────────────────────────────────────────────── */

@media (min-width: 981px) {
    /* Connector dashes only once the steps are genuinely side by side. */
    .lp-step:not(:last-child)::after { display: block; top: calc(50% - 40px); }

    /* ── One screenful ──────────────────────────────────────────────────────
       The hero is exactly the viewport minus the sticky header, with the row
       centered in it, so a visitor sees the headline, the CTA and the whole film
       without scrolling.

       The film is then constrained by the height that leaves, not by a width:
       `max-width: available-height × ratio` keeps the aspect intact and simply
       draws the film smaller on a short screen. Doing it the other way round —
       fixing the width and clamping the height — breaks the ratio and crops the
       picture, which on a film with text in it loses the text.

       Consequence worth knowing: the ratio decides how big the film can be. At a
       790px viewport a 4:5 film fills the full 480px card; a 9:16 one is held to
       343px. See static/videos/README.md. */
    .lp-hero-split {
        display: flex;
        align-items: center;
        min-height: calc(100vh - var(--lp-header-h));
        min-height: calc(100svh - var(--lp-header-h));
        padding-block: var(--lp-hero-pad-y);
    }
    .lp-hero-split .lp-hero-inner { width: 100%; }

    .lp-hero-plain .lp-video-plain,
    .lp-hero-split .lp-phone {
        max-width: min(
            var(--lp-media-max),
            calc((100vh - var(--lp-header-h) - 2 * var(--lp-hero-pad-y)) * var(--lp-ar))
        );
        max-width: min(
            var(--lp-media-max),
            calc((100svh - var(--lp-header-h) - 2 * var(--lp-hero-pad-y)) * var(--lp-ar))
        );
    }
    /* The phone is narrower than the card and has its own ratio. */
    .lp-hero-split .lp-phone { --lp-media-max: 320px; }
}

@media (max-width: 980px) {
    .lp-hero-split .lp-hero-inner {
        grid-template-columns: minmax(0, 1fr);
        text-align: center;
        gap: 40px;
    }
    .lp-hero-split .lp-hero-actions { justify-content: center; }
    .lp-hero-split .lp-sub { margin-inline: auto; }

    .lp-steps { grid-template-columns: minmax(0, 1fr); max-width: 520px; margin-inline: auto; }
    .lp-step-text { text-align: center; }
    .lp-step-num { margin-inline: auto; }

    .lp-footer-top { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 760px) {
    :root { --lp-gutter: 18px; }

    /* The nav links collapse before the CTA does: on a phone the one thing the
       header has to keep is the button, and the same links all exist in the
       footer. No hamburger — there is nothing behind it worth the complexity. */
    .lp-header-nav .lp-header-link { display: none; }

    .lp-h1 { font-size: clamp(2.2rem, 10vw, 3rem); }
    .lp-hero { padding-top: 34px; }

    /* ── The hero, loosened ───────────────────────────────────────────────────
       Everything here was the same width as everything else — headline, sub and
       a saturated full-bleed button, all 354px, stacked tight. Nothing was wrong
       individually; the sameness was the problem. The copy column becomes a flex
       column so the carousel can be reordered out of the top (below), the button
       sizes to its own text, and the sub is set smaller and narrower so it reads
       as support rather than as a second headline. */
    /* ── The film keeps its distance from the copy ────────────────────────────
       It used to begin 505px down and run 443px, so 339px of it fell inside the
       first screen and 104px below — too little to read, too much to ignore, and
       a picture sliced by the fold reads as an accident however the copy above it
       is spaced. That was what made the hero feel crammed.

       The fix is separation, not removal. The copy block is given a minimum
       height so it owns the first screen on its own, and the film starts after a
       deliberate 72px gap — far enough down that only its top edge shows, which
       reads as "there is a picture below" rather than as a cropped one. Scrolling
       brings it up whole.

       The 180px subtracted is the hero's own top padding plus the peek: it leaves
       roughly 64px of the film showing on every phone from an SE up, since the
       calculation scales with the viewport rather than assuming one. */
    .lp-hero-split { display: block; }
    .lp-hero-copy {
        justify-content: center;
        min-height: calc(100vh - var(--lp-header-h) - 180px);
        min-height: calc(100svh - var(--lp-header-h) - 180px);
    }
    .lp-hero-split .lp-hero-inner { width: 100%; gap: 72px; }

    .lp-hero { padding-top: 44px; }
    .lp-hero-copy { display: flex; flex-direction: column; }

    .lp-h1 { margin-bottom: 20px; }

    /* Matches `.lp-hero-split .lp-sub`, which sets the desktop measure. A bare
       `.lp-sub` here would lose to it: a media query adds no specificity, so a
       two-class selector outside one still wins over a one-class selector in it. */
    .lp-hero-split .lp-sub {
        max-width: 33ch;
        margin-bottom: 34px;
        font-size: 0.97rem;
    }

    /* ── The carousel moves below the call to action ──────────────────────────
       It was wedged between the header and the headline, the tightest band on
       the page, and the headline is what the top of a phone screen is for. Only
       this one item moves, so a single `order` does it — everything else keeps
       the default 0 and stays in source order. Desktop is untouched: there it
       still sits above the headline, where there is room for it.

       Full-bleed as well. Inside the gutter it had 354px to work with and the two
       fades ate 156 of them: exactly ONE pill was ever fully legible, which is
       why the strip read as broken rather than as moving. Edge to edge it gets
       the whole screen and three pills, and the clip lands at the screen edge
       where it reads as a ticker crossing it.

       It stays inside the gutter rather than bleeding to the screen edges, and
       the fade is wide enough that a pill is well dissolved before it reaches
       that edge — so the strip reads as a window with soft sides, not as
       something running off the phone. */
    .lp-hero-subjects {
        order: 1;                       /* everything else stays at 0 */
        width: 100%;
        /* Clear of the call to action above it: at 4px the strip read as attached
           to "See how it works" rather than as its own thing. */
        margin: 34px 0 0;
        -webkit-mask-image: linear-gradient(90deg, transparent, #000 15%, #000 85%, transparent);
        mask-image: linear-gradient(90deg, transparent, #000 15%, #000 85%, transparent);
    }

    /* ── Compact the comparison rows ──────────────────────────────────────────
       Five stacked rows came to 1236px — a screen and a half of the same shape
       repeating. The long label ("An app that hands back the solution") was set
       above every single half and wrapped to two lines each time, so most of
       that height was the same 35 characters printed ten times. On a phone the
       short label does the same job. */
    .lp-compare tbody td::before { content: attr(data-label-short); }
    .lp-compare tbody th { padding: 12px 14px 8px; font-size: 0.98rem; }
    .lp-compare tbody td { padding: 0 14px 12px; font-size: 0.94rem; }
    .lp-compare tbody .lp-compare-us { padding-top: 10px; padding-bottom: 14px; }
    .lp-compare tr { margin-bottom: 10px; }

    /* Below this width the portrait cut of the film is used (switch_at in
       src/landing_content.py — keep the two numbers the same). The real ratio is
       read off the file once it loads; this only reserves the right shape first.
       The portrait cut is tall, so it is capped to stay inside a phone screen
       rather than pushing everything under it a screen and a half down. */
    .lp-video-hero { aspect-ratio: 9 / 16; }
    .lp-hero-media-wide { max-width: min(420px, 100%); }
    .lp-video-sound { right: 10px; bottom: 10px; padding: 8px 13px; font-size: 0.78rem; }

    .lp-footer-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .lp-footer-bottom { justify-content: center; text-align: center; }
    .lp-legal { justify-content: center; }
}

@media (max-width: 440px) {
    .lp-footer-cols { grid-template-columns: minmax(0, 1fr); }
    .lp-btn-lg { padding-left: 38px; padding-right: 38px; }
    /* The button sized to its own text instead of the full column. A full-bleed
       block of saturated gradient was the heaviest thing on the screen, and it
       made the hero read as three identical bars stacked up. */
    .lp-hero-actions { flex-direction: column; align-items: center; gap: 18px; }
    /* Stretched to the full column, this link's underline became a rule spanning
       the whole screen — it read as a stray divider rather than as a link. It is
       the one item in the stretched column that must hug its own text. */
    .lp-hero-secondary { align-self: center; }
}

/* ── Reduced motion ───────────────────────────────────────────────────────── */
/* The marquee and the reveals stop; the videos stop autoplaying and gain real
   controls, so the content stays reachable rather than simply disappearing. */
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }

    .lp-subjects-track { animation: none; transform: none; }
    .lp-subjects-rail {
        overflow-x: auto;
        -webkit-mask-image: none;
        mask-image: none;
    }

    .lp-reveal { opacity: 1; transform: none; transition: none; }

    /* The films get real <video controls> here instead of autoplaying, and those
       already carry a volume control — two mute buttons on one video is worse
       than none. */
    .lp-video-sound { display: none; }

    *, *::before, *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
    }
}

/* ── Native app ───────────────────────────────────────────────────────────── */
/* This page is a marketing page and is never the app's own shell, but the native
   WebView can still reach it via a link. Hide the cookie icon there, as the other
   site pages do. */
.capacitor-native [id*="silktide"] { display: none !important; }
