/* Dose Pop site. The app's own colours, one typeface, rows and hairlines.
   Pass 1 plan: docs/superpowers/specs/2026-10-16-landing-rebuild-design.md
   Pass 2 plan (palette sources, the hero scene, the motion score):
   docs/superpowers/specs/2026-10-16-app-colours-depth-motion.md */

@font-face {
    font-family: "Atkinson Hyperlegible Next";
    src: url("fonts/atkinson-hyperlegible-next-latin.woff2") format("woff2");
    font-weight: 200 800;
    font-style: normal;
    font-display: swap;
    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;
}

/* Light is the app's default appearance; every value is from AppColors.swift
   or the AccentColor asset, or derived inside the app's own stone family. */
:root {
    color-scheme: light dark;

    --ground: #FAFAF9;            /* ppBackground */
    --surface: #F5F5F4;           /* ppSurface */
    --ink-heading: #1C1917;       /* ppTextPrimary, APCA Lc 101 */
    --ink: #44403C;               /* stone 700, Lc 91 */
    --muted: #78716C;             /* ppTextSecondary, Lc 70 */
    --accent: #0F766E;            /* ppPrimaryDark, the app's primary button fill */
    --accent-ink: #FFFFFF;        /* the app's button text, Lc 82 on the fill */
    --accent-hover: #115E59;
    --accent-text: #0F766E;       /* links on hover, focus ring, Lc 74 */
    --accent-line: #0D9488;       /* AccentColor: underlines and the dose ring */
    --green: #16A34A;             /* ppSuccess, the I Took It button */
    --hairline: rgba(28, 25, 23, 0.14);
    --quiet-border: rgba(28, 25, 23, 0.48);

    --phone: #1C1917;
    --phone-edge: #44403C;
    --phone-rim: rgba(28, 25, 23, 0);

    --font: "Atkinson Hyperlegible Next", "Atkinson Hyperlegible", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

    /* Fluid values ramp from 390 to 1280 wide and stay flat above. */
    --fs-body: clamp(1.125rem, 1.094rem + 0.126vw, 1.1953rem);
    --fs-lede: clamp(1.2656rem, 1.204rem + 0.253vw, 1.4063rem);
    --fs-h2: clamp(1.75rem, 1.439rem + 1.326vw, 2.5rem);
    --fs-h1: clamp(2.125rem, 1.555rem + 2.431vw, 3.5rem);
    --fs-row: 1.375rem;
    --fs-small: 1rem;

    --measure-body: 30em;
    --measure-lede: 28em;
    --measure-h1: 12em;

    --section: clamp(80px, 63.4px + 4.42vw, 120px);
    --hero-top: clamp(32px, 18.7px + 3.54vw, 64px);
    --max-width: 1120px;
    --gutter: clamp(20px, 15px + 1.33vw, 32px);
    --cols: minmax(0, 7fr) minmax(0, 5fr);
    --col-gap: 64px;
    --phone-shot: clamp(240px, 215px + 6.63vw, 300px);
    --hero-shot: clamp(240px, 64px + 21.5vw, 340px);
    --tap: 48px;
}

/* Dark follows the app's dark appearance: ppBackgroundDark, ppSurfaceDark,
   the dark AccentColor, ppPrimaryLight for the fill, ppCardBorder for lines. */
@media (prefers-color-scheme: dark) {
    :root {
        --ground: #1C1917;        /* ppBackgroundDark */
        --surface: #292524;       /* ppSurfaceDark */
        --ink-heading: #FAFAF9;   /* Lc 103 */
        --ink: #E7E5E4;           /* Lc 90 */
        --muted: #A8A29E;         /* ppTextTertiary, Lc 51 */
        --accent: #5EEAD4;        /* ppPrimaryLight */
        --accent-ink: #1C1917;    /* Lc 80 on the fill */
        --accent-hover: #99F6E4;
        --accent-text: #5EEAD4;
        --accent-line: #14B8A6;   /* AccentColor, dark appearance */
        --green: #16A34A;
        --hairline: rgba(255, 255, 255, 0.14);   /* ppCardBorder */
        --quiet-border: rgba(255, 255, 255, 0.4);

        --phone: #0C0A09;
        --phone-edge: #44403C;
        --phone-rim: rgba(255, 255, 255, 0.14);
    }
}

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

html {
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
    scroll-padding-top: 16px;
}

body {
    margin: 0;
    background: var(--ground);
    color: var(--ink);
    font-family: var(--font);
    font-size: var(--fs-body);
    font-weight: 400;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    font-kerning: normal;
}

