/* lunchdate.io home page. Legal and form pages keep styles.css.
 *
 * Typography mirrors the app: SF Pro Expanded for display text, SF Pro for the
 * rest. Apple platforms resolve -apple-system to SF and honour font-stretch;
 * elsewhere display text uses Lunchdate Display (below), body text the system
 * sans.
 * Colours are the app's AppTheme tokens (iOS/Lunchdate/Theme/AppTheme.swift).
 * Shape rule: pills for interactive elements, 28px for surfaces. The device
 * frame has its own geometry.
 */

/* Display voice where SF Pro is missing (Windows, Android, Linux): Roboto Flex
   subsets whose width axis is remapped so font-stretch: expanded matches SF Pro
   Expanded (scripts/website-display-font.py, licence in assets/fonts/OFL.txt).
   Apple platforms resolve -apple-system first and never download these files.
   styles.css carries the same rules for the legal pages. */
@font-face {
    font-family: "Lunchdate Display";
    src: url("assets/fonts/display-latin.woff2") format("woff2");
    font-weight: 600 700;
    font-stretch: 100% 151%;
    font-display: swap;
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074,
        U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: "Lunchdate Display";
    src: url("assets/fonts/display-latin-ext.woff2") format("woff2");
    font-weight: 600 700;
    font-stretch: 100% 151%;
    font-display: swap;
    unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB,
        U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
    --bg: #FAF9F6;
    --surface: #FFFFFF;
    --sand: #EDE8DF;
    --ink: #1B1F24;
    --ink-2: #3A3F47;
    --ink-3: #555B64;
    --line: rgba(27, 31, 36, 0.12);
    --header-glass: rgba(250, 249, 246, 0.78);
    --shadow: 31, 42, 68;

    --font-text: -apple-system, BlinkMacSystemFont, "Segoe UI Variable Text", "Segoe UI", Roboto,
        "Helvetica Neue", Arial, sans-serif;
    --font-display: -apple-system, BlinkMacSystemFont, "Lunchdate Display", "Segoe UI Variable Display", "Segoe UI",
        Roboto, "Helvetica Neue", Arial, sans-serif;

    --page: 1180px;
    --gutter: clamp(16px, 4.5vw, 40px);
    --radius: 28px;
    /* One vertical rhythm between sections (tour, Pro, questions, closing). */
    --space-section: clamp(56px, 7vw, 96px);
    --ease: cubic-bezier(0.16, 1, 0.3, 1);
    color-scheme: light dark;
}

@media (prefers-color-scheme: dark) {
    :root {
        --bg: #121416;
        --surface: #1C1F24;
        --sand: #232830;
        --ink: #F5F5F5;
        --ink-2: #D2D4D7;
        --ink-3: #A9AEB4;
        --line: rgba(245, 245, 245, 0.12);
        --header-glass: rgba(18, 20, 22, 0.74);
        --shadow: 0, 0, 0;
    }
}

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

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

@media (prefers-reduced-motion: no-preference) {
    html {
        scroll-behavior: smooth;
    }
}

body {
    margin: 0;
    background: var(--bg);
    color: var(--ink);
    font-family: var(--font-text);
    font-size: 17px;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    overflow-x: hidden;
}

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

a {
    color: inherit;
}

:focus-visible {
    outline: 2px solid var(--ink);
    outline-offset: 3px;
    border-radius: 6px;
}

.wrap {
    width: min(var(--page), 100% - 2 * var(--gutter));
    margin-inline: auto;
}

.display {
    font-family: var(--font-display);
    font-stretch: expanded;
    font-weight: 700;
    letter-spacing: -0.012em;
    line-height: 1.06;
    margin: 0;
    text-wrap: balance;
}

.lede {
    color: var(--ink-2);
    font-size: clamp(1.05rem, 1rem + 0.35vw, 1.25rem);
    line-height: 1.5;
    max-width: 34em;
    margin: 0;
    text-wrap: pretty;
}

.skip-link {
    position: absolute;
    left: 16px;
    top: -60px;
    z-index: 30;
    padding: 10px 16px;
    border-radius: 999px;
    background: var(--ink);
    color: var(--bg);
    text-decoration: none;
}

.skip-link:focus {
    top: 12px;
}

/* Header ------------------------------------------------------------------ */

