/* Hallmark · pre-emit critique: P5 H5 E5 S5 R5 V5 */
/* Hallmark · macrostructure: Workbench · genre: modern-minimal · theme: Vital 3.2 Theme Engine
 * enrichment: authentic product captures + production canvas backdrops · nav: N9 · footer: Ft2
 * contrast: pass (40–41) · slop: pass (42–45) · honest: pass (46) · chrome: pass (47)
 * tokens: pass (48) · responsive: pass (34, 49) · mobile: pass (34, 49–57) · icons: pass (30)
 */

:root {
    --font-theme-display: var(--font-display);
    --font-theme-body: var(--font-body);
    --accent-ink: var(--bg);
    --focus: var(--accent);
    --focus-ring: 0 0 0 2px var(--bg), 0 0 0 4px var(--focus);
    --theme-tracking: var(--tracking-mono);
    --theme-transition-duration: var(--dur-med);
    /* Overwritten per theme by applyThemePersonality — the curve is half
       of what tells one swap apart from the next. */
    --theme-ease: var(--ease-out);

    /* Homepage-only override (nothing else loads this sheet). The shared
       1360px measure was far wider than the hero's real content — copy plus
       a height-capped phone comes to roughly 1000-1080px — so the hero could
       only fill it by centring itself, which then knocked its left edge out
       of line with the header, the comparison and the footer. One narrower
       measure lets every band on the page share the same two edges. */
    --container-wide: min(1080px, 94vw);
}

html,
body {
    overflow-x: clip;
}

body {
    background-color: var(--bg);
    color: var(--text);
    transition:
        background-color var(--theme-transition-duration) var(--theme-ease),
        color var(--theme-transition-duration) var(--theme-ease);
}

.theme-backdrop {
    position: fixed;
    inset: 0;
    z-index: 0;
    width: 100%;
    height: 100%;
    display: block;
    pointer-events: none;
    opacity: 1;
    transition: opacity var(--theme-transition-duration) var(--theme-ease);
}

html[data-theme-transitioning="true"] .theme-backdrop {
    opacity: 0.16;
}

.launch-header,
main,
.launch-footer {
    position: relative;
    z-index: 1;
}

.skip-link {
    position: fixed;
    inset-block-start: var(--space-md);
    inset-inline-start: var(--space-md);
    z-index: 10;
    padding: var(--space-sm) var(--space-md);
    border-radius: var(--radius-sm);
    background: var(--text);
    color: var(--bg);
    font-size: var(--fs-small);
    transform: translateY(-200%);
    transition: transform var(--dur-fast) var(--ease-out);
}

.skip-link:focus-visible {
    transform: translateY(0);
}

:where(.skip-link) {
    white-space: nowrap;
}

.launch-header,
.launch-hero,
.comparison,
.launch-footer__line {
    width: var(--container-wide);
    margin-inline: auto;
}

.launch-header {
    min-height: var(--header-height);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-lg);
    border-block-end: 1px solid var(--border);
}

.launch-header,
.launch-hero__download,
.launch-form__input,
.launch-form__button,
.theme-stage__image,
.comparison,
.comparison__rows,
.comparison__row,
.launch-footer__line {
    transition:
        background-color var(--theme-transition-duration) var(--theme-ease),
        border-color var(--theme-transition-duration) var(--theme-ease),
        border-radius var(--theme-transition-duration) var(--theme-ease),
        color var(--theme-transition-duration) var(--theme-ease),
        opacity var(--theme-transition-duration) var(--theme-ease);
}

.launch-header__release,
.launch-header__download,
.launch-hero__body,
.launch-choice__divider,
.launch-form__title,
.launch-form__label,
.launch-form__feedback,
.launch-form__message,
.launch-hero__fallback,
.launch-hero__fallback a,
.comparison__labels,
.comparison__row dt,
.comparison__row dd,
.comparison__mobile-label,
.comparison__close,
.launch-footer__line,
.launch-footer a {
    transition:
        color var(--theme-transition-duration) var(--theme-ease),
        text-decoration-color var(--theme-transition-duration) var(--theme-ease);
}