img { display: block; max-width: 100%; height: auto; }

h1, h2, h3 {
    color: var(--ink-heading);
    font-weight: 700;
    margin: 0;
    text-wrap: balance;
}

p { margin: 0; text-wrap: pretty; }

a {
    color: var(--ink-heading);
    text-decoration-line: underline;
    text-decoration-color: var(--accent-line);
    text-decoration-thickness: 2px;
    text-underline-offset: 0.22em;
}

a:hover { color: var(--accent-text); }

:focus-visible {
    outline: 3px solid var(--accent-text);
    outline-offset: 3px;
}

.wrap {
    width: 100%;
    max-width: calc(var(--max-width) + 2 * var(--gutter));
    margin-inline: auto;
    padding-inline: var(--gutter);
}

/* Skip link: moved out of view by its own height, never by a fixed offset. */
.skip-link {
    position: absolute;
    top: 0;
    left: var(--gutter);
    z-index: 10;
    padding: 12px 20px;
    background: var(--accent);
    color: var(--accent-ink);
    font-weight: 700;
    text-decoration: none;
    border-radius: 0 0 8px 8px;
    /* Height independent: its own height plus a few pixels so no edge bleeds. */
    transform: translateY(calc(-100% - 4px));
}

.skip-link:focus { transform: translateY(0); }
.skip-link:hover { color: var(--accent-ink); }

/* Header */

.site-header .wrap {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0 16px;
    min-height: 80px;
    padding-block: 16px;
}

.brand {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    min-height: var(--tap);
    color: var(--ink-heading);
    font-size: 1.25rem;
    font-weight: 700;
    text-decoration: none;
    white-space: nowrap;
    flex-shrink: 0;
}

.brand:hover { color: var(--ink-heading); }

.brand img {
    width: 40px;
    height: 40px;
    border-radius: 9px;
}

.site-nav {
    display: flex;
    flex-shrink: 0;
    gap: 8px;
    margin-right: -12px;
}

.site-nav a {
    display: inline-flex;
    align-items: center;
    min-height: var(--tap);
    padding-inline: 12px;
    color: var(--ink);
    text-decoration: none;
    white-space: nowrap;
}

.site-nav a:hover,
.site-nav a[aria-current="page"],
.footer-links a[aria-current="page"] { color: var(--ink-heading); text-decoration: underline; text-decoration-color: var(--accent-line); }

/* Buttons */

.button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 56px;
    padding: 12px 28px;
    border-radius: 12px;
    background: var(--accent);
    color: var(--accent-ink);
    font-size: 1.125rem;
    font-weight: 700;
    line-height: 1.25;
    text-align: center;
    text-decoration: none;
}

.button:hover { color: var(--accent-ink); background: var(--accent-hover); }

.button-quiet {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: var(--tap);
    padding: 8px 18px;
    border: 1px solid var(--quiet-border);
    border-radius: 10px;
    color: var(--ink-heading);
    font-weight: 700;
    text-decoration: none;
}

.button-quiet:hover { color: var(--ink-heading); border-color: var(--accent-text); }

/* Hero */

.hero { overflow-x: clip; }

.hero .wrap {
    display: grid;
    grid-template-columns: var(--cols);
    column-gap: var(--col-gap);
    padding-top: var(--hero-top);
}

.hero-copy {
    align-self: center;
    padding-bottom: 64px;
}

.hero h1 {
    font-size: var(--fs-h1);
    line-height: 1.06;
    letter-spacing: -0.012em;
    max-width: var(--measure-h1);
}

.lede {
    margin-top: 24px;
    max-width: var(--measure-lede);
    font-size: var(--fs-lede);
    line-height: 1.5;
    color: var(--ink);
}

.hero-actions {
    margin-top: 32px;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 16px 24px;
}

.send {
    margin-top: 24px;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 12px;
}

.send p { margin-right: 4px; }

/* The hero scene. Three planes in one 3D context, all pivoting on one contact
   point: the middle of the phone's base, where it meets the hero rule.
     background  the day strip, set back
     subject     the phone, standing on the rule, with the clean plate as its screen
     foreground  the real dose card, lifted off the screen toward the reader
   Geometry comes from the 1320 wide capture: one capture pixel is var(--sw) / 1320.
   The card sits at (48, 918), 1224 by 485; the visible screen is the top 1600 rows;
   the plate runs to row 1950 so the phone body continues below the rule. */