.site-header {
    position: sticky;
    top: 0;
    z-index: 20;
    background: var(--header-glass);
    -webkit-backdrop-filter: saturate(180%) blur(20px);
    backdrop-filter: saturate(180%) blur(20px);
    border-bottom: 1px solid transparent;
    transition: border-color 0.3s var(--ease);
}

.site-header.is-scrolled {
    border-bottom-color: var(--line);
}

@media (prefers-reduced-transparency: reduce) {
    .site-header {
        background: var(--bg);
        -webkit-backdrop-filter: none;
        backdrop-filter: none;
    }
}

.site-header__inner {
    display: flex;
    align-items: center;
    gap: 24px;
    height: 64px;
}

.brand {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    text-decoration: none;
    font-family: var(--font-display);
    font-stretch: expanded;
    font-weight: 700;
    font-size: 17px;
    letter-spacing: -0.01em;
}

/* The app icon carries its own rounded mask (ictool export). */
.brand img {
    display: block;
    width: 30px;
    height: 30px;
}

.site-nav {
    display: flex;
    gap: 28px;
    margin-left: auto;
}

.site-nav a {
    /* 6 px above and below: a 30 px target (WCAG 2.5.8 asks for 24). */
    padding: 6px 0;
    color: var(--ink-2);
    font-size: 15px;
    text-decoration: none;
    transition: color 0.2s var(--ease);
}

.site-nav a:hover {
    color: var(--ink);
}

.lang-switch {
    display: inline-flex;
    padding: 3px;
    border-radius: 999px;
    background: var(--sand);
}

.lang-switch a {
    padding: 7px 12px;
    border-radius: 999px;
    background: transparent;
    color: var(--ink-3);
    font: 600 13px/1 var(--font-text);
    letter-spacing: 0.02em;
    text-decoration: none;
    transition: background-color 0.2s var(--ease), color 0.2s var(--ease);
}

.lang-switch a[aria-current="true"] {
    background: var(--surface);
    color: var(--ink);
    box-shadow: 0 1px 3px rgba(var(--shadow), 0.12);
}

@media (max-width: 860px) {
    .site-nav {
        display: none;
    }

    .lang-switch {
        margin-left: auto;
    }
}

/* Device frame ------------------------------------------------------------ */
/* Apple's product bezel for iPhone 18 Pro in Silver (Apple Design Resources,
   Bezel-iPhone-18.dmg, 1350 x 2760 px PNG, here as WebP). Apple's marketing
   guidelines require the official bezel, used as is: no added shadows,
   reflections or highlights, never cropped or covered by another device, and
   several devices at the same scale. The screenshot sits under the bezel in
   its transparent display opening, 1206 x 2622 px at 72, 69: the 402 x 874 pt
   screen at @3x. --w is the width of the whole image, side buttons included. */

.phone {
    --w: 320px;
    position: relative;
    width: var(--w);
    aspect-ratio: 1350 / 2760;
    flex: none;
    margin: 0;
}

.phone::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    background: url("assets/iphone-18-pro-silver.webp") center / 100% 100% no-repeat;
}

.phone__screen {
    position: absolute;
    left: calc(100% * 72 / 1350);
    top: calc(100% * 69 / 2760);
    width: calc(100% * 1206 / 1350);
    height: calc(100% * 2622 / 2760);
    /* Measured: any radius from 76 to 186 px (bezel pixels) hides the
       corners under the bezel without cutting into the opening. */
    border-radius: calc(var(--w) * 130 / 1350);
    overflow: hidden;
    background: var(--bg);
    isolation: isolate;
}

.phone__screen img,
.phone__video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* A clip starts on its poster's frame, so it fades in over the screenshot
   without a jump once it actually plays. */
.phone__video {
    opacity: 0;
    transition: opacity 0.3s ease-out;
}

.phone__video.is-playing {
    opacity: 1;
}

/* App Store ---------------------------------------------------------------- */

.store {
    display: grid;
    justify-items: start;
    gap: 10px;
}

.store__row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px 18px;
}

.store__note {
    margin: 0;
    color: var(--ink-3);
    font-size: 14px;
}