.launch-header__wordmark,
.launch-header__download,
.launch-footer a {
    white-space: nowrap;
}

.launch-header__wordmark {
    min-height: var(--space-3xl);
    display: inline-flex;
    align-items: center;
    line-height: 1;
}

.launch-header__release {
    min-width: 0;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--space-lg);
    color: var(--text-secondary);
    font-family: var(--font-display);
    font-size: var(--fs-micro);
    line-height: 1;
    font-variant-numeric: tabular-nums;
}

.launch-header__download {
    min-height: var(--space-3xl);
    display: inline-flex;
    align-items: center;
    line-height: 1;
    color: var(--text);
    text-decoration: underline;
    text-decoration-color: var(--hairline);
    text-underline-offset: var(--space-xs);
}

.launch-hero {
    min-height: calc(100dvh - var(--header-height));
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    align-items: center;
    gap: var(--space-3xl);
    padding-block: var(--space-xxl) var(--space-3xl);
}

.launch-hero__copy,
.theme-stage {
    min-width: 0;
}

.launch-hero h1 {
    min-width: 0;
    font-size: var(--fs-hero);
    line-height: var(--lh-heading);
    letter-spacing: var(--tracking-heading);
    overflow-wrap: anywhere;
}

.launch-hero__body {
    max-width: 65ch;
    margin-block-start: var(--space-lg);
    color: var(--text-secondary);
    font-size: var(--fs-h3);
    line-height: var(--lh-body);
}

/* The download and the waitlist are one decision, so they sit in one
   panel. Previously the CTA slab, the OR rule and the form were three
   loose blocks stacked down the column and the fork didn't read. */
.launch-choice {
    margin-block-start: var(--space-xxl);
    padding: var(--space-xl);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background: color-mix(in srgb, var(--card) 58%, transparent);
    transition:
        background-color var(--theme-transition-duration) var(--theme-ease),
        border-color var(--theme-transition-duration) var(--theme-ease),
        border-radius var(--theme-transition-duration) var(--theme-ease);
}

.launch-choice .launch-hero__download {
    margin-block-start: 0;
}

.launch-hero__download {
    width: 100%;
    min-height: var(--space-4xl);
    margin-block-start: var(--space-xxl);
    padding: var(--space-md) var(--space-lg);
    border: 1px solid var(--text);
    border-radius: var(--radius-md);
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--space-lg);
    background: var(--text);
    color: var(--bg);
    text-decoration: none;
}

.launch-hero__download-copy {
    min-width: 0;
    display: grid;
    gap: var(--space-xs);
    line-height: 1.2;
}

.launch-hero__download-copy strong {
    font-family: var(--font-display);
    font-size: var(--fs-body);
    font-weight: 600;
}

.launch-hero__download-copy span {
    font-size: var(--fs-small);
    opacity: 0.72;
}

.launch-hero__download-arrow {
    font-family: var(--font-display);
    font-size: var(--fs-h3);
    line-height: 1;
}

.launch-hero__download:focus-visible {
    outline: 2px solid var(--focus);
    outline-offset: 3px;
}

.launch-choice__divider {
    margin-block: var(--space-lg);
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    align-items: center;
    gap: var(--space-md);
    color: var(--text-tertiary);
    font-family: var(--font-display);
    font-size: var(--fs-micro);
    line-height: 1;
    letter-spacing: var(--tracking-mono);
}

.launch-choice__divider::before,
.launch-choice__divider::after {
    content: "";
    border-block-start: 1px solid var(--hairline);
}

.launch-choice__divider + .launch-form {
    margin-block-start: 0;
}

.launch-form {
    margin-block-start: var(--space-3xl);
}

.launch-form__title {
    margin-block-end: var(--space-md);
    color: var(--text);
    font-family: var(--font-display);
    font-size: var(--fs-body);
    font-weight: 600;
    line-height: var(--lh-heading);
}