.hero-media {
    --w: var(--hero-shot);                   /* phone width */
    --sw: calc(var(--w) - 20px);             /* screen width inside a 10px bezel */
    --hv: calc(10px + var(--sw) * 1600 / 1320);  /* visible height, base to rule */
    --phone-x: calc(100% - var(--w));        /* phone's left edge inside the stage */
    --lift: calc(var(--w) * 0.16);
    --depth: calc(var(--w) * 3);
    --turn: -16deg;
    --lean: 7deg;
    --p: 0;
    --rx: 0deg;
    --ry: 0deg;

    align-self: end;
    min-width: 0;
    margin: 0;
}

.shot-caption {
    width: var(--w);
    margin: 0 0 16px auto;
    color: var(--ink);
    font-size: var(--fs-small);
    line-height: 1.5;
    min-height: 1.5em;
}

/* The stage clips only at the rule; the planes may run past its sides. */
.stage {
    position: relative;
    height: var(--hv);
    perspective: var(--depth);
    perspective-origin: calc(var(--phone-x) + var(--w) / 2) 40%;
    clip-path: inset(-100vh -100vw 0 -100vw);
}

.rig {
    position: absolute;
    inset: 0;
    transform-style: preserve-3d;
    transform-origin: calc(var(--phone-x) + var(--w) / 2) 100%;
    transform: rotateX(var(--rx)) rotateY(var(--ry));
}

/* Background plane: the morning, one line an hour, the 9 AM line level with
   the dose card. Pushed back, then scaled by the same factor so its labels
   still render at 16px and its lines land where they are laid out. */
.strip-plane {
    position: absolute;
    top: 0;
    bottom: 0;
    left: -16px;
    right: calc(-1 * var(--gutter));
    transform-style: preserve-3d;
    transform-origin: calc(100% - var(--gutter) - var(--w) / 2) 40%;
    transform: translateZ(calc(var(--w) * -0.35)) scale(1.1167) translateY(calc(var(--p) * var(--w) * 0.035));
}

.strip {
    position: absolute;
    inset: 0;
    margin: 0;
    padding: 0;
    list-style: none;
}

.strip li {
    position: absolute;
    left: 0;
    right: 0;
    /* The 9 AM line (index 3) sits on the card's centre row, 1160 in the capture. */
    top: calc(10px + var(--sw) * 1160 / 1320 + (var(--i) - 3) * var(--w) * 0.135);
    height: 1px;
    background: var(--hairline);
}

.strip span {
    position: absolute;
    left: 0;
    bottom: 6px;
    color: var(--muted);
    font-size: var(--fs-small);
    line-height: 1;
    white-space: nowrap;
}

.dose-mark {
    position: absolute;
    left: 46px;
    top: -7px;
    width: 15px;
    height: 15px;
    border: 3px solid var(--accent-line);
    border-radius: 50%;
    background: var(--ground);
}

.hero-media[data-state="taken"] .dose-mark {
    border-color: var(--green);
    background: var(--green);
}

.phone-rise {
    position: absolute;
    top: 0;
    left: var(--phone-x);
    width: var(--w);
    transform-style: preserve-3d;
}

.phone {
    position: relative;
    transform-style: preserve-3d;
    transform-origin: 50% var(--hv);
    transform:
        rotateY(calc(var(--turn) * (1 - var(--p))))
        rotateX(calc(var(--lean) * (1 - var(--p))));
}

/* Front face, cut by the rule: no bottom bezel ever shows. */
.bezel {
    padding: 10px 10px 0;
    background: var(--phone);
    border-radius: calc(var(--w) * 0.15) calc(var(--w) * 0.15) 0 0;
    box-shadow: inset 0 0 0 1px var(--phone-rim);
}

.screen {
    position: relative;
    overflow: hidden;
    border-radius: calc(var(--w) * 0.125) calc(var(--w) * 0.125) 0 0;
    aspect-ratio: 760 / 1123;
    background: #FAFAF9;
}

.screen img {
    width: 100%;
    height: 100%;
}

/* The phone's right side, turned square to the front so it shows as the phone turns. */
.edge {
    position: absolute;
    top: calc(var(--w) * 0.15);
    bottom: 0;
    left: 100%;
    width: calc(var(--w) * 0.045);
    background: var(--phone-edge);
    transform-origin: 0 50%;
    transform: rotateY(90deg);
}