/* QR code for visitors at a computer: only once the badge links to the App
   Store, and only with a mouse or trackpad. It encodes lunchdate.io/app
   (app.html), which forwards to the store. Dark modules on white in both
   schemes, as camera apps expect. */
.store__qr {
    display: none;
    align-items: center;
    gap: 12px;
    margin: 0;
}

@media (hover: hover) and (pointer: fine) {
    .store__row:has(.app-store-badge[href]) .store__qr {
        display: inline-flex;
    }
}

.store__qr img {
    width: 76px;
    height: 76px;
    border-radius: 10px;
    outline: 1px solid var(--line);
    outline-offset: -1px;
}

.store__qr figcaption {
    max-width: 8.5em;
    color: var(--ink-3);
    font-size: 13px;
    line-height: 1.3;
    text-align: left;
}

/* Apple's badge artwork exactly as provided: not restyled, recoloured or
   animated, at least 40px tall on screen (App Store marketing guidelines). */
.app-store-badge {
    display: inline-block;
    line-height: 0;
    border-radius: 10px;
}

.app-store-badge img {
    display: block;
    width: auto;
    height: 50px;
}

.app-store-badge:focus-visible {
    outline: 2px solid var(--ink);
    outline-offset: 3px;
}

/* Until app-store.js has a store ID the link has no href: the status pill
   below stands in for it, so nothing on the page looks clickable but isn't. */
.app-store-badge:not([href]) {
    display: none;
}

.coming-soon {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    min-height: 50px;
    margin: 0;
    padding: 0 22px;
    border-radius: 999px;
    background: var(--sand);
    color: var(--ink-2);
    font: 600 16px/1 var(--font-text);
    white-space: nowrap;
}

.coming-soon[hidden] {
    display: none;
}

.text-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: var(--ink);
    font-weight: 600;
    font-size: 16px;
    text-decoration: none;
}

.text-link span {
    transition: transform 0.25s var(--ease);
}

.text-link:hover span {
    transform: translateX(3px);
}

/* Hero --------------------------------------------------------------------- */

.hero {
    /* Also follows the window height, so a short laptop window keeps the
       device whole beside the copy (see the device width below). */
    --hero-top: clamp(40px, min(7vw, 10svh), 88px);
    padding: var(--hero-top) 0 clamp(56px, 8vw, 104px);
}

.hero__grid {
    display: grid;
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
    align-items: center;
    gap: clamp(32px, 4vw, 56px);
}

.hero__copy {
    display: grid;
    gap: 26px;
    justify-items: start;
}

.hero h1 {
    font-size: clamp(2rem, 0.9rem + 4.1vw, 4.1rem);
}

/* The store block closes the copy under a hairline. Until launch it is a
   plain status line, not a pill that looks like a button. */
.hero .store {
    width: 100%;
    max-width: 29rem;
    margin-top: 10px;
    padding-top: 22px;
    border-top: 1px solid var(--line);
    gap: 4px;
}

.hero .coming-soon {
    min-height: 0;
    padding: 0;
    background: none;
    color: var(--ink);
    font: 600 17px/1.3 var(--font-text);
}

.hero .store__note {
    font-size: 15px;
}

/* Beside the device the lede breaks at the comma; stacked it runs free. */
.lede__break {
    display: none;
}

@media (min-width: 861px) {
    .lede__break {
        display: inline;
    }

    /* Safari's pretty wrapping rebalances the hand-broken lines and pushed
       "deiner Nähe," onto a line of its own. */
    .hero .lede {
        text-wrap: wrap;
    }
}

.hero__devices {
    display: flex;
    justify-content: center;
}

.hero__devices .phone {
    --w: clamp(270px, 26vw, 330px);
}

@media (min-width: 861px) {
    /* Beside the copy the whole device stays above the fold: no taller than
       the window below the header and the top padding, 24px to spare, and
       never under Apple's 200px minimum. */
    .hero__devices .phone {
        --w: max(calc(200px * 1350 / 2760),
                min(clamp(270px, 26vw, 330px), calc((100svh - 64px - var(--hero-top) - 24px) * 1350 / 2760)));
    }
}

@media (max-width: 860px) {
    /* Phones and narrow tablets: copy on top, device below. */
    .hero__grid {
        grid-template-columns: 1fr;
    }

    .hero__copy {
        justify-items: start;
    }
}