.launch-form__label {
    display: block;
    margin-block-end: var(--space-sm);
    color: var(--text-secondary);
    font-family: var(--font-display);
    font-size: var(--fs-mono);
}

.launch-form__row {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-sm);
}

.launch-form__input,
.launch-form__button {
    min-height: var(--space-3xl);
    border: 1px solid var(--hairline);
    border-radius: var(--radius-md);
    font-size: var(--fs-body);
}

.launch-form__input {
    min-width: 0;
    padding-inline: var(--space-lg);
    outline: 2px solid transparent;
    outline-offset: 1px;
    background: var(--card);
    color: var(--text);
}

.launch-form__input:focus-visible {
    outline: 2px solid var(--focus);
    outline-offset: 1px;
}

.launch-form__input::placeholder {
    color: var(--text-muted);
}

.launch-form__input[aria-invalid="true"] {
    border-color: var(--bad);
}

.launch-form__input:disabled,
.launch-form__button:disabled {
    opacity: 0.55;
    cursor: not-allowed;
}

.launch-form__button {
    padding-inline: var(--space-xl);
    background: var(--text);
    color: var(--bg);
    font-family: var(--font-display);
    white-space: nowrap;
}

.launch-form__feedback {
    margin-block-start: var(--space-sm);
    display: grid;
    gap: var(--space-xs);
    color: var(--text-tertiary);
    font-size: var(--fs-small);
}

.launch-form__message {
    min-height: 1lh;
}

.launch-form__message[data-kind="error"] {
    color: var(--bad);
}

.launch-form__message[data-kind="success"] {
    color: var(--good);
}

.launch-hero__fallback {
    margin-block-start: var(--space-lg);
    color: var(--text-secondary);
    font-size: var(--fs-small);
}

.launch-hero__fallback a {
    min-width: var(--space-3xl);
    min-height: var(--space-3xl);
    display: inline-flex;
    align-items: center;
    color: var(--text);
    text-decoration: underline;
    text-decoration-color: var(--hairline);
    text-underline-offset: var(--space-xs);
    white-space: nowrap;
}

.theme-stage {
    width: 100%;
    display: grid;
    gap: var(--space-md);
    justify-self: center;
}

.theme-stage__capture {
    min-width: 0;
    display: grid;
    place-items: center;
}

/* A bezel and a theme-tinted cast shadow, so the capture reads as a device
   sitting in the room rather than a screenshot pasted on the page. The tint
   is what carries the theme into the space around the phone. */
.theme-stage__device {
    position: relative;
    min-width: 0;
    display: block;
    padding: var(--space-sm);
    border: 1px solid var(--hairline);
    border-radius: calc(var(--radius-lg) + var(--space-sm));
    background: color-mix(in srgb, var(--card-elevated) 70%, transparent);
    box-shadow:
        0 1px 0 color-mix(in srgb, var(--text) 8%, transparent),
        0 28px 64px -28px color-mix(in srgb, var(--accent) 42%, transparent),
        0 8px 24px -12px color-mix(in srgb, var(--bg) 70%, transparent);
    transition:
        background-color var(--theme-transition-duration) var(--theme-ease),
        border-color var(--theme-transition-duration) var(--theme-ease),
        border-radius var(--theme-transition-duration) var(--theme-ease),
        box-shadow var(--theme-transition-duration) var(--theme-ease),
        transform var(--theme-transition-duration) var(--theme-ease);
}

/* The capture dips a touch as a swap lands, then settles on the incoming
   theme's own curve — bouncy themes overshoot here, crisp ones snap. */
html[data-theme-transitioning="true"] .theme-stage__device {
    transform: scale(0.985);
}

.theme-stage__image {
    width: 100%;
    height: auto;
    max-width: 100%;
    max-height: none;
    object-fit: contain;
    border: 1px solid var(--hairline);
    border-radius: var(--radius-lg);
    will-change: opacity;
}

/* The theme's name, set in the theme's own display face. This is where the
   catalogue's per-theme typography finally shows up at a size you can read
   it at — Didot, Menlo and Marker Felt should not all look alike. */
