/* ─────────────────────────────────────────────────────────────────────────────
 * Pre-login landing page (SDW-668). Loaded only by templates/landing/index.html.
 *
 * Every color here is a shody-system.css token. data_warehouse/style_drift.py
 * scans static/css/*.css as well as templates/, so a raw hex or an rgba() literal
 * in this file fails CI exactly as it would in the template. Reach for a token;
 * if none fits, add one to the token block rather than inlining a value here.
 *
 * Motion: shody-system.css already neutralizes animation and transition under
 * `prefers-reduced-motion: reduce` globally, so the flow dot and the scroll
 * reveal below stop on their own -- they need no separate media query. Both are
 * decoration layered onto content that is fully visible without them, which is
 * also what keeps the page readable with JavaScript disabled (there is none).
 * ──────────────────────────────────────────────────────────────────────────── */

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

.lp {
    margin: 0;
    font-family: var(--shody-font-sans);
    color: var(--shody-text);
    background: var(--shody-surface-0);
    -webkit-font-smoothing: antialiased;
}

.lp-shell {
    width: 100%;
    max-width: 68rem;
    margin-inline: auto;
    padding-inline: var(--shody-gap-lg);
}

/* Keyboard users land here first; hidden until focused. */
.lp-skip {
    position: absolute;
    left: -9999px;
    top: var(--shody-gap-md);
    z-index: 2;
    padding: var(--shody-gap-xs) var(--shody-gap-md);
    border-radius: var(--shody-r-sm);
    background: var(--shody-surface-0);
    color: var(--shody-text-strong);
    font-size: var(--shody-type-body);
    text-decoration: none;
}
.lp-skip:focus { left: var(--shody-gap-md); }

/* ── Hero: the dark command surface, continuous with the sign-in card ─────── */

.lp-hero {
    position: relative;
    overflow: hidden;
    background: linear-gradient(180deg, var(--shody-ink-900) 0%, var(--shody-ink-800) 100%);
    color: var(--shody-text-invert);
    padding-block: clamp(3.5rem, 9vw, 7rem);
}

/* Data-topology substrate: the same dotted field the sign-in card sits on. */
.lp-hero__grid {
    position: absolute;
    inset: 0;
    background-image: radial-gradient(circle, var(--shody-ink-600) 1px, transparent 1.2px);
    background-size: 26px 26px;
    opacity: 0.55;
    pointer-events: none;
}

/* Everything except the dotted substrate sits above it. */
.lp-hero > .lp-shell,
.lp-hero__inner { position: relative; z-index: 1; }

.lp-hero__inner {
    display: grid;
    gap: clamp(2.5rem, 5vw, 4rem);
    align-items: center;
}

@media (min-width: 60rem) {
    .lp-hero__inner { grid-template-columns: 1.05fr 0.95fr; }
}

.lp-eyebrow {
    margin: 0 0 var(--shody-gap-md);
    font-size: var(--shody-type-micro);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--shody-flow);
}

.lp-hero__title {
    margin: 0;
    max-width: 34ch;
    font-size: clamp(2.25rem, 6vw, 4rem);
    line-height: 1.05;
    letter-spacing: -0.02em;
    font-weight: 700;
    text-wrap: balance;
}

.lp-hero__lede {
    margin: var(--shody-gap-lg) 0 0;
    max-width: 58ch;
    font-size: clamp(1rem, 1.8vw, 1.2rem);
    line-height: 1.6;
    color: var(--shody-status-muted-line);
}

.lp-hero__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--shody-gap-sm);
    margin-top: var(--shody-gap-xl);
}

/* ── Chain preview: the hero's right column, and the Phase 2 film's slot ──── */

.lp-track {
    padding: var(--shody-gap-xl);
    border: 1px solid var(--shody-ink-600);
    border-radius: var(--shody-r-xl);
    background: var(--shody-ink-800);
    box-shadow: var(--shody-shadow-pop);
}

.lp-track__cap {
    margin: 0 0 var(--shody-gap-lg);
    font-size: var(--shody-type-micro);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--shody-text-faint);
}

.lp-track__list {
    position: relative;
    list-style: none;
    margin: 0;
    padding: 0 0 0 var(--shody-gap-xl);
    display: grid;
    gap: var(--shody-gap-lg);
}

/* The rail the five nodes hang off, plus a packet travelling down it. */
.lp-track__list::before {
    content: '';
    position: absolute;
    left: 5px;
    top: 0.4rem;
    bottom: 0.4rem;
    width: 2px;
    background: var(--shody-ink-600);
}