@media (max-width: 600px) {
    .hero__devices .phone {
        --w: min(72vw, 300px);
    }
}

/* Statement ---------------------------------------------------------------- */

/* Framed by hairlines above and below, so the tour after it opens a new
   section instead of floating under the centred line. */
.statement {
    padding: clamp(48px, 6vw, 80px) 0;
    border-top: 1px solid var(--line);
    border-bottom: 1px solid var(--line);
}

.statement p {
    max-width: 27em;
    margin: 0 auto;
    text-align: center;
    font-family: var(--font-display);
    font-stretch: expanded;
    font-weight: 600;
    font-size: clamp(1.35rem, 0.95rem + 1.4vw, 1.95rem);
    line-height: 1.28;
    letter-spacing: -0.01em;
    text-wrap: balance;
}

@media (max-width: 600px) {
    /* Semi-expanded on phones, like the app's long reading texts. */
    .statement p {
        font-stretch: 112%;
        font-size: 1.3rem;
        line-height: 1.34;
    }
}

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

/* Tour (sticky phone, scrolling steps) -------------------------------------- */

.tour {
    padding: var(--space-section) 0 clamp(32px, 4vw, 64px);
}

.section-head {
    display: grid;
    gap: 14px;
    max-width: 40rem;
    margin-bottom: clamp(32px, 5vw, 56px);
}

.section-head h2,
.pro h2,
.faq h2,
.closing h2 {
    font-size: clamp(2rem, 1.3rem + 2.4vw, 3.1rem);
}

.tour__grid {
    display: grid;
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
    column-gap: clamp(32px, 6vw, 96px);
}

/* The section head sits in the scene, so the pinned scene keeps it in view
   through every step; unpinned it simply spans the grid above phone and text. */
.tour__scene > .section-head {
    grid-column: 1 / -1;
}

.tour__stage {
    --stage-w: min(clamp(260px, 25vw, 318px), calc((100svh - 112px) * 1350 / 2760));
    position: sticky;
    top: calc(64px + (100svh - 64px - var(--stage-w) * 2760 / 1350) / 2);
    align-self: start;
    display: flex;
    justify-content: center;
}

.tour__stage .phone {
    --w: var(--stage-w);
}

/* The outgoing screen leaves before the next one arrives, so two app
   screens never sit on top of each other mid-fade. */
.tour__stage .phone__screen img {
    opacity: 0;
    transform: scale(0.985);
    transition: opacity 0.22s ease-out, transform 0.22s ease-out;
}

.tour__stage .phone__screen img.is-active {
    opacity: 1;
    transform: none;
    transition: opacity 0.45s var(--ease) 0.2s, transform 0.45s var(--ease) 0.2s;
}

/* The step-1 clip shows only while its step is active, over its own poster. */
.tour__stage .phone__video:not(.is-active) {
    opacity: 0;
    transition: opacity 0.22s ease-out;
}

.steps {
    list-style: none;
    margin: 0;
    padding: 0;
}

.step {
    display: grid;
    align-content: center;
    gap: 14px;
    min-height: 78vh;
    padding: 24px 0;
    transition: opacity 0.5s var(--ease);
}

/* Dimmed, but still readable: 0.74 keeps body text above 4.5:1 in both schemes. */
.js .step:not(.is-active) {
    opacity: 0.74;
}

.step:last-child {
    min-height: 62vh;
}

.step h3 {
    font-size: clamp(1.6rem, 1.2rem + 1.4vw, 2.3rem);
}

.step p {
    margin: 0;
    text-wrap: pretty;
    max-width: 30em;
    color: var(--ink-2);
    font-size: 18px;
}

.step__media {
    display: none;
}

/* Unpinned, the scene wrapper is layout-neutral: stage and steps stay grid items. */
.tour__scene {
    display: contents;
}

/* Beside the tour phone (never on it, Apple's rules): the step dots of the
   pinned tour and the pause control of the clip. */
.tour__rail {
    display: none;
}

@media (min-width: 861px) {
    .tour__rail {
        position: absolute;
        right: 0;
        top: 50%;
        translate: 0 -50%;
        display: grid;
        justify-items: center;
        gap: 18px;
        /* As wide as the pause control, shown or not, so the dots never
           shift sideways when a step without a clip hides it. */
        width: 32px;
    }
}