/* Set for one frame as the swap starts, so the caption re-enters last —
   backdrop sweeps, surfaces recolour, then the name lands. */
/* One segment per theme, each tinted with that theme's own accent. Replaces
   a bare "05 / 44" counter: the whole collection is visible at once, you can
   see where you are in it, and you can jump straight to any of them. */
/* The auto-advance countdown, so the cycle reads as a rhythm you can
   anticipate rather than a jump that keeps surprising you. */
.comparison {
    padding-block: var(--space-5xl);
    border-block-start: 1px solid var(--border);
}

.comparison h2 {
    min-width: 0;
    font-size: var(--fs-h2);
    overflow-wrap: anywhere;
}

.comparison__labels {
    display: none;
}

.comparison__rows {
    margin-block-start: var(--space-3xl);
    border-block-start: 1px solid var(--hairline);
}

.comparison__row {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    border-block-end: 1px solid var(--border);
}

.comparison__row dt,
.comparison__row dd {
    min-width: 0;
    padding-block: var(--space-lg);
    color: var(--text-secondary);
    font-size: var(--fs-body);
}

.comparison__row dd {
    color: var(--text);
}

.comparison__mobile-label {
    display: block;
    margin-block-end: var(--space-xs);
    color: var(--text-tertiary);
    font-family: var(--font-display);
    font-size: var(--fs-micro);
    font-variant-numeric: tabular-nums;
}

.comparison__close {
    max-width: 65ch;
    margin-block-start: var(--space-3xl);
    color: var(--text-secondary);
    font-size: var(--fs-h3);
    line-height: var(--lh-body);
}

/* Scroll choreography. Driven entirely by the scroll position via
   animation-timeline, so there is no observer and no JS to run; browsers
   without it simply get the static page, which is already correct. */
@keyframes launch-rise {
    from {
        opacity: 0;
        transform: translateY(var(--space-xl));
    }
    to {
        opacity: 1;
        transform: none;
    }
}

@supports (animation-timeline: view()) {
    @media (prefers-reduced-motion: no-preference) {
        .comparison h2,
        .comparison__row,
        .comparison__close {
            animation: launch-rise linear both;
            animation-timeline: view();
            animation-range: entry 8% cover 30%;
        }
    }
}

.launch-footer {
    width: 100%;
}

.launch-footer__line {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    line-height: 1;
    gap: var(--space-md) var(--space-xl);
    padding-block: var(--space-xl);
    border-block-start: 1px solid var(--border);
    color: var(--text-tertiary);
    font-size: var(--fs-micro);
}

.launch-footer__line p {
    line-height: var(--lh-body);
}

.launch-footer__nav {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-md);
}

.launch-footer a {
    min-width: var(--space-3xl);
    min-height: var(--space-3xl);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
    color: var(--text-secondary);
    white-space: nowrap;
}

html[data-theme-neon="true"] .launch-form__input,
html[data-theme-neon="true"] .theme-stage__image,
html[data-theme-neon="true"] html[data-theme-neon="true"] .comparison__rows {
    border-color: var(--hairline);
}

.skip-link:active {
    background: var(--accent);
    color: var(--accent-ink);
}

.launch-header__wordmark:active,
.launch-header__download:active,
.launch-hero__fallback a:active,
.launch-footer a:active {
    color: var(--text);
    opacity: 0.72;
    text-decoration-color: var(--accent);
}

.launch-form__input:active {
    background: var(--card-elevated);
}

.launch-form__button:active,
.launch-hero__download:active,
@media (hover: hover) and (pointer: fine) {
    .launch-header__download:hover,
    .launch-hero__fallback a:hover,
    .launch-footer a:hover {
        color: var(--text);
        text-decoration-color: var(--text);
    }

    .launch-form__input:hover {
        background: var(--card-elevated);
    }

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

    .launch-hero__download:hover {
        border-color: var(--accent);
        background: var(--accent);
        color: var(--accent-ink);
    }
}