.lp-track__list::after {
    content: '';
    position: absolute;
    left: 2px;
    top: 0.4rem;
    width: 8px;
    height: 8px;
    border-radius: var(--shody-r-pill);
    background: var(--shody-flow);
    animation: lp-packet 6s var(--shody-ease-standard) infinite;
}

@keyframes lp-packet {
    0%,  4%   { top: 0.4rem; opacity: 0; }
    10%       { opacity: 1; }
    90%       { opacity: 1; }
    96%, 100% { top: calc(100% - 0.9rem); opacity: 0; }
}

.lp-track__node {
    position: relative;
    font-size: 0.95rem;
    line-height: 1.4;
    color: var(--shody-status-muted-line);
}

/* Each node's own marker, sitting on the rail. */
.lp-track__node::before {
    content: '';
    position: absolute;
    left: calc(-1 * var(--shody-gap-xl) + 2px);
    top: 0.45rem;
    width: 8px;
    height: 8px;
    border-radius: var(--shody-r-pill);
    border: 2px solid var(--shody-ink-600);
    background: var(--shody-ink-800);
}

.lp-track__node--accent {
    color: var(--shody-text-invert);
    font-weight: 600;
}
.lp-track__node--accent::before {
    border-color: var(--shody-accent);
    background: var(--shody-accent);
}

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

.lp-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: var(--shody-gap-sm) var(--shody-gap-lg);
    border: 1px solid transparent;
    border-radius: var(--shody-r-pill);
    font-size: 0.95rem;
    font-weight: 600;
    text-decoration: none;
    cursor: pointer;
    transition: background-color var(--shody-dur-2) var(--shody-ease-standard),
                border-color var(--shody-dur-2) var(--shody-ease-standard),
                transform var(--shody-dur-2) var(--shody-ease-out);
}
.lp-btn:hover { transform: translateY(-1px); }
.lp-btn:focus-visible {
    outline: 3px solid var(--shody-accent-ring);
    outline-offset: 2px;
}

/* --shody-accent-strong, not --shody-accent: white on the plain accent is
 * 4.32:1 and on --shody-accent-hover only 3.63:1, both under the 4.5:1 AA floor
 * for text this size. accent-strong is 5.67:1. Hover therefore does NOT lighten
 * the fill -- it would walk contrast back down -- and signals with elevation
 * instead, so the page's primary action never drops below AA in any state. */
.lp-btn--primary {
    background: var(--shody-accent-strong);
    color: var(--shody-accent-contrast);
}
.lp-btn--primary:hover { box-shadow: var(--shody-shadow-2); }

.lp-btn--ghost {
    background: transparent;
    border-color: var(--shody-ink-600);
    color: var(--shody-text-invert);
}
.lp-btn--ghost:hover { border-color: var(--shody-flow); }

.lp-btn--lg {
    padding: var(--shody-gap-md) var(--shody-gap-xl);
    font-size: 1.05rem;
}

/* ── Figure row: reviewed literals, never measurements ────────────────────── */

.lp-figures {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
    gap: var(--shody-gap-md);
    margin: clamp(2.5rem, 6vw, 4rem) 0 0;
}

.lp-figure {
    padding: var(--shody-gap-lg);
    border: 1px solid var(--shody-ink-600);
    border-radius: var(--shody-r-lg);
    background: var(--shody-ink-800);
}

.lp-figure__label {
    margin: 0;
    font-size: var(--shody-type-micro);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--shody-text-faint);
}

.lp-figure__value {
    margin: var(--shody-gap-xs) 0 0;
    font-size: 2.5rem;
    line-height: 1;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--shody-text-invert);
}

.lp-figure__note {
    margin: var(--shody-gap-xs) 0 0;
    font-size: var(--shody-type-meta);
    line-height: 1.45;
    /* On --shody-ink-800: status-muted is 3.49:1, text-faint is 5.60:1. The
     * lighter token is both the accessible one and the one the label uses. */
    color: var(--shody-text-faint);
}

/* ── Section headings shared by the chain and the closing call to action ──── */

.lp-main { display: block; }

.lp-section__title {
    margin: 0;
    font-size: clamp(1.6rem, 3.6vw, 2.4rem);
    line-height: 1.15;
    letter-spacing: -0.015em;
    color: var(--shody-text-strong);
    text-wrap: balance;
}

.lp-section__lede {
    margin: var(--shody-gap-md) 0 0;
    max-width: 54ch;
    font-size: 1.05rem;
    line-height: 1.6;
    color: var(--shody-text-muted);
}