.tour__dots {
    display: none;
}

.tour__dots i {
    display: block;
    width: 6px;
    height: 6px;
    border-radius: 3px;
    background: var(--line);
    transition: height 0.3s var(--ease), background-color 0.3s;
}

.tour__dots i.is-active {
    height: 18px;
    background: var(--ink-3);
}

@media (max-width: 860px) {
    .tour__grid {
        grid-template-columns: 1fr;
        gap: 0;
    }

    /* Stacked (no JS, or a screen too low for the pinned scene): each step
       with its own phone. */
    .tour__stage {
        display: none;
    }

    .step {
        min-height: 0;
        padding: 0 0 56px;
    }

    .step__media {
        display: flex;
        justify-content: center;
        margin-bottom: 12px;
    }

    .step__media .phone {
        --w: min(72vw, 300px);
    }

    .js .step:not(.is-active) {
        opacity: 1;
    }
}

/* Tour, pinned (home.js sets .is-pinned when the longest step and the
   phone fit the screen together). Phone and text stay in place while the
   page scrolls through the track; the scroll position picks the step and
   the text swaps where it stands, so it never drifts or leaves a gap. Copy
   stays beside the device, never on it (Apple's rules). svh, not vh, so the
   toolbars don't resize the scene. */
.tour__grid.is-pinned {
    --tour-step-scroll: 45svh;
    display: block;
    height: calc(100svh - 64px + var(--tour-steps, 5) * var(--tour-step-scroll));
}

.is-pinned .tour__scene {
    position: sticky;
    top: 64px;
    height: calc(100svh - 64px);
}

.is-pinned .tour__stage {
    position: relative;
    top: auto;
}

.is-pinned .tour__rail {
    position: absolute;
    right: 0;
    top: 50%;
    translate: 0 -50%;
    display: grid;
    justify-items: center;
    gap: 18px;
    width: 32px;
}

.is-pinned .tour__dots {
    display: grid;
    gap: 8px;
}

.is-pinned .step__media {
    display: none;
}

/* All steps share one cell, so the text area is as tall as the longest
   text and every heading sits at the same spot. */
.is-pinned .steps {
    display: grid;
}

.is-pinned .step {
    grid-area: 1 / 1;
    min-height: 0;
}

/* Phone: the phone on top, as tall as the space above the text allows. */
@media (max-width: 860px) {
    .is-pinned .tour__scene {
        display: flex;
        flex-direction: column;
    }

    /* Compact on a phone, so the device keeps most of the height. */
    .is-pinned .tour__scene > .section-head {
        flex: none;
        gap: 6px;
        margin: 0;
        padding-top: 14px;
    }

    .is-pinned .tour__scene > .section-head h2 {
        font-size: 1.4rem;
    }

    .is-pinned .tour__stage {
        align-self: stretch;
        flex: 1 1 auto;
        min-height: 0;
        display: flex;
        justify-content: center;
        align-items: center;
        padding-top: 24px;
        container-type: size;
        --phone-cap: 300px;
    }

    /* As tall as the stage allows (cqh is the content box, the padding is
       already out), never wider than --phone-cap. */
    .is-pinned .tour__stage .phone {
        --w: min(calc(100cqh * 1350 / 2760), var(--phone-cap));
    }

    /* Beside the phone rather than at the screen edge, centred on it. */
    .is-pinned .tour__rail {
        top: calc(50% + 12px);
        right: max(0px, calc(50% - min(100cqh * 1350 / 2760, var(--phone-cap)) / 2 - 48px));
    }

    .is-pinned .steps {
        flex: none;
    }

    .is-pinned .step {
        align-content: start;
        padding: 20px 0 24px;
    }
}

/* Tablet portrait: the phone layout, with a larger device and the full-size
   section title, so the scene does not leave a gap under a small phone. */
@media (min-width: 600px) and (max-width: 860px) {
    .is-pinned .tour__stage {
        --phone-cap: 380px;
    }

    .is-pinned .tour__scene > .section-head {
        gap: 12px;
    }

    .is-pinned .tour__scene > .section-head h2 {
        font-size: clamp(2rem, 1.3rem + 2.4vw, 3.1rem);
    }
}