/* The card's shadow lies on the screen under it: offset down and right, blurred. */
.lift-shadow {
    position: absolute;
    left: calc(var(--sw) * 48 / 1320);
    top: calc(var(--sw) * 918 / 1320);
    width: calc(var(--sw) * 1224 / 1320);
    height: calc(var(--sw) * 485 / 1320);
    border-radius: calc(var(--sw) * 48 / 1320);
    background: rgba(28, 25, 23, 0.22);
    filter: blur(calc(var(--w) * 0.03));
    transform: translate(calc(var(--w) * 0.012), calc(var(--w) * 0.04));
}

.card-plane {
    position: absolute;
    left: calc(10px + var(--sw) * 48 / 1320);
    top: calc(10px + var(--sw) * 918 / 1320);
    width: calc(var(--sw) * 1224 / 1320);
    height: calc(var(--sw) * 485 / 1320);
    transform-style: preserve-3d;
    transform: translateZ(var(--lift));
}

/* The card is rounded through its pictures, never an overflow clip: the
   press target's 48px hit area must be free to reach past a small card's edge. */
.card {
    position: relative;
    height: 100%;
    border-radius: calc(var(--sw) * 48 / 1320);
    background: #F5F5F4;
}

.card picture,
.card img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border-radius: inherit;
}

.card .state-taken { opacity: 0; }

.hero-media[data-state="taken"] .state-taken { opacity: 1; }

/* The press target sits on the real button in the card: I Took It spans
   x 96 to 636 and y 1186 to 1355 in the capture, Undo x 96 to 1224. In card
   terms (origin 48, 918; 1224 by 485) that is left 3.92%, top 55.26%,
   width 44.12% or 92.16%, height 34.85%. */
.tap-target {
    position: absolute;
    left: 3.92%;
    top: 55.26%;
    width: 44.12%;
    height: 34.85%;
    padding: 0;
    margin: 0;
    border: 0;
    border-radius: calc(var(--sw) * 36 / 1320);
    background: transparent;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

/* A hit area of at least 48px even where the picture is small. */
.tap-target::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    height: max(100%, var(--tap));
    transform: translateY(-50%);
}

.hero-media[data-state="taken"] .tap-target { width: 92.16%; }

/* The screenshot is light in both schemes, so focus here is the app's ink. */
.tap-target:focus-visible {
    outline: 3px solid #1C1917;
    outline-offset: 2px;
}

/* A neutral touch mark, like the one iOS draws for a touch. It sits on the card,
   centred on I Took It (x 366, y 1270.5 in the capture: 25.98%, 72.68% of the
   card); the script moves it to Undo's centre (50%) when Undo is pressed. */
.ring {
    position: absolute;
    left: 25.98%;
    top: 72.68%;
    width: calc(var(--sw) * 0.16);
    aspect-ratio: 1;
    background: rgba(28, 25, 23, 0.16);
    border: 2px solid rgba(28, 25, 23, 0.32);
    border-radius: 50%;
    opacity: 0;
    pointer-events: none;
    transform: translate(-50%, -50%) scale(0.4);
}

.hero-rule {
    height: 1px;
    background: var(--hairline);
    margin: 0;
    border: 0;
}

/* Sections */

.section .wrap {
    display: grid;
    grid-template-columns: var(--cols);
    column-gap: var(--col-gap);
    align-items: start;
    padding-block: calc(var(--section) / 2);
}

.section-copy { min-width: 0; }

.section h2 {
    font-size: var(--fs-h2);
    line-height: 1.12;
    letter-spacing: -0.006em;
    max-width: 16em;
}

.intro {
    margin-top: 16px;
    max-width: var(--measure-body);
}

.rows {
    list-style: none;
    margin: 32px 0 0;
    padding: 0;
}

.rows li {
    padding-block: 24px;
    border-top: 1px solid var(--hairline);
}

.rows li:last-child { padding-bottom: 0; }

.rows h3 {
    font-size: var(--fs-row);
    line-height: 1.3;
}

.rows p {
    margin-top: 8px;
    max-width: var(--measure-body);
}

.section-media {
    justify-self: end;
    width: var(--phone-shot);
    margin: 0;
    perspective: 1000px;
}

.section-media img {
    width: 100%;
    border-radius: calc(var(--phone-shot) * 0.11);
    border: 1px solid var(--hairline);
}

/* Feature grid: the same two grid lines as the hero, rows divided by hairlines.
   Each row's hairline is its own element, so it can be drawn. */

.section-grid .wrap { display: block; }