@media (min-width: 40rem) {
    .launch-hero {
        padding-block: var(--space-3xl) var(--space-4xl);
    }
}

@media (min-width: 60rem) {
    /* Not a 50/50 split: the capture is height-capped, so on a short window
       it cannot fill half the container and the slack collects between the
       columns. Cap the copy at a readable measure and let the stage track
       take the remainder, with the phone pinned to its far edge — so both
       outer edges line up with every other band on the page and the leftover
       space lands in the gutter, where it belongs. */
    .launch-hero {
        grid-template-columns: minmax(0, 38rem) minmax(0, 1fr);
        gap: var(--space-4xl);
    }

    /* Shrink to the phone rather than filling the track, otherwise the
       capture centres inside a full-width stage and lands half the leftover
       space short of the page's right edge. */
    .theme-stage {
        width: auto;
        justify-self: end;
    }

    .launch-form__row {
        grid-template-columns: minmax(0, 1fr) auto;
    }

    .theme-stage__image {
        width: auto;
        max-height: 78dvh;
    }

    .comparison__labels,
    .comparison__row {
        display: grid;
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
        column-gap: var(--space-3xl);
    }

    .comparison__labels {
        margin-block-start: var(--space-3xl);
        color: var(--text-tertiary);
        font-family: var(--font-display);
        font-size: var(--fs-mono);
        font-variant-numeric: tabular-nums;
    }

    .comparison__rows {
        margin-block-start: var(--space-md);
    }

    .comparison__mobile-label {
        display: none;
    }

    /* A short accent rule leading each 3.2 answer, so the eye travels
       left-to-right from what it was to what it becomes. */
    .comparison__row dd {
        position: relative;
        padding-inline-start: var(--space-xl);
    }

    .comparison__row dd::before {
        content: "";
        position: absolute;
        inset-inline-start: 0;
        inset-block-start: calc(var(--space-lg) + 0.6lh);
        width: var(--space-md);
        border-block-start: 2px solid var(--accent);
        transition: border-color var(--theme-transition-duration) var(--theme-ease);
    }
}

/* Laptop windows are wide but short, and the hero's vertical padding is a
   fixed 112px there — enough to push the waitlist panel past the fold on a
   600px-tall window. Give the padding back when height is the scarce axis. */
@media (min-width: 60rem) and (max-height: 46rem) {
    .launch-hero {
        padding-block: var(--space-xl) var(--space-xxl);
    }
}

@media (max-width: 59.999rem) {
    .launch-hero,
    .launch-form__row,
    .comparison__row {
        grid-template-columns: minmax(0, 1fr);
    }

}

@media (max-width: 40rem) {
    .launch-header__release {
        gap: var(--space-sm);
    }

    .launch-footer__line {
        align-items: flex-start;
        flex-direction: column;
    }
}

@media (prefers-reduced-motion: reduce) {
    :where(
        body,
        .theme-backdrop,
        .skip-link,
        .launch-header,
        .launch-header__release,
        .launch-header__download,
            .launch-hero__body,
        .launch-hero__download,
        .launch-choice__divider,
        .launch-form__title,
        .launch-form__label,
        .launch-form__input,
        .launch-form__button,
        .launch-form__feedback,
        .launch-form__message,
        .launch-hero__fallback,
        .launch-hero__fallback a,
        .theme-stage__image,
                                .comparison,
        .comparison__labels,
        .comparison__rows,
        .comparison__row,
        .comparison__row dt,
        .comparison__row dd,
        .comparison__mobile-label,
        .comparison__close,
        .launch-footer__line,
        .launch-footer a,
        .launch-choice,
        .theme-stage__device
    ) {
        transition: none;
    }

    /* No pulse, no dip, no reveal — the swap still happens, it just
       stops performing. */
    :where(
        .comparison h2,
        .comparison__row,
        .comparison__close
    ) {
        animation: none;
    }

    html[data-theme-transitioning="true"] .theme-stage__device {
        transform: none;
    }
}