/* Desktop: the section head on top, below it phone left and text right,
   centred in the space that is left. */
@media (min-width: 861px) {
    .is-pinned .tour__scene {
        display: grid;
        grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
        grid-template-rows: auto minmax(0, 1fr);
        column-gap: clamp(32px, 6vw, 96px);
        align-items: center;
        padding-bottom: clamp(24px, 4svh, 40px);
    }

    .is-pinned .tour__scene > .section-head {
        margin: 0;
        padding: clamp(32px, 5svh, 48px) 0 clamp(16px, 2.5svh, 24px);
    }

    .is-pinned .tour__stage {
        align-self: stretch;
        display: flex;
        justify-content: center;
        align-items: center;
        container-type: size;
    }

    /* As tall as the space under the head allows, never above --stage-w. */
    .is-pinned .tour__stage .phone {
        --w: min(calc(100cqh * 1350 / 2760), var(--stage-w));
    }

    .is-pinned .step {
        align-content: center;
        padding: 0;
    }
}

.is-pinned .step:not(.is-active) {
    opacity: 0;
    translate: 0 10px;
    pointer-events: none;
    transition: opacity 0.2s ease-out, translate 0.2s ease-out;
}

.is-pinned .step.is-active {
    opacity: 1;
    translate: none;
    transition: opacity 0.35s ease-out 0.12s, translate 0.45s var(--ease) 0.12s;
}

/* Crossfade without a blank frame: the new screen fades in over the old one,
   which leaves only once it is covered. */
.is-pinned .tour__stage .phone__screen img {
    transform: none;
    transition: opacity 0s linear 0.4s;
}

.is-pinned .tour__stage .phone__screen img.is-active {
    z-index: 1;
    transition: opacity 0.35s ease-out;
}

.is-pinned .tour__stage .phone__video.is-active {
    z-index: 2;
    transition: opacity 0.35s ease-out;
}

.is-pinned .tour__stage .phone__video:not(.is-active) {
    transition: opacity 0s linear 0.4s;
}

/* One step per swipe, on a phone only: in the pinned tour the page snaps
   to the middle of each step's stretch, and scroll-snap-stop keeps a strong
   swipe from rolling past the next step. On desktop a slow trackpad scroll
   of less than half a step snapped back up, so there the scene alone keeps
   the text in place. home.js places the snap areas: one marker per step,
   plus one tall area above and one below the tour, which keep the rest of
   the page free (a snap area taller than the screen may rest anywhere
   inside it). Snapping is on only near the tour: it changes how iOS carries
   momentum even in the free areas.
   The bottom padding shrinks the snapport to a line under the header (svh,
   not %, which an engine may resolve against the width). With the full
   screen as snapport, a step marker anywhere on screen already counts, and
   the screen above the tour turned into a magnet. */
.tour-snapping {
    scroll-snap-type: y mandatory;
    scroll-padding-bottom: calc(100svh - 81px);
}

.tour-snap {
    position: absolute;
    left: 0;
    width: 1px;
    pointer-events: none;
    scroll-snap-align: start;
}

.tour-snap--step {
    height: 1px;
    scroll-snap-stop: always;
}

@media (prefers-reduced-motion: reduce) {
    .is-pinned .step:not(.is-active),
    .is-pinned .step.is-active,
    .is-pinned .tour__stage .phone__screen img,
    .is-pinned .tour__stage .phone__screen img.is-active,
    .is-pinned .tour__stage .phone__video {
        translate: none;
        transition: none;
    }
}

/* Pause control for the looping clips (WCAG 2.2.2). home.js shows it while
   motion is allowed and a clip is the current content. */
.clip-toggle {
    display: grid;
    place-items: center;
    width: 32px;
    height: 32px;
    padding: 0;
    border: 1px solid var(--line);
    border-radius: 50%;
    background: var(--surface);
    color: var(--ink-2);
    cursor: pointer;
}

.clip-toggle[hidden] {
    display: none;
}

/* Beside the tour phone the control hangs below the dots instead of adding
   to the rail's height: the rail is centred on the phone, so showing or
   hiding the control would otherwise move the dots up and down. */
.tour__rail .clip-toggle {
    position: absolute;
    top: calc(100% + 18px);
    left: 0;
}