/* ── The chain: five steps on a single spine ──────────────────────────────── */

.lp-chain { padding-block: clamp(3.5rem, 8vw, 6rem); }

.lp-chain__inner {
    display: grid;
    gap: clamp(2.5rem, 5vw, 4rem);
    align-items: start;
}

/* Wide viewports read as two columns: the section's premise on the left, the
 * five steps on the right. Without this the steps hug the left edge of a 68rem
 * shell and leave a third of the page empty. */
@media (min-width: 60rem) {
    .lp-chain__inner { grid-template-columns: 19rem 1fr; }
    .lp-chain__intro {
        position: sticky;
        top: clamp(2rem, 6vh, 4rem);
    }
}

.lp-scenes {
    position: relative;
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: clamp(2rem, 5vw, 3.5rem);
}

/* The spine itself, and the packet travelling down it. Both are decoration:
 * `aria-hidden` art and a pseudo-element, so neither reaches the a11y tree. */
.lp-scenes::before {
    content: '';
    position: absolute;
    left: 2.5rem;
    top: 0;
    bottom: 0;
    width: 2px;
    background: linear-gradient(180deg, transparent, var(--shody-border-strong) 8%,
                                var(--shody-border-strong) 92%, transparent);
}

.lp-scenes::after {
    content: '';
    position: absolute;
    left: calc(2.5rem - 3px);
    top: 0;
    width: 8px;
    height: 8px;
    border-radius: var(--shody-r-pill);
    background: var(--shody-flow);
    animation: lp-flow 5.5s var(--shody-ease-standard) infinite;
}

@keyframes lp-flow {
    0%   { top: 2%;  opacity: 0; }
    12%  { opacity: 1; }
    88%  { opacity: 1; }
    100% { top: 98%; opacity: 0; }
}

.lp-scene {
    position: relative;
    display: grid;
    grid-template-columns: 5rem 1fr;
    gap: var(--shody-gap-lg);
    align-items: start;
}

.lp-scene__art {
    display: grid;
    place-items: center;
    width: 5rem;
    height: 5rem;
    border: 1px solid var(--shody-border);
    border-radius: var(--shody-r-lg);
    background: var(--shody-surface-0);
    box-shadow: var(--shody-shadow-1);
    color: var(--shody-text-muted);
}

/* Step 4 is the differentiator -- the governed definition. Accent it so the eye
 * stops there rather than reading five identical rows. */
.lp-scene--accent .lp-scene__art {
    border-color: var(--shody-accent);
    background: var(--shody-accent-soft);
    color: var(--shody-accent);
}