.grid-rows {
    list-style: none;
    margin: 40px 0 0;
    padding: 0;
    display: grid;
    grid-template-columns: var(--cols);
    column-gap: var(--col-gap);
    row-gap: 32px;
}

.grid-rows li {
    position: relative;
    padding-top: 24px;
}

.grid-rows li::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 1px;
    background: var(--hairline);
    transform-origin: 0 50%;
}

.grid-rows h3 {
    font-size: var(--fs-row);
    line-height: 1.3;
}

.grid-rows p {
    margin-top: 8px;
    max-width: var(--measure-body);
}

/* Price row */

.price .wrap { padding-block: calc(var(--section) / 2); }

.price-row {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: 16px 48px;
    padding-block: 40px;
    border-top: 1px solid var(--hairline);
    border-bottom: 1px solid var(--hairline);
}

.price-figure {
    color: var(--ink-heading);
    font-size: var(--fs-h1);
    font-weight: 700;
    line-height: 1.06;
    letter-spacing: -0.012em;
    clip-path: inset(0);
}

.price-figure span { display: inline-block; }

.price-terms {
    font-size: var(--fs-lede);
    line-height: 1.5;
}

.price-terms strong { color: var(--ink-heading); font-weight: 700; }

.medical-note {
    margin-top: 32px;
    max-width: 40em;
    font-size: var(--fs-small);
    line-height: 1.6;
}

/* Footer */

.site-footer { border-top: 1px solid var(--hairline); }

.site-footer .wrap {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 24px 48px;
    padding-block: 48px 56px;
    font-size: var(--fs-small);
    line-height: 1.5;
}

.footer-links {
    display: flex;
    flex-wrap: wrap;
    gap: 0 8px;
    margin: 0 0 0 -12px;
    padding: 0;
    list-style: none;
}

.footer-links a,
.footer-meta a {
    display: inline-flex;
    align-items: center;
    min-height: var(--tap);
    padding-inline: 12px;
    color: var(--ink);
    text-decoration: none;
}

.footer-links a:hover,
.footer-meta a:hover { color: var(--ink-heading); text-decoration: underline; text-decoration-color: var(--accent-line); }

.footer-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0 8px;
    margin: 8px 0 0 -12px;
}

.footer-meta p { padding-inline: 12px; color: var(--muted); }

.footer-store {
    align-self: start;
    display: inline-flex;
    min-height: var(--tap);
    align-items: center;
}

.footer-store img { width: 150px; height: auto; }

/* Narrow screens: one column, phone at no more than 60% of the screen.
   The scene is art directed for the phone: the phone hangs on the left grid
   line and the day strip runs out to its right, labels at the far end. */

/* The narrowest two column widths: the strip starts 8px nearer the copy so
   the 9 AM mark keeps clear of the phone's edge. */
@media (min-width: 861px) and (max-width: 1023px) {
    .strip-plane { left: -24px; }
}