.clip-toggle svg {
    width: 12px;
    height: 12px;
    fill: currentColor;
}

.clip-toggle__play,
.clip-toggle[aria-pressed="true"] .clip-toggle__pause {
    display: none;
}

.clip-toggle[aria-pressed="true"] .clip-toggle__play {
    display: block;
}

.clip-toggle:focus-visible {
    outline: 2px solid var(--ink);
    outline-offset: 2px;
}

/* Pro: a sand band with its own two-step tour (trips, Travel Mode); the
   other Pro features follow on one surface ---------------------------------- */

.pro {
    padding: var(--space-section) 0;
    background: var(--sand);
}

.pro__after {
    display: grid;
    gap: 14px;
    max-width: 34rem;
}

/* Under the text column of the scene beside the phone. */
@media (min-width: 861px) {
    .pro__after {
        margin-left: calc((100% - clamp(32px, 6vw, 96px)) * 0.9 / 2 + clamp(32px, 6vw, 96px));
    }
}

/* The other Pro features sit together on one surface, one short line each,
   in the app's paywall names. */
.pro__more {
    display: grid;
    gap: 6px;
    padding: 22px 24px 10px;
    border-radius: var(--radius);
    background: var(--surface);
}

.pro__list {
    margin: 0;
    padding: 0;
    list-style: none;
}

.pro__list li {
    display: grid;
    gap: 2px;
    padding: 13px 0;
    border-top: 1px solid var(--line);
}

.pro__list li:first-child {
    border-top: 0;
}

.pro__list strong {
    font-weight: 600;
}

.pro__list span {
    color: var(--ink-2);
    font-size: 15px;
    text-wrap: pretty;
}

.pro__note {
    text-wrap: pretty;
    margin: 4px 0 0;
    color: var(--ink-3);
    font-size: 15px;
}

.eyebrow {
    margin: 0;
    color: var(--ink-3);
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

/* FAQ: native disclosure rows on one surface, like the Pro list ---------------- */

.faq {
    padding: var(--space-section) 0;
}

/* The same columns as the tours, so the list lines up with the step text. */
.faq__grid {
    display: grid;
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
    align-items: start;
    gap: clamp(24px, 6vw, 96px) clamp(32px, 6vw, 96px);
}

.faq__list {
    padding: 4px clamp(20px, 3vw, 28px);
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: inset 0 0 0 1px var(--line);
}

.faq__item + .faq__item {
    border-top: 1px solid var(--line);
}

.faq__item summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    min-height: 44px;
    padding: 16px 0;
    font-weight: 600;
    list-style: none;
    cursor: pointer;
    text-wrap: pretty;
}

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

/* Chevron from two borders; it turns up while the answer is open. */
.faq__item summary::after {
    content: "";
    flex: none;
    width: 8px;
    height: 8px;
    margin: -4px 4px 0 0;
    border-right: 2px solid var(--ink-3);
    border-bottom: 2px solid var(--ink-3);
    transform: rotate(45deg);
}

.faq__item[open] summary::after {
    margin-top: 4px;
    transform: rotate(-135deg);
}

@media (prefers-reduced-motion: no-preference) {
    .faq__item summary::after {
        transition: transform 0.3s var(--ease), margin 0.3s var(--ease);
    }
}

.faq__item p {
    margin: -4px 0 0;
    padding-bottom: 20px;
    max-width: 38em;
    color: var(--ink-2);
    text-wrap: pretty;
}

@media (max-width: 860px) {
    .faq__grid {
        grid-template-columns: 1fr;
    }
}

/* Closing: the store once more at the end of the page --------------------------- */

.closing {
    padding: var(--space-section) 0;
    border-top: 1px solid var(--line);
}

.closing__inner {
    display: grid;
    justify-items: center;
    gap: 22px;
    text-align: center;
}

.closing__icon {
    width: 72px;
    height: 72px;
}

.closing .store {
    justify-items: center;
}

.closing .store__row {
    justify-content: center;
}

/* Footer ---------------------------------------------------------------------- */

.site-footer {
    padding: 40px 0 calc(40px + env(safe-area-inset-bottom));
    border-top: 1px solid var(--line);
    color: var(--ink-3);
    font-size: 14px;
}

.site-footer__inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 18px 32px;
}