.lp-art {
    width: 2.75rem;
    height: 2.75rem;
    fill: none;
    stroke: currentColor;
    stroke-width: 4;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.lp-scene__step {
    margin: 0;
    font-size: var(--shody-type-micro);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    /* text-faint is only 3.10:1 on a white surface; muted is 5.98:1. Small
     * uppercase text needs the AA floor more than most, not less. */
    color: var(--shody-text-muted);
}

.lp-scene__title {
    margin: var(--shody-gap-2xs) 0 0;
    font-size: clamp(1.15rem, 2.4vw, 1.5rem);
    line-height: 1.25;
    color: var(--shody-text-strong);
}

.lp-scene__text {
    margin: var(--shody-gap-sm) 0 0;
    max-width: 56ch;
    font-size: 1rem;
    line-height: 1.65;
    color: var(--shody-text-muted);
}

/* Scroll-driven reveal, as pure CSS enhancement.
 *
 * Deliberately animates TRANSFORM ONLY. The first version faded from
 * `opacity: 0` with `both` fill, which meant every step below the fold rendered
 * invisible until it was scrolled past -- and stayed invisible for anything that
 * does not scroll: a full-page screenshot, print, a reader mode, an anchor jump
 * straight to #chain. Text that a decoration can hide is a bug, not an effect.
 * A slide has no such failure mode: the worst case is copy offset by 20px. */
@supports (animation-timeline: view()) {
    @media (prefers-reduced-motion: no-preference) {
        .lp-scene {
            animation: lp-rise linear both;
            animation-timeline: view();
            animation-range: entry 5% cover 22%;
        }
        @keyframes lp-rise {
            from { transform: translateY(1.25rem); }
            to   { transform: none; }
        }
    }
}

/* ── What it runs on: the named stack ─────────────────────────────────────── */

.lp-stack {
    border-top: 1px solid var(--shody-border-faint);
    background: var(--shody-surface-1);
    padding-block: clamp(3.5rem, 8vw, 6rem);
}

.lp-stack__grid {
    list-style: none;
    margin: clamp(2rem, 5vw, 3rem) 0 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
    gap: var(--shody-gap-md);
}

.lp-stack__item {
    padding: var(--shody-gap-lg);
    border: 1px solid var(--shody-border);
    border-radius: var(--shody-r-lg);
    background: var(--shody-surface-0);
    box-shadow: var(--shody-shadow-1);
}

.lp-stack__name {
    margin: 0;
    font-size: 1.05rem;
    line-height: 1.3;
    color: var(--shody-text-strong);
}

.lp-stack__text {
    margin: var(--shody-gap-xs) 0 0;
    font-size: 0.95rem;
    line-height: 1.6;
    color: var(--shody-text-muted);
}

/* ── Closing call to action ───────────────────────────────────────────────── */

.lp-cta {
    border-top: 1px solid var(--shody-border-faint);
    background: var(--shody-surface-0);   /* alternates against .lp-stack above */
    padding-block: clamp(3rem, 7vw, 5rem);
}

.lp-cta__body {
    display: grid;
    justify-items: center;
    gap: var(--shody-gap-md);
    text-align: center;
}
.lp-cta__body .lp-section__lede { margin-inline: auto; }
.lp-cta__body .lp-btn { margin-top: var(--shody-gap-xs); }

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

.lp-foot {
    border-top: 1px solid var(--shody-border-faint);
    background: var(--shody-surface-0);
    padding-block: var(--shody-gap-xl);
}

.lp-foot__text {
    margin: 0;
    font-size: var(--shody-type-meta);
    color: var(--shody-text-muted);   /* 5.98:1; text-faint is 3.10:1 here */
}

/* ── Narrow viewports: stack the art above the copy, drop the spine ───────── */

@media (max-width: 640px) {
    .lp-scenes::before,
    .lp-scenes::after { display: none; }

    .lp-scenes { gap: var(--shody-gap-xl); }

    .lp-scene { grid-template-columns: 1fr; gap: var(--shody-gap-md); }

    .lp-scene__art { width: 3.5rem; height: 3.5rem; }
    .lp-art { width: 2rem; height: 2rem; }

    .lp-hero__actions .lp-btn { flex: 1 1 auto; }
}

/* ── The scroll-scrubbed camera flight (SDW-665 Phase 2) ──────────────────────
 *
 * The engine in static/js/scroll-world.js is vendored third-party code that injects
 * its own namespaced CSS. It is themed ONLY through these --sw-* custom properties,
 * mapped from the shody-system.css tokens.
 *
 * Why that matters: static/js/ is outside style_drift.py's SCAN_GLOBS, so a color
 * written into the engine config would sit where the ratchet cannot see it. Keeping
 * the palette here means the design system stays authoritative and the guard still
 * applies -- the engine's own built-in defaults are vendor fallbacks that our tokens
 * override before they are ever used.
 * ─────────────────────────────────────────────────────────────────────────── */

/* Set on :root AND .sw-root, not on the container.
 *
 * The engine declares its own defaults on .sw-root inside @layer sw. Layer order does
 * not help here: a custom property set DIRECTLY on an element always beats one
 * inherited from an ancestor, so theming .lp-world left the engine's dark default ink
 * in place and the copy rendered near-black on the navy footage -- unreadable. Setting
 * the same element the engine sets, from unlayered CSS, is what actually wins. */
:root,
.sw-root {
    --sw-bg: var(--shody-ink-900);
    --sw-ink: var(--shody-text-invert);
    --sw-ink-soft: var(--shody-status-muted-line);
    --sw-accent: var(--shody-accent-strong);   /* AA-safe under white text */
    --sw-font-display: var(--shody-font-sans);
    --sw-font-body: var(--shody-font-sans);
}

.lp-world {
    position: relative;
    z-index: 1;
    background: var(--shody-ink-900);
}

/* Set by landing-mount.js only after the flight has actually mounted. Until then the
 * static page is visible and the flight container is `hidden`, so a visitor is never
 * looking at nothing. */
.lp-flight-on .lp-static { display: none; }

/* A mounted flight owns the viewport, so the page must not also scroll its own bars. */
.lp-flight-on,
.lp-flight-on body { background: var(--shody-ink-900); }

/* The skip link has to keep working in both modes. */
.lp-flight-on .lp-skip { z-index: 5; }