@media (max-width: 860px) {
    :root { --col-gap: 0px; }

    .hero .wrap,
    .section .wrap,
    .grid-rows { grid-template-columns: minmax(0, 1fr); }

    .hero-copy { padding-bottom: 40px; }

    .hero-media {
        --w: min(var(--hero-shot), 60vw);
        --phone-x: 0px;
    }

    .shot-caption { width: auto; margin-left: 0; }

    .strip-plane {
        left: calc(var(--w) / 2);
        transform-origin: 0 40%;
    }

    .strip span {
        left: auto;
        right: var(--gutter);
    }

    .dose-mark { left: calc(var(--w) / 2 + 16px); }

    .section-media {
        justify-self: start;
        width: min(var(--phone-shot), 60vw);
        margin-top: 16px;
    }

    .section-media img { border-radius: calc(min(var(--phone-shot), 60vw) * 0.11); }

    .price-row { grid-template-columns: minmax(0, 1fr); }

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

@media (max-width: 420px) {
    .site-nav { gap: 0; margin-right: -8px; }
    .site-nav a { padding-inline: 8px; }
    .brand { gap: 10px; }
    .brand img { width: 36px; height: 36px; border-radius: 8px; }
    .button { width: 100%; }
}

.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Display Zoom widths: the nav drops under the brand; its text lines up with the brand. */
@media (max-width: 359px) {
    .site-nav { margin-left: -8px; }
}

/* Motion. Everything below runs only when the visitor has not asked for less
   motion. Transform, opacity and clip-path only; every transition names them.
   `.motion` is set in the head before first paint; `.reveal` is set by the
   script once the section observer is running, so without script every
   section is simply shown. */

@media (prefers-reduced-motion: no-preference) {
    .button,
    .button-quiet { transition: transform 140ms ease-out; }

    .button:hover,
    .button-quiet:hover { transform: translateY(-1px); }

    .button:active,
    .button-quiet:active { transform: translateY(0) scale(0.98); }

    /* Hero load: the planes settle, then the copy appears. */
    .motion .strip { animation: strip-in 760ms cubic-bezier(0.2, 0.7, 0.2, 1) both; }
    .motion .phone-rise { animation: phone-rise 900ms cubic-bezier(0.2, 0.8, 0.2, 1) 60ms both; }
    .motion .card { animation: card-lift 620ms cubic-bezier(0.2, 0.8, 0.2, 1) 520ms both; }
    .motion .lift-shadow { animation: shadow-in 620ms cubic-bezier(0.2, 0.8, 0.2, 1) 520ms both; }
    .motion .hero h1,
    .motion .lede,
    .motion .hero-actions,
    .motion .send,
    .motion .shot-caption { animation: copy-in 480ms ease-out both; }
    .motion .hero h1 { animation-delay: 500ms; }
    .motion .lede { animation-delay: 570ms; }
    .motion .hero-actions { animation-delay: 640ms; }
    .motion .send { animation-delay: 700ms; }
    .motion .shot-caption { animation-delay: 760ms; }

    /* The press: the touch mark. The card's push toward the screen is a
       script animation (see the page script). */
    .ring.is-on { animation: press 480ms ease-out; }
    .card picture { transition: opacity 220ms ease-out; }
    .hero-media[data-state="taken"] .dose-mark { animation: mark-fill 360ms ease-out; }

    /* Feature rows wipe in along their own hairline. */
    .reveal .grid-rows li::before { transition: transform 560ms cubic-bezier(0.4, 0, 0.2, 1); }
    /* Both ends are inset() so the wipe interpolates; a clip-path cannot
       transition to none. The 0.25em bleed keeps descenders clear. */
    .reveal .grid-rows li > * {
        clip-path: inset(-0.25em 0 -0.25em 0);
        transition: clip-path 520ms cubic-bezier(0.4, 0, 0.2, 1) 180ms;
    }
    .reveal .grid-rows li:not(.is-in)::before { transform: scaleX(0); }
    .reveal .grid-rows li:not(.is-in) > * { clip-path: inset(-0.25em 100% -0.25em 0); }
    .reveal .grid-rows li:nth-child(even)::before { transition-delay: 90ms; }
    .reveal .grid-rows li:nth-child(even) > * { transition-delay: 270ms; }

    /* The sharing screen squares up from perspective. */
    .reveal .section-media img { transition: transform 900ms cubic-bezier(0.2, 0.7, 0.2, 1), opacity 500ms ease-out; }
    .reveal .section-media:not(.is-in) img {
        opacity: 0.4;
        transform: rotateY(-18deg) rotateX(5deg) translateZ(-40px);
    }

    /* The price figure arrives from below its own line. */
    .reveal .price-figure span { transition: transform 640ms cubic-bezier(0.2, 0.8, 0.2, 1); }
    .reveal .price-terms { transition: opacity 480ms ease-out 160ms, transform 480ms ease-out 160ms; }
    .reveal .price-row:not(.is-in) .price-figure span { transform: translateY(105%); }
    .reveal .price-row:not(.is-in) .price-terms { opacity: 0; transform: translateY(8px); }
}

/* Reduced motion: no animation, no transition; every element in its final
   state. The scene keeps its depth in the opening pose. */
@media (prefers-reduced-motion: reduce) {
    .hero-media { --p: 0 !important; --rx: 0deg !important; --ry: 0deg !important; }
}

@keyframes strip-in {
    from { opacity: 0; transform: translateZ(calc(var(--w) * -0.3)); }
}

@keyframes phone-rise {
    from { transform: translateY(calc(var(--hv) * 0.22)); }
}

@keyframes card-lift {
    from { transform: translateZ(calc(-1 * var(--lift))); }
}

@keyframes shadow-in {
    from { opacity: 0; }
}

@keyframes copy-in {
    from { opacity: 0; transform: translateY(8px); }
}

@keyframes press {
    0% { opacity: 1; transform: translate(-50%, -50%) scale(0.6); }
    40% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
    100% { opacity: 0; transform: translate(-50%, -50%) scale(1.25); }
}

@keyframes mark-fill {
    50% { transform: scale(1.35); }
}