.site-footer nav {
    display: flex;
    flex-wrap: wrap;
    gap: 10px 22px;
}

.site-footer a {
    display: inline-block;
    padding: 4px 0;
    color: var(--ink-2);
    text-decoration: none;
}

.site-footer a:hover {
    color: var(--ink);
    text-decoration: underline;
}

/* The icon stays beside the first line when the company line wraps. */
.site-footer__brand {
    display: inline-flex;
    align-items: flex-start;
    gap: 10px;
}

.site-footer__brand img {
    display: block;
    width: 22px;
    height: 22px;
}

/* Standalone pages: the 404 page and the app-link landing (app-link.html for
   /connect|refer|match|profile/**). Same header, footer and type as the home
   page; the copy stands centred under the app icon. Without app-link.js both
   languages show, one under the other. ---------------------------------------- */

.side {
    display: grid;
    align-items: center;
    min-height: calc(100svh - 64px - 160px);
    padding: var(--space-section) 0;
}

.side__inner {
    display: grid;
    justify-items: center;
    gap: 28px;
    max-width: 34rem;
    text-align: center;
}

.side__icon {
    width: 72px;
    height: 72px;
}

.app-link-copy {
    display: grid;
    justify-items: center;
    gap: 16px;
    width: 100%;
}

.app-link-copy[hidden],
.app-link-note[hidden],
.app-link-lang-switch[hidden] {
    display: none;
}

.app-link-copy:not([hidden]) ~ .app-link-copy:not([hidden]) {
    padding-top: 28px;
    border-top: 1px solid var(--line);
}

.app-link-copy h1 {
    font-size: clamp(1.75rem, 1.3rem + 1.8vw, 2.5rem);
}

.app-link-copy p {
    margin: 0;
    color: var(--ink-2);
    text-wrap: pretty;
}

.app-link-note {
    display: grid;
    gap: 8px;
    width: 100%;
    padding: 20px 24px;
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: inset 0 0 0 1px var(--line);
}

.app-link-code {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 1.6rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    color: var(--ink);
    -webkit-user-select: all;
    user-select: all;
}

.side__store {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 12px;
    margin-top: 4px;
}

.app-link-lang-switch {
    appearance: none;
    -webkit-appearance: none;
    min-height: 44px;
    padding: 0 12px;
    border: 0;
    background: none;
    color: var(--ink-3);
    font: inherit;
    font-size: 15px;
    cursor: pointer;
}

.app-link-lang-switch:hover {
    color: var(--ink);
}

/* Motion ---------------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
    .js .reveal {
        opacity: 0;
        transform: translateY(16px);
        transition: opacity 0.6s var(--ease), transform 0.6s var(--ease);
    }

    .js .reveal.is-visible {
        opacity: 1;
        transform: none;
    }

    .hero__copy > *,
    .hero__devices {
        animation: rise 0.9s var(--ease) both;
    }

    .hero__copy > :nth-child(2) {
        animation-delay: 0.08s;
    }

    .hero__copy > :nth-child(3) {
        animation-delay: 0.16s;
    }

    .hero__devices {
        animation-delay: 0.12s;
    }
}

@media (prefers-reduced-motion: reduce) {
    .tour__stage .phone__screen img,
    .tour__stage .phone__screen img.is-active,
    .step {
        transform: none;
        transition: none;
    }
}

@keyframes rise {
    from {
        opacity: 0;
        transform: translateY(18px);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

@media print {
    .js .reveal,
    .js .step:not(.is-active),
    .is-pinned .step:not(.is-active) {
        opacity: 1 !important;
        transform: none !important;
        translate: none !important;
    }

    .tour__stage,
    .step__media,
    .clip-toggle {
        display: none !important;
    }

    /* Printed, every answer shows, open or not. */
    .faq__item::details-content {
        content-visibility: visible;
    }

    .faq__item summary::after {
        display: none;
    }

    .tour__grid.is-pinned,
    .is-pinned .tour__scene,
    .is-pinned .steps {
        display: block;
        position: static;
        height: auto;
    }

    .step {
        min-height: 0 !important;
        padding: 0 0 24px !important;
        break-inside: avoid;
    }

    .hero__copy > *,
    .hero__devices {
        animation: none !important;
    }

    .site-header {
        position: static;
    }
}
