/* ==========================================================================
   Investment Path – public landing page and guided planner
   ========================================================================== */

.landing-page {
    min-height: 100vh;
    overflow-x: hidden;
    background: var(--bg);
}

/* Controls inherit the body stack instead of the UA's system font – but this
   has to carry NO specificity. As a plain selector it scores (0,1,1) and so
   outranks every single-class button rule in this file, which silently
   rendered .landing-secondary, .guide-back and .guide-next at 16px/400
   instead of their declared 12.5px/760 and 11.5px/760. .landing-primary is
   an <a>, never matched, and kept its own type – which is exactly why a
   deliberately matched pair rendered as two different systems.
   :where() zeroes the specificity: controls that declare nothing still
   inherit, and controls that declare their own type now win. */
:where(.landing-page button, .landing-page input) {
    font: inherit;
}

.landing-page a {
    color: inherit;
}

.landing-page [hidden] {
    display: none !important;
}

/* The page backdrop: the two corner glows, and the brand mark's trend glyph
   at wallpaper scale – the same drawing as the header logo and the favicon,
   so the background is the identity rather than decoration beside it. It
   replaced three drifting blurred blobs and a 58px grid, which read as
   generic. The .path-preview glass sits over its final rise and picks it up
   through its backdrop-filter, which is half the point.

   The geometry is generated: see scripts/generate_landing_curve.py and the
   comment in landing.html. Nothing here may be reshaped by hand. */
.landing-glow,
.landing-path {
    position: fixed;
    inset: 0;
    z-index: 0;
    pointer-events: none;
}

.landing-glow {
    background:
        radial-gradient(600px 400px at 8% -5%, var(--bg-glow-1), transparent 70%),
        radial-gradient(700px 500px at 100% 0%, var(--bg-glow-2), transparent 70%);
}

.landing-path svg {
    width: 100%;
    height: 100%;
    display: block;
}

/* A leg that falls is red and a leg that rises is green – on a line shaped
   like a chart, any other reading is actively misleading. The gradient in
   landing.html positions these; the tokens keep them on-theme, so the light
   mode's slightly heavier values apply here too. */
.landing-curve-rise { stop-color: var(--green); }
.landing-curve-fall { stop-color: var(--red); }

.landing-path-line { opacity: 0.4; }

[data-theme="light"] .landing-path-line { opacity: 0.5; }

/* A single short dash walking the line once every 13s, with a wide blurred
   copy of itself for the halo. Both ride the same gradient, so the light and
   its glow turn red through the retracement and green on the way back up.
   Only stroke-dashoffset animates; the blur and the opacities are static.

   The gap is longer than the normalised path (40 + 1000 > pathLength), so
   only one dash can ever be on the line. When the two summed to exactly
   pathLength the pattern wrapped at the end of every cycle and briefly drew
   two bars – one leaving the top while the next re-entered at the bottom.

   These three numbers come from scripts/generate_landing_curve.py, which
   sizes the dash against the line's real length. Do not retype them. */
.landing-path-spark,
.landing-path-glow {
    stroke-dasharray: 40 1000;
    animation: pathTravel 13s linear infinite;
}

.landing-path-spark {
    opacity: 0.9;
}

/* Blurred, and dimmer than the light it sits under – at matching opacity the
   halo reads as a smear rather than a glow. How strongly it shows through a
   panel is the panel's business, not this element's: widening the halo to
   push it through the glass just makes a fat light everywhere else. */
.landing-path-glow {
    opacity: 0.5;
    filter: blur(5px);
}

/* One pass at constant speed, looping. No hold and no fade: the line runs 150
   units past the frame at both ends (RUN_OFF in the generator), so the light
   has room to slide fully off screen before it reaches the end of the path
   and starts shrinking. Without that run-off it contracted to a point in the
   top-right corner in full view, which read as the stroke stopping. */
@keyframes pathTravel {
    from { stroke-dashoffset: 1040; }
    to   { stroke-dashoffset: 40; }
}

/* ==========================================================================
   Glass, so the line passes behind the copy rather than through it
   ==========================================================================

   Every block of text sits on a pane, and every panel on the landing pages is
   the same glass – .path-preview, the assumption cards and the guided-flow
   cards included. One recipe, declared once here; the files that own those
   components keep only their radius and their own decoration.

   How much of the travelling glow comes through is set here, by the fill, and
   nowhere else – widening the halo instead would make a fat light everywhere
   it is not behind a panel.

   The fill can be this thin because --surface-solid and --bg are both dark
   and close together: dropping it lets far more of the glow through while
   barely changing what the copy sits on. saturate() suits this better than
   brightness() for the same reason it is here – the glow is coloured and the
   backdrop behind it is near-neutral, so saturation lifts the glow and leaves
   the panel alone, where brightness lifted both and only washed it out.

   The panels are ::before layers rather than backgrounds on the text blocks
   themselves. A background would need padding, and padding on
   .landing-hero-copy narrows the column enough to rewrap the headline. A
   layer behind costs no layout at all. Where a block is already a padded card
   it takes the fill directly. */
.landing-hero-copy::before,
.landing-section-copy::before,
.landing-footer::before,
.landing-principles article,
.path-preview,
.assumption-stack article,
.guide-card,
.guide-recap {
    border: 1px solid var(--border);
    background:
        linear-gradient(145deg, rgba(255, 255, 255, 0.07), transparent 55%),
        color-mix(in srgb, var(--surface-solid) 46%, transparent);
    backdrop-filter: blur(22px) saturate(220%);
    -webkit-backdrop-filter: blur(22px) saturate(220%);
}

.landing-hero-copy::before,
.landing-section-copy::before,
.landing-footer::before,
.landing-principles article {
    border-radius: var(--radius);
    box-shadow: 0 24px 70px rgba(0, 0, 0, 0.20);
}

.landing-hero-copy,
.landing-section-copy,
.landing-footer {
    position: relative;
}

/* The gap between the copy and the edge of its pane comes from the block's
   own padding, so it is the same at every width and needs no breakpoint. The
   pane then reaches a little further outward – but only as far as the page's
   real side margin allows while staying 8px clear of the viewport, which is
   nothing below 1196px and 28px once the container has hit its 1180px cap.
   So the gap runs 28px on a narrow window to 56px on a wide one, and the
   pane never has its corners sliced off at the screen edge.

   Growing inward was avoided at first on the assumption that padding would
   cost the hero headline a line. Measured, it does not: `text-wrap: balance`
   on the h1 holds it at three lines with up to 40px of padding at both 1100px
   and 1440px. Check that again before raising this much further. */
.landing-hero-copy,
.landing-section-copy,
.landing-footer {
    padding-inline: 28px;
}

.landing-hero-copy::before,
.landing-section-copy::before,
.landing-footer::before {
    content: "";
    position: absolute;
    z-index: -1;
    inset-block: -30px;
    inset-inline: calc(-1 * min(28px, max(0px, (100vw - 1180px) / 2 - 8px)));
}

.landing-footer::before {
    inset-block: 0;
}

.landing-hero-copy::before,
.landing-section-copy::before {
    inset-block: -40px;
}
