/* ============================================================
   LANDING PAGE  (PuNoObservation)

   Visual world: "field record" on paper. A light ground, an
   expanded grotesk for display, mono for anything that is a
   measurement, and photography carrying the drama.

   Rules this file follows, so later edits stay consistent:
     - Radius: surfaces 16px, anything interactive is a pill.
     - Theme: light, page-wide. Photographs may be dark, but no
       section inverts the page ground.
     - Accent: one green family, shared with the application shell.
       --accent for text and icons, --lime as a solid fill that
       carries light type, --lime-deep for the footer ground.
       Nothing on the page is a high-luminance neon.
     - Motion: transform and opacity only, all of it gated
       behind prefers-reduced-motion.
   ============================================================ */

.landing-page {
    /* ---- type scale ---- */
    --fs-xs: 0.75rem;
    --fs-sm: 0.875rem;
    --fs-base: 1rem;
    --fs-lg: 1.125rem;
    --fs-xl: 1.375rem;
    --fs-h3: clamp(1.25rem, 1.1rem + 0.7vw, 1.75rem);
    /* every section heading sets at the About heading's size */
    --fs-h2: clamp(1.9rem, 1.1rem + 1.7vw, 2.85rem);
    --fs-h1: clamp(2.5rem, 1.5rem + 3.9vw, 4.5rem);
    --fs-figure: clamp(2.75rem, 1.6rem + 4.8vw, 5.25rem);

    /* ---- spacing rhythm (8px) ---- */
    --sp-1: 0.5rem;
    --sp-2: 1rem;
    --sp-3: 1.5rem;
    --sp-4: 2rem;
    --sp-6: 3rem;
    --sp-8: 4rem;
    --sp-10: 5rem;
    --sp-14: 7rem;

    /* ---- colour ----
       Every value below clears 4.5:1 against the surface it sits on. */
    /* Page grounds are tints of the logo's own green (hue ~142deg, the
       #20c050 of the leaves), so the page and the mark read as one family.
       Cards and buttons stay white on top of them. */
    --paper: #ecf8ef;
    --paper-alt: #f6fcf7;
    --paper-2: #ffffff;
    --paper-3: #dcf2e2;
    --ink: #0d1c14;
    --body: #4a5a51;
    --mute: #67786e;
    --accent: #15803d;
    --accent-deep: #14532d;
    /* The brand fill used to be an electric lime (#bef264). At full-page
       scale it glared, so it is now the same forest green the application
       shell uses (--brand-600), carried with light type on top. Same
       family, a quarter of the luminance. */
    --lime: #1c7a41;
    --lime-hover: #219049;
    --lime-deep: #005a38;   /* the logo's deep emerald; footer ground */
    --on-lime: #f2f8f0;
    --leaf: #4f9d68;
    --leaf-soft: #a9d3ae;
    --bone: #eef4ec;
    --frame: #2c3a32;
    --line: #d4eadb;
    --line-soft: #e3f3e7;

    /* ---- shape ---- */
    --r: 16px;
    --r-sm: 10px;
    --pill: 999px;

    /* Shadows are tinted to the ground rather than pure black. */
    --sh-sm: 0 1px 2px rgba(19, 44, 30, 0.04), 0 2px 8px rgba(19, 44, 30, 0.04);
    --sh-md: 0 2px 4px rgba(19, 44, 30, 0.04), 0 10px 28px rgba(19, 44, 30, 0.07);
    --sh-lg: 0 4px 8px rgba(19, 44, 30, 0.05), 0 20px 48px rgba(19, 44, 30, 0.11);

    --ease: cubic-bezier(0.16, 1, 0.3, 1);

    /* Hover growth -- photographs and cards that take space under the
       pointer. --ease is an expo-out curve: it covers most of its distance
       in the first few frames, which reads as a snap however long the
       duration is. This one eases in as well as out, so a picture grows
       rather than jumps. Buttons and links keep their own quick timing:
       a control should answer immediately. */
    --grow: 900ms;
    --grow-ease: cubic-bezier(0.37, 0, 0.25, 1);
    --shell: 78rem;
}

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

.landing-page {
    margin: 0;
    background: var(--paper);
    color: var(--body);
    font-family: "Inter Tight", system-ui, -apple-system, "Segoe UI", sans-serif;
    font-size: var(--fs-base);
    line-height: 1.6;
    overflow-x: hidden;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* Archivo carries a width axis. Widening the display face is what makes
   the headings feel built rather than merely large. */
.landing-page h1,
.landing-page h2,
.landing-page h3 {
    margin: 0;
    font-family: "Archivo", "Inter Tight", system-ui, sans-serif;
    font-variation-settings: "wdth" 112;
    color: var(--ink);
    line-height: 1.02;
    letter-spacing: -0.03em;
    text-wrap: balance;
}

.landing-page h1 { font-size: var(--fs-h1); font-weight: 800; }
.landing-page h2 { font-size: var(--fs-h2); font-weight: 700; }
.landing-page h3 { font-size: var(--fs-h3); font-weight: 700; line-height: 1.15; letter-spacing: -0.02em; }
/* :where() keeps these resets at zero specificity, so a single class is
   enough to override them. Without it .landing-page p was silently
   cancelling the top margin on every paragraph that sets one. */
:where(.landing-page p) { margin: 0; }
:where(.landing-page a) { color: inherit; text-decoration: none; }
.landing-page img { display: block; max-width: 100%; height: auto; }

.landing-page :focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
    border-radius: 4px;
}

.landing-shell {
    width: 100%;
    max-width: var(--shell);
    margin-inline: auto;
    padding-inline: var(--sp-3);
}

/* Sections alternate ground so each block of the page reads as its own
   panel. --section-bg is declared here so anything sitting inside a
   section (marquee fade edges, for one) can match whichever ground it
   happens to be on. */
.landing-section {
    --section-bg: var(--paper);
    background: var(--section-bg);
    /* The plate triptych runs past the shell on purpose. Clipping here --
       on the full-width section -- cuts it at the screen edge and keeps a
       horizontal scrollbar off the page. */
    overflow-x: clip;
    padding-block: clamp(var(--sp-8), 7vw, var(--sp-14));
    scroll-margin-top: 6rem;
}
.landing-section-alt { --section-bg: var(--paper-alt); }

/* About, Coverage and Features each have their own ground, all tints of
   the logo, kept light so dark type reads on every one:
     About     mint  -- the leaves' green (and the hero's ground)
     Coverage  pale lime -- the "P"
     Features  cool sage -- the deep emerald of the trunk
   Each holds its colour for most of its height and only in its last
   stretch eases into the colour of the section after it, so the change is
   seen but there is never an edge. --section-bg is what the marquee edge
   fades blend into. */
#about,
#coverage,
#features {
    --g-about: #e3f6e8;
    --g-coverage: #eef6d6;
    --g-features: #ddeee9;
    --g-after: #e1f2dc;   /* the call-to-action section's top colour */
}

#about {
    --section-bg: var(--g-about);
    background: linear-gradient(180deg, var(--g-about) 0%, var(--g-about) 72%, var(--g-coverage) 100%);
}

#coverage {
    --section-bg: var(--g-coverage);
    background: linear-gradient(180deg, var(--g-coverage) 0%, var(--g-coverage) 72%, var(--g-features) 100%);
}

#features {
    --section-bg: var(--g-features);
    background:
        radial-gradient(circle at 10% 22%, rgba(197, 236, 211, 0.6), transparent 26%),
        radial-gradient(circle at 90% 47%, rgba(215, 243, 220, 0.7), transparent 24%),
        linear-gradient(180deg, var(--g-features) 0%, var(--g-features) 86%, var(--g-after) 100%);
}

/* The closing "See what is already on the map" section: its own ground,
   the logo's leaf green, deepening towards the bottom so it leads into
   the dark green footer. */
.landing-section-cta {
    --section-bg: #e1f2dc;
    background: linear-gradient(180deg, #e1f2dc 0%, #d4ecd2 55%, #c3e3c4 100%);
}

/* Mono is reserved for measurements and system labels, never for prose. */
.landing-tag {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    font-family: "JetBrains Mono", ui-monospace, monospace;
    font-size: 0.6875rem;
    font-weight: 500;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--accent);
}
.landing-tag svg { width: 14px; height: 14px; }

.landing-lead {
    font-size: var(--fs-lg);
    color: var(--body);
    max-width: 58ch;
}

/* ---------- Buttons ---------- */
.landing-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    white-space: nowrap;
    padding: 0.8125rem 1.5rem;
    border-radius: var(--pill);
    border: 1px solid transparent;
    font-family: inherit;
    font-size: var(--fs-sm);
    font-weight: 600;
    letter-spacing: -0.01em;
    cursor: pointer;
    transition: transform var(--grow) var(--grow-ease), background-color var(--grow) var(--grow-ease),
                border-color var(--grow) var(--grow-ease), box-shadow var(--grow) var(--grow-ease);
}
.landing-btn:active { transform: translateY(1px); }
.landing-btn svg { width: 16px; height: 16px; }

/* The primary action is the solid forest green, light type on top. It is
   the loudest thing on the page without being the brightest. */
.landing-page .landing-btn-primary {
    background: var(--lime);
    color: var(--on-lime);
    box-shadow: var(--sh-sm);
}
.landing-page .landing-btn-primary:hover { background: var(--lime-hover); box-shadow: var(--sh-md); }

.landing-page .landing-btn-ghost {
    background: var(--paper-2);
    border-color: var(--line);
    color: var(--ink);
}
.landing-page .landing-btn-ghost:hover { border-color: #c3cfba; box-shadow: var(--sh-sm); }

.landing-btn-sm { padding: 0.6875rem 1.375rem; font-size: 0.9375rem; }

.landing-page .landing-link {
    display: inline-flex;
    align-items: center;
    gap: 0.4375rem;
    font-size: var(--fs-base);
    font-weight: 600;
    color: var(--accent);
}
.landing-link svg { width: 17px; height: 17px; transition: transform var(--grow) var(--grow-ease); }
.landing-link:hover svg { transform: translateX(3px); }

/* ---------- Nav ----------
   A full-width bar pinned to the top of the window the whole way down:
   brand on the left, page links in the middle, sign-in on the right. It is
   frosted glass -- translucent white over a blur of whatever scrolls
   beneath -- so the hero photograph still reads through it at the top and
   the content does further down. */
.landing-page { --nav-h: 3.5rem; }   /* 56px at the full size */

/* Same desktop scale as the app (style.css): 80% on screens wider than a
   phone, so the landing page and the app read at the same size. */
@media (min-width: 861px) {
    html {
        font-size: 80%;
    }
}

.landing-nav-wrap {
    position: sticky;
    top: 0;
    z-index: 60;
    /* the page's mint (--paper), translucent */
    background: rgba(236, 248, 239, 0.78);
    backdrop-filter: blur(18px) saturate(1.6);
    -webkit-backdrop-filter: blur(18px) saturate(1.6);
    border-bottom: 1px solid rgba(13, 28, 20, 0.08);
    transition: background-color var(--grow) var(--grow-ease), box-shadow var(--grow) var(--grow-ease);
}

/* Off the hero, a touch more opaque and a soft shadow to lift it. */
.landing-nav-wrap.is-stuck {
    background: rgba(236, 248, 239, 0.88);
    box-shadow: 0 6px 24px -12px rgba(13, 28, 20, 0.25);
}

/* Without backdrop-filter the glass would just be thin; go solid. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .landing-nav-wrap { background: rgba(236, 248, 239, 0.97); }
}

.landing-nav {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: var(--sp-3);
    /* The full window width: brand near the left edge, sign-in near the
       right, with a gutter that grows a little on wide screens. */
    max-width: none;
    height: var(--nav-h);
    padding: 0 clamp(1.25rem, 2.5vw, 2.5rem);
}

.landing-page .landing-brand {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    justify-self: start;
    font-family: "Archivo", sans-serif;
    font-variation-settings: "wdth" 108;
    font-weight: 700;
    font-size: 1rem;
    letter-spacing: -0.02em;
    color: var(--ink);
}
.landing-brand img { width: 24px; height: 24px; object-fit: contain; }
.landing-brand .accent { color: var(--accent); }

.landing-nav-links {
    display: flex;
    align-items: center;
    gap: clamp(1.25rem, 2.6vw, 2.25rem);
    font-size: 1.0625rem;
    font-weight: 500;
    color: var(--mute);
}
.landing-nav-links a {
    position: relative;
    padding: 0.35rem 0;
    transition: color 150ms ease;
}
.landing-nav-links a:hover,
.landing-nav-links a[aria-current="page"] { color: var(--ink); }

/* The link for the section on screen is underlined; landing.js moves
   aria-current as the page scrolls. */
.landing-nav-links a::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: -2px;
    height: 2px;
    border-radius: 2px;
    background: var(--accent);
    transform: scaleX(0);
    transition: transform 220ms var(--ease);
}
.landing-nav-links a[aria-current="page"]::after { transform: scaleX(1); }
@media (prefers-reduced-motion: reduce) {
    .landing-nav-links a::after { transition: none; }
}

.landing-nav-actions {
    display: flex;
    align-items: center;
    justify-self: end;
    gap: 1rem;
}

/* The one action in the bar: an outlined button, no fill. */
.landing-page .landing-nav-login {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.45rem 1.1rem;
    border: 1.5px solid var(--accent);
    border-radius: 8px;
    background: transparent;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--accent);
    transition: background-color 150ms ease, color 150ms ease;
}
.landing-page .landing-nav-login:hover {
    background: rgba(21, 128, 61, 0.08);
    color: var(--accent-deep);
}

/* Create account beside it: solid, the same height and corners as the
   outlined Log in, so the pair reads as one set. */
.landing-page .landing-nav-cta {
    padding: 0.45rem 1.1rem;
    border: 1.5px solid transparent;
    border-radius: 8px;
    font-size: 0.8125rem;
}

/* No scrollbar line down the right edge while the page scrolls; the
   wheel, trackpad, touch and keyboard all still scroll it. */
html:has(> body.landing-page) {
    scrollbar-width: none;
}
html:has(> body.landing-page)::-webkit-scrollbar {
    display: none;
}

/* ---------- Hero ----------
   Light ground, copy on the left in dark type, and the photograph on the
   right fading into the ground towards the copy. The ground is the mint
   the About section opens with, so the two run on without a seam. */
.landing-hero {
    --hero-ground: #e3f6e8;
    position: relative;
    min-height: 100vh;
    min-height: 100dvh;
    display: flex;
    align-items: center;
    margin-top: calc(-1 * var(--nav-h));   /* the glass bar sits over the hero */
    padding-top: var(--nav-h);
    overflow: hidden;
    isolation: isolate;
    background: var(--hero-ground);
}

/* the photograph covers the right of the hero */
.landing-hero-media {
    position: absolute;
    top: var(--nav-h);
    right: 0;
    bottom: 0;
    left: 38%;
    z-index: -2;
}
.landing-hero-media img { width: 100%; height: 100%; object-fit: cover; object-position: 60% 50%; }

/* The fade: solid ground behind the copy, easing into the photograph
   across the middle. The photograph runs to the bottom edge unfaded. */
.landing-hero-scrim {
    position: absolute;
    inset: 0;
    z-index: -1;
    background:
        linear-gradient(90deg,
            var(--hero-ground) 0%,
            var(--hero-ground) 40%,
            rgba(227, 246, 232, 0.88) 50%,
            rgba(227, 246, 232, 0.35) 63%,
            rgba(227, 246, 232, 0) 76%);
}

/* The copy keeps a gutter of about a tenth of the screen from the left
   edge, rather than following the centred page column, which left a wide
   empty band on big screens. */
.landing-hero-inner {
    width: 100%;
    padding-inline: clamp(1.25rem, 10vw, 12rem);
}
.landing-hero-copy {
    max-width: 36rem;
    text-align: left;
}

/* small greeting over the headline */
.landing-hero-kicker {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    margin-bottom: var(--sp-2);
    font-size: var(--fs-sm);
    font-weight: 600;
    color: var(--accent);
}
.landing-hero-kicker svg { width: 1rem; height: 1rem; }

.landing-hero h1 {
    margin-bottom: var(--sp-3);
    font-size: clamp(2.4rem, 1.2rem + 3.4vw, 3.9rem);
    font-weight: 700;
    line-height: 1.05;
    letter-spacing: -0.03em;
    color: var(--ink);
    font-variation-settings: "wdth" 100;
}
.landing-hero h1 .accent { color: var(--accent); }

.landing-hero .landing-lead { max-width: 32rem; color: var(--body); }

.landing-hero-buttons {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin-top: var(--sp-4);
}

/* ---------- About ---------- */
/* Photographs on the left, reaching into the page gutter; the copy on
   the right as one column -- label and heading centred over it, the
   paragraphs and the credit reading left-aligned beneath. */
.landing-about {
    display: grid;
    grid-template-columns: minmax(0, 1.18fr) minmax(0, 1fr);
    gap: clamp(var(--sp-4), 4vw, var(--sp-8));
    align-items: center;
}
.landing-about h2 { margin: var(--sp-2) 0 var(--sp-3); }

/* The photographs reach into the left gutter, so the copy reaches into
   the right one by the same amount and centres itself in that space --
   otherwise a wide screen left an empty band down the right. The blocks
   share one width so the paragraphs and the credit line up on the left. */
.landing-about-copy {
    margin-right: calc(-1 * max(0px, (100vw - var(--shell)) / 2) - var(--sp-3));
    display: flex;
    flex-direction: column;
    align-items: center;
}

.landing-about-copy > * {
    width: min(100%, 38rem);
}

.landing-about-copy .landing-credit {
    max-width: none;
}

.landing-about-copy .landing-tag {
    display: flex;
    justify-content: center;
}

/* sized so the heading sets on two lines over the column */
.landing-about-copy h2 {
    text-align: center;
    font-size: clamp(1.9rem, 1.1rem + 1.7vw, 2.85rem);
    line-height: 1.1;
}

.landing-about-copy .landing-lead {
    max-width: none;
    line-height: 1.75;
    /* justified, with hyphenation so the spacing between words stays even */
    text-align: justify;
    hyphens: auto;
    -webkit-hyphens: auto;
}
.landing-about .landing-lead + .landing-lead { margin-top: var(--sp-2); }

.landing-credit {
    margin-top: var(--sp-6);
    padding-left: var(--sp-2);
    border-left: 2px solid var(--accent);
    font-size: 0.8125rem;
    line-height: 1.5;
    color: var(--mute);
    max-width: 52ch;
}


/* Three photographs at once, the middle one largest, rotating one slot
   every few seconds. The description keeps its own column beside this
   and never moves.

   Every card sits in the same place and is moved into its slot by a
   transform alone -- no card is ever re-laid-out, so the rotation is one
   smooth motion rather than three elements reflowing past each other.
   The percentages in translate are of the card's own width, which is why
   the spacing holds at every screen size. */
/* The set reaches into the left gutter, but on a wide screen it is also
   slid right by --plates-shift (same size, it just sits closer to the
   copy): the gutter minus 14rem, so it grows with the screen and is zero
   on a laptop, where the two are already close. */
.landing-plates {
    --plates-shift: max(0px, (100vw - var(--shell)) / 2 - 14rem);
    margin-left: calc(-1 * max(0px, (100vw - var(--shell)) / 2) - var(--sp-3) + var(--plates-shift));
    margin-right: calc(-1 * var(--plates-shift));
}

.landing-plate-stage {
    position: relative;
    aspect-ratio: 16 / 9;
    min-height: 19rem;
    max-height: 34rem;
}

.landing-plate {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 40%;
    margin: 0;
    aspect-ratio: 3 / 4;
    border-radius: var(--r);
    overflow: hidden;
    isolation: isolate;
    box-shadow: var(--sh-md);
    cursor: pointer;
    /* The resting state is also the waiting state: a card with no slot
       is parked off to the right at zero opacity, so it fades in as it
       reaches the right-hand slot and never appears from nowhere. */
    z-index: 0;
    opacity: 0;
    pointer-events: none;
    transform: translate(calc(-50% + 130%), -50%) scale(0.62);
    transition: transform var(--grow) var(--grow-ease), opacity var(--grow) var(--grow-ease),
                box-shadow var(--grow) var(--grow-ease);
}

.landing-plate.is-center {
    z-index: 3;
    opacity: 1;
    pointer-events: auto;
    box-shadow: var(--sh-lg);
    transform: translate(-50%, -50%) scale(1);
}
.landing-plate.is-left {
    z-index: 2;
    opacity: 0.88;
    pointer-events: auto;
    transform: translate(calc(-50% - 80%), -50%) scale(0.78);
}
.landing-plate.is-right {
    z-index: 2;
    opacity: 0.88;
    pointer-events: auto;
    transform: translate(calc(-50% + 80%), -50%) scale(0.78);
}
.landing-plate.is-center:hover {
    transform: translate(-50%, -50%) scale(1.045);
}

/* The side pictures come up to full strength under the pointer -- they are
   clickable, so they have to answer -- but they do not grow. Only the
   middle one is the subject. */
.landing-plate.is-left:hover,
.landing-plate.is-right:hover { opacity: 1; }

/* One step outside the trio on either side. Still invisible, but placed,
   so entering and leaving the set is a slide rather than a fade in
   place. */
.landing-plate.is-far-left {
    z-index: 1;
    opacity: 0;
    transform: translate(calc(-50% - 130%), -50%) scale(0.62);
}
.landing-plate.is-far-right {
    z-index: 1;
    opacity: 0;
    transform: translate(calc(-50% + 130%), -50%) scale(0.62);
}

.landing-plate img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    /* The drift below only runs on the middle card. The transition is
       what carries the zoom back down when a card leaves the middle,
       instead of letting it snap. */
    transition: transform var(--grow) var(--grow-ease);
}
/* The volunteers shot has its subject low in the frame, so it is nudged
   up rather than cropped through the middle. */
.landing-plate:first-child img { object-position: 50% 42%; }

/* A slow drift on whichever card is in the middle, so the one being
   looked at never feels frozen while it waits its turn. */
@media (prefers-reduced-motion: no-preference) {
    .landing-plate.is-center img { animation: landing-plate-drift 7s linear forwards; }
}
@keyframes landing-plate-drift {
    from { transform: scale(1.005); }
    to { transform: scale(1.07); }
}

/* On hover a skewed band of light crosses the picture once, then clears
   -- the same gesture the coverage cards and the screenshots use. */
.landing-plate::after {
    content: "";
    position: absolute;
    top: -12%;
    bottom: -12%;
    left: -70%;
    width: 58%;
    z-index: 1;
    pointer-events: none;
    opacity: 0;
    transform: skewX(-20deg) translateX(0);
    background: linear-gradient(
        90deg,
        rgba(255, 255, 255, 0) 0%,
        rgba(255, 255, 255, 0.1) 28%,
        rgba(255, 255, 255, 0.55) 46%,
        rgba(255, 255, 255, 0.16) 58%,
        rgba(255, 255, 255, 0.08) 82%,
        rgba(255, 255, 255, 0) 100%
    );
}
@media (prefers-reduced-motion: no-preference) {
    .landing-plate:hover::after { animation: landing-sheen 0.95s var(--ease); }
}
/* Shared by the plates and the coverage cards: a band of light enters
   from the left, crosses, and leaves. It is only ever driven by a hover,
   so it never runs on its own. */
@keyframes landing-sheen {
    0%   { opacity: 0; transform: skewX(-20deg) translateX(0); }
    15%  { opacity: 1; }
    85%  { opacity: 1; }
    100% { opacity: 0; transform: skewX(-20deg) translateX(340%); }
}

.landing-badge {
    grid-column: 2;
    grid-row: 1;
    align-self: start;
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    margin-left: clamp(-5rem, -20%, -1.5rem);
    padding: var(--sp-3);
    border-radius: var(--r);
    background: var(--accent);
    color: #ffffff;
    box-shadow: var(--sh-lg);
}
.landing-badge svg { width: 36px; height: 36px; flex-shrink: 0; }
.landing-badge span {
    padding-left: var(--sp-3);
    border-left: 1px solid rgba(255, 255, 255, 0.4);
    font-size: 0.8125rem;
    font-weight: 700;
    line-height: 1.4;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    white-space: nowrap;
}

/* ---------- Coverage marquee ----------
   The strip runs on its own. Hovering does not stop it, it eases the speed
   down so a photograph can be looked at without chasing it. */
.landing-carousel-head {
    margin-bottom: var(--sp-6);
    text-align: center;
}
.landing-carousel-head h2 { margin-top: var(--sp-2); }

.landing-marquee {
    position: relative;
    width: 100vw;
    margin-inline: calc(50% - 50vw);
    padding-block: 4px;
    overflow: hidden;
}

/* Soft edges, so slides enter and leave rather than being chopped off. */
.landing-marquee::before,
.landing-marquee::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    z-index: 2;
    width: clamp(24px, 7vw, 120px);
    pointer-events: none;
}
.landing-marquee::before { left: 0; background: linear-gradient(to right, var(--section-bg, var(--paper)), rgba(255, 255, 255, 0)); }
.landing-marquee::after { right: 0; background: linear-gradient(to left, var(--section-bg, var(--paper)), rgba(255, 255, 255, 0)); }

.landing-track {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    width: max-content;
    will-change: transform;
}
/* pan-y leaves vertical page scrolling alone while the strip takes over
   horizontal drags. */
.landing-marquee.is-running .landing-track { cursor: grab; touch-action: pan-y; }
.landing-marquee.is-dragging .landing-track { cursor: grabbing; }
.landing-marquee.is-dragging .landing-slide img { transform: none; }

/* Without JavaScript, or under reduced motion, the strip stays a plain
   horizontal scroller rather than an animation. */
.landing-marquee:not(.is-running) { overflow-x: auto; scrollbar-width: none; }
.landing-marquee:not(.is-running)::-webkit-scrollbar { display: none; }
@media (prefers-reduced-motion: reduce) {
    .landing-track { transform: none !important; }
}

/* A caption sitting on a photograph needs its own scrim. That is image
   treatment, not a second theme. */
.landing-slide {
    position: relative;
    flex: 0 0 min(30rem, 78vw);
    border-radius: var(--r);
    overflow: hidden;
    isolation: isolate;
    aspect-ratio: 4 / 3;
    box-shadow: var(--sh-md);
}
.landing-slide img {
    position: absolute;
    inset: 0;
    z-index: -2;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform var(--grow) var(--grow-ease);
}
.landing-slide::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background: linear-gradient(to top, rgba(6, 20, 13, 0.95) 6%, rgba(6, 20, 13, 0.5) 44%, rgba(6, 20, 13, 0.04) 100%);
    transition: opacity var(--grow) var(--grow-ease);
}

/* A sheen sweeps across the photograph on hover, the same gesture the
   hero plates and the feature screenshots use, so every image on the page
   answers a pointer the same way. */
.landing-slide::before {
    content: "";
    position: absolute;
    top: -12%;
    bottom: -12%;
    left: -70%;
    width: 58%;
    z-index: 1;
    pointer-events: none;
    opacity: 0;
    transform: skewX(-20deg) translateX(0);
    background: linear-gradient(
        90deg,
        rgba(255, 255, 255, 0) 0%,
        rgba(255, 255, 255, 0.1) 28%,
        rgba(255, 255, 255, 0.45) 46%,
        rgba(255, 255, 255, 0.14) 58%,
        rgba(255, 255, 255, 0.06) 82%,
        rgba(255, 255, 255, 0) 100%
    );
}

@media (prefers-reduced-motion: no-preference) {
    .landing-slide:hover img { transform: scale(1.06); }
    .landing-slide:hover::before { animation: landing-sheen 0.95s var(--ease); }
}
@media (prefers-reduced-motion: reduce) { .landing-slide:hover img { transform: none; } }

/* The caption sits on the photograph, so it carries its own scrim rather
   than a panel. */
.landing-slide-body {
    position: absolute;
    inset-inline: 0;
    bottom: 0;
    z-index: 2;
    padding: var(--sp-3);
}
.landing-slide-body h3 { font-size: var(--fs-xl); color: var(--bone); }

/* Only the title is on the card at rest. The description is collapsed to
   zero height rather than merely hidden, so it takes no room until the
   card is pointed at. The max-height is a ceiling for the animation, not
   a real limit -- these captions run to three lines at most. */
.landing-slide-body p {
    max-height: 0;
    margin-top: 0;
    opacity: 0;
    overflow: hidden;
    transform: translateY(8px);
    font-size: var(--fs-sm);
    color: #d3ddd5;
    max-width: 36ch;
    transition: max-height var(--grow) var(--grow-ease), opacity var(--grow) var(--grow-ease),
                transform var(--grow) var(--grow-ease), margin-top var(--grow) var(--grow-ease);
}
.landing-slide:hover .landing-slide-body p,
.landing-slide:focus-within .landing-slide-body p {
    max-height: 7rem;
    margin-top: 0.5rem;
    opacity: 1;
    transform: none;
}

/* Without a pointer there is nothing to hover, so the caption is simply
   there. Same for anyone who has asked for less motion. */
@media (hover: none) {
    .landing-slide-body p { max-height: 7rem; margin-top: 0.5rem; opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
    .landing-slide-body p { transition: none; }
}


/* The "More features" strip reuses the marquee, but carries pills rather
   than photographs. Every pill is the same height whatever its label, so
   the row reads as one band -- the height comes from the icon badge, not
   from the text, and nothing wraps. */
.landing-mini {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 0.625rem;
    height: 52px;
    padding: 0 1.25rem 0 0.625rem;
    border-radius: var(--pill);
    border: 1px solid var(--line);
    background: var(--paper-2);
    box-shadow: var(--sh-sm);
    font-size: var(--fs-base);
    font-weight: 500;
    line-height: 1;
    color: var(--ink);
    white-space: nowrap;
    user-select: none;
    transition: border-color var(--grow) var(--grow-ease),
                box-shadow var(--grow) var(--grow-ease),
                transform var(--grow) var(--grow-ease);
}
.landing-mini:hover {
    border-color: #c3cfba;
    box-shadow: var(--sh-md);
    transform: translateY(-2px);
}
.landing-mini > span {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 34px;
    width: 34px;
    height: 34px;
    border-radius: var(--pill);
    background: var(--bone);
    color: var(--accent);
}
.landing-mini svg { width: 17px; height: 17px; }

/* ---------- Features ----------
   A centred header, then four features. Each is copy on one side and its
   mockup on the other, the sides alternating, and both slide in from
   their own side as they are reached. Then the "More features" pills
   under a soft dome. */
.lf {
    position: relative;
    overflow: hidden;
    padding-block: 0;
}

.lf-kicker {
    margin: 0;
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--accent);
}

/* header */
.lf-head {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    min-height: 520px;
    justify-content: center;
    padding: 110px 24px 120px;
    text-align: center;
}
.lf-head::before {
    content: "";
    position: absolute;
    top: 40px;
    left: 50%;
    width: 680px;
    max-width: 92vw;
    height: 340px;
    border: 1px solid rgba(35, 143, 86, 0.12);
    border-radius: 50%;
    transform: translateX(-50%);
}
.lf-head h2 {
    position: relative;
    max-width: 820px;
    margin: 18px 0 22px;
    font-size: clamp(2.4rem, 1.4rem + 3vw, 4.5rem);
    font-weight: 800;
    line-height: 1.04;
    letter-spacing: -0.045em;
}
.lf-intro {
    position: relative;
    max-width: 37rem;
    margin: 0;
    color: var(--body);
    font-size: var(--fs-lg);
    line-height: 1.75;
}
.lf-note {
    position: relative;
    max-width: 37rem;
    margin: 0.9rem 0 0;
    color: var(--mute);
    font-size: var(--fs-sm);
    line-height: 1.6;
}
.lf-cue {
    position: absolute;
    bottom: 12px;
    left: 50%;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    transform: translateX(-50%);
    color: var(--mute);
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
}

.lf-timeline {
    position: relative;
    width: min(1240px, calc(100% - 48px));
    margin: 0 auto;
}

/* one feature */
.lf-row {
    position: relative;
    z-index: 1;
    display: grid;
    min-height: 690px;
    grid-template-columns: minmax(0, 0.86fr) minmax(0, 1.14fr);
    align-items: center;
    gap: 7%;
}
.lf-row.lf-reverse { grid-template-columns: minmax(0, 1.14fr) minmax(0, 0.86fr); }
.lf-row.lf-reverse .lf-copy { order: 2; justify-self: end; }
.lf-row.lf-reverse .lf-visual { order: 1; }

.lf-copy {
    position: relative;
    max-width: 500px;
}

/* the step number in a small white disc, with the label beside it */
.lf-label {
    display: flex;
    align-items: center;
    gap: 0.9rem;
}
.lf-num {
    display: grid;
    place-items: center;
    flex: none;
    width: 2.6rem;
    height: 2.6rem;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.85);
    border: 1px solid rgba(255, 255, 255, 0.9);
    box-shadow: 0 4px 14px rgba(16, 74, 50, 0.08);
    font-size: 0.8125rem;
    font-weight: 700;
    color: var(--ink);
    font-variant-numeric: tabular-nums;
}
.lf-copy h3 {
    margin: 15px 0 18px;
    font-size: clamp(1.9rem, 1.2rem + 1.5vw, 2.7rem);
    font-weight: 800;
    line-height: 1.12;
    letter-spacing: -0.04em;
}
.lf-desc {
    margin: 0;
    color: var(--body);
    font-size: var(--fs-base);
    line-height: 1.75;
}
.lf-cta { margin-top: 25px; }

/* the mockup */
.lf-visual {
    position: relative;
    min-width: 0;
}
.lf-visual::before {
    content: "";
    position: absolute;
    z-index: -1;
    inset: 12% 5%;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(69, 177, 105, 0.2), transparent 67%);
    filter: blur(20px);
}
.lf-visual .landing-shot { transition: transform 450ms cubic-bezier(.2, .7, .2, 1); }
.lf-visual:hover .landing-shot { transform: translateY(-8px); }

/* more features */
.lf-more {
    position: relative;
    padding: 125px 24px 150px;
    overflow: hidden;
    text-align: center;
}
.lf-more::before {
    content: "";
    position: absolute;
    inset: 45px -10% 0;
    border-radius: 50% 50% 0 0;
    background:
        radial-gradient(circle at center top, rgba(182, 232, 181, 0.44), transparent 55%),
        rgba(232, 248, 229, 0.4);
}
.lf-more > * { position: relative; }
.lf-more h2 {
    max-width: 700px;
    margin: 16px auto 14px;
    font-weight: 800;
    line-height: 1.08;
    letter-spacing: -0.045em;
}
.lf-more-intro {
    max-width: 600px;
    margin: 0 auto;
    color: var(--body);
    font-size: var(--fs-base);
    line-height: 1.7;
}
.lf-pills {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 12px;
    max-width: 1280px;
    margin: 48px auto 0;
    padding: 0;
    list-style: none;
}
.lf-pill {
    display: flex;
    align-items: center;
    gap: 11px;
    min-height: 58px;
    padding: 8px 17px 8px 9px;
    border: 1px solid rgba(27, 105, 70, 0.08);
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.86);
    box-shadow: 0 10px 24px rgba(32, 91, 64, 0.08);
    color: #20342b;
    font-size: 0.875rem;
    font-weight: 600;
}
.lf-pill-icon {
    display: grid;
    place-items: center;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: #edf8ee;
    color: #09814b;
}
.lf-pill-icon svg { width: 20px; height: 20px; }

@media (max-width: 900px) {
    .lf-head { min-height: 460px; padding-top: 90px; }
    .lf-timeline { width: min(680px, calc(100% - 36px)); }
    .lf-row,
    .lf-row.lf-reverse {
        min-height: auto;
        grid-template-columns: 1fr;
        gap: 38px;
        padding: 78px 0 88px;
    }
    .lf-row.lf-reverse .lf-copy,
    .lf-row.lf-reverse .lf-visual { order: initial; }
    .lf-row.lf-reverse .lf-copy { justify-self: start; }
}

@media (max-width: 560px) {
    .lf-head::before { width: 420px; }
    .lf-timeline { width: calc(100% - 24px); }
    .lf-row,
    .lf-row.lf-reverse { gap: 24px; padding: 70px 0; }
    .lf-more { padding: 100px 18px 110px; }
    .lf-pills { flex-direction: column; align-items: stretch; }
}

/* The screenshots arrive inside their own device mockups on transparent
   backgrounds, so they need no bezel. The cap stops the squarer mockups
   from towering over the copy beside them. */
.landing-shot {
    display: flex;
    justify-content: center;
}
.landing-shot img {
    width: auto;
    max-width: 100%;
    max-height: clamp(18rem, 32vw, 30rem);
}

/* Hover on a screenshot: the mockup lifts a little and a highlight sweeps
   across it. The sweep is masked with the same image so it follows the
   device silhouette instead of a rectangle -- these PNGs are transparent
   around the mockup, so a plain box would give the shape away. */
.landing-shot { position: relative; isolation: isolate; }
.landing-shot img {
    transition: transform var(--grow) var(--grow-ease);
}
.landing-glint {
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    opacity: 0;
    background: linear-gradient(
        105deg,
        rgba(255, 255, 255, 0) 38%,
        rgba(255, 255, 255, 0.55) 48%,
        rgba(255, 255, 255, 0.85) 52%,
        rgba(255, 255, 255, 0.5) 56%,
        rgba(255, 255, 255, 0) 66%
    );
    background-size: 260% 100%;
    background-position: 130% 0;
    -webkit-mask-image: var(--shot-src);
    mask-image: var(--shot-src);
    -webkit-mask-size: contain;
    mask-size: contain;
    -webkit-mask-position: center;
    mask-position: center;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
}

/* Devices mockup: a soft shadow under each device so the set looks lifted
   off the page. drop-shadow follows the PNG's shape, so each device casts
   its own shadow instead of the image casting a rectangle. */
.landing-shot.has-lift img {
    filter:
        drop-shadow(0 6px 5px rgba(16, 36, 26, 0.12))
        drop-shadow(0 18px 16px rgba(16, 36, 26, 0.14));
    transition:
        transform var(--grow) var(--grow-ease),
        filter var(--grow) var(--grow-ease);
}

@media (prefers-reduced-motion: no-preference) {
    .landing-shot.has-lift:hover img {
        filter:
            drop-shadow(0 10px 8px rgba(16, 36, 26, 0.10))
            drop-shadow(0 28px 24px rgba(16, 36, 26, 0.16));
    }
    .landing-shot:hover img { transform: translateY(-8px) scale(1.015); }
    .landing-shot:hover .landing-glint { animation: landing-glint-sweep 0.9s var(--ease); }
}
@keyframes landing-glint-sweep {
    0%   { opacity: 0; background-position: 130% 0; }
    12%  { opacity: 1; }
    88%  { opacity: 1; }
    100% { opacity: 0; background-position: -60% 0; }
}

.landing-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: clamp(var(--sp-8), 6vw, var(--sp-10));
}
.landing-chips span {
    padding: 0.4375rem 0.875rem;
    border-radius: var(--pill);
    border: 1px solid var(--line);
    background: var(--paper-2);
    font-size: 0.8125rem;
    color: var(--body);
}

.landing-note {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    margin-top: var(--sp-6);
    font-size: var(--fs-base);
    color: var(--mute);
    max-width: 64ch;
}
.landing-note svg { width: 18px; height: 18px; flex-shrink: 0; margin-top: 3px; color: var(--accent); }

/* ---------- Closing call to action ----------
   The one photographic card with light text on it. It is an image with a
   caption, which is why it does not break the light ground of the page. */
.landing-close {
    position: relative;
    border-radius: var(--r);
    overflow: hidden;
    isolation: isolate;
    padding: clamp(var(--sp-8), 9vw, var(--sp-14)) var(--sp-4);
    text-align: center;
    box-shadow: var(--sh-lg);
}
.landing-close-media { position: absolute; inset: 0; z-index: -2; }
.landing-close-media img { width: 100%; height: 100%; object-fit: cover; }
.landing-close::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background: radial-gradient(120% 92% at 50% 50%, rgba(6, 20, 13, 0.58) 0%, rgba(6, 20, 13, 0.86) 100%);
}
.landing-close h2 {
    max-width: 20ch;
    margin-inline: auto;
    color: var(--bone);
    font-variation-settings: "wdth" 118;
}
.landing-close p { margin: var(--sp-3) auto 0; max-width: 48ch; color: #d3ddd5; }
.landing-close-buttons {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    justify-content: center;
    margin-top: var(--sp-6);
}
/* Over a photograph the primary lifts one step and takes a hairline ring, so
   a mid-green pill still separates itself from mid-green foliage. */
.landing-page .landing-close .landing-btn-primary {
    background: var(--lime-hover);
    box-shadow: 0 0 0 1px rgba(242, 248, 240, 0.3), 0 8px 24px rgba(4, 14, 9, 0.45);
}
.landing-page .landing-close .landing-btn-primary:hover {
    background: #29a154;
}

/* On the photograph the ghost button needs its own surface to stay legible. */
.landing-page .landing-close .landing-btn-ghost {
    background: rgba(255, 255, 255, 0.14);
    border-color: rgba(238, 244, 236, 0.42);
    color: var(--bone);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
}
.landing-page .landing-close .landing-btn-ghost:hover {
    background: rgba(255, 255, 255, 0.24);
    border-color: rgba(238, 244, 236, 0.6);
}

/* ---------- Footer ---------- */
/* The footer carries the darkest tone of the same green the primary action
   uses, so the page closes on the brand colour. Type on it is bone, the
   same light the hero uses over the photograph. */
/* The footer carries the logo's own gradient: the deep emerald at the
   base of the trunk on the left, rising to the leaves' green on the right,
   with a soft lime glow in the corner where the "P" would be. Light type
   throughout; the column labels pick up the lime. */
.landing-footer {
    position: relative;
    background:
        radial-gradient(45% 80% at 100% 0%, rgba(144, 224, 48, 0.18), transparent 70%),
        linear-gradient(120deg, #00472d 0%, #005c38 45%, #0b7a42 100%);
    color: var(--on-lime);
    padding-block: var(--sp-8) var(--sp-4);
    font-size: var(--fs-base);
    /* rounded top corners; the footer tucks up over the section above by
       the radius, so that section's colour shows in the corners */
    border-radius: 16px 16px 0 0;
    margin-top: -16px;
    z-index: 1;
}
.landing-footer-grid {
    display: grid;
    grid-template-columns: 1.6fr repeat(3, 1fr);
    gap: var(--sp-6);
}
.landing-footer-brand {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-family: "Archivo", sans-serif;
    font-weight: 700;
    font-size: var(--fs-xl);
    color: var(--on-lime);
}
.landing-footer-brand img { width: 30px; height: auto; }
.landing-footer-brand .accent { color: #a8ec6a; }
.landing-footer .tagline {
    margin-top: 0.75rem;
    color: rgba(242, 248, 240, 0.78);
    max-width: 34ch;
}
.landing-footer h4 {
    margin: 0 0 var(--sp-2);
    font-family: "JetBrains Mono", monospace;
    font-size: 0.8125rem;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: #a8ec6a;
}
.landing-footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.75rem; }
.landing-footer li a {
    color: rgba(242, 248, 240, 0.84);
    transition: color var(--grow) var(--grow-ease);
}
.landing-footer li a:hover { color: #c6f59a; text-decoration: underline; }

/* The rule that used to sit above the academic note now separates the link
   columns from the copyright, which is all that is left down here. */
.landing-footer-bottom {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2) var(--sp-4);
    justify-content: center;
    margin-top: var(--sp-8);
    padding-top: var(--sp-4);
    border-top: 1px solid rgba(242, 248, 240, 0.18);
    color: rgba(242, 248, 240, 0.7);
    font-size: var(--fs-sm);
}
.landing-footer :focus-visible { outline-color: var(--on-lime); }

/* ---------- Scroll reveal ----------
   Driven by IntersectionObserver, never a scroll listener. The offset is
   built from three variables so one transition can serve every case:
   --reveal-x slides a photograph in from its own side of the page, and
   --reveal-sign flips the vertical direction, which is what lets an
   element that is being scrolled back up drop in from above rather than
   rise from below. */
@media (prefers-reduced-motion: no-preference) {
    .has-js .landing-reveal {
        opacity: 0;
        transform: translate3d(
            calc(var(--reveal-x, 0px) * var(--reveal-sign, 1)),
            calc(var(--reveal-y, 26px) * var(--reveal-sign, 1)),
            0
        ) scale(0.985);
        transition: opacity var(--grow) var(--grow-ease), transform var(--grow) var(--grow-ease);
        transition-delay: var(--reveal-delay, 0ms);
    }
    /* The hero copy comes up from further down and without the slight
       shrink the scrolled-in elements use -- a headline that scales as it
       arrives reads as a zoom, and this should read as floating up. */
    .has-js .landing-reveal.landing-rise {
        --reveal-y: 46px;
        transform: translate3d(0, calc(var(--reveal-y) * var(--reveal-sign, 1)), 0);
    }

    .has-js .landing-reveal.landing-from-left { --reveal-x: -52px; --reveal-y: 14px; }
    .has-js .landing-reveal.landing-from-right { --reveal-x: 52px; --reveal-y: 14px; }

    /* Set by the script once an element has left the top of the screen. */
    .has-js .landing-reveal.is-above { --reveal-sign: -1; }

    .has-js .landing-reveal.is-in {
        opacity: 1;
        transform: none;
    }
}

/* ---------- Photo viewer ----------
   Opened from the About photographs. Large, but held inside the screen
   with room around it; the page behind is blurred and dimmed. */
.landing-plate { cursor: zoom-in; }
.landing-plate:focus-visible {
    outline: 3px solid var(--accent);
    outline-offset: 3px;
}

.landing-viewer {
    /* the dialog is the whole screen; the photograph sits in its middle */
    position: fixed;
    inset: 0;
    width: 100vw;
    height: 100vh;
    height: 100dvh;
    max-width: none;
    max-height: none;
    margin: 0;
    padding: clamp(1rem, 4vw, 3rem);
    border: 0;
    background: transparent;
    color: #fff;
    display: none;
    place-items: center;
    overflow: hidden;
}
.landing-viewer[open] { display: grid; }
.landing-viewer:focus { outline: none; }

.landing-viewer::backdrop {
    background: rgba(8, 18, 12, 0.5);
    backdrop-filter: blur(10px) saturate(1.1);
    -webkit-backdrop-filter: blur(10px) saturate(1.1);
}

.landing-viewer-frame {
    margin: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.75rem;
    max-width: min(1100px, 100%);
}

.landing-viewer-frame img {
    display: block;
    max-width: 100%;
    max-height: 78vh;
    max-height: 78dvh;
    width: auto;
    height: auto;
    border-radius: 14px;
    box-shadow: 0 30px 80px -20px rgba(0, 0, 0, 0.6);
    background: #1a2a20;
}

.landing-viewer-btn {
    position: absolute;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border: 1px solid rgba(255, 255, 255, 0.25);
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.14);
    color: #fff;
    cursor: pointer;
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    transition: background-color 150ms ease;
}
.landing-viewer-btn:hover { background: rgba(255, 255, 255, 0.28); }
.landing-viewer-btn:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.landing-viewer-btn svg { width: 20px; height: 20px; }
.landing-viewer-btn.is-close { top: clamp(0.75rem, 2vw, 1.5rem); right: clamp(0.75rem, 2vw, 1.5rem); }
.landing-viewer-btn.is-prev { left: clamp(0.5rem, 2vw, 1.5rem); top: 50%; transform: translateY(-50%); }
.landing-viewer-btn.is-next { right: clamp(0.5rem, 2vw, 1.5rem); top: 50%; transform: translateY(-50%); }

@media (prefers-reduced-motion: no-preference) {
    .landing-viewer[open] .landing-viewer-frame { animation: landing-viewer-in 220ms var(--ease); }
    .landing-viewer[open]::backdrop { animation: landing-viewer-fade 220ms ease; }
}
@keyframes landing-viewer-in {
    from { opacity: 0; transform: scale(0.96); }
    to { opacity: 1; transform: none; }
}
@keyframes landing-viewer-fade {
    from { opacity: 0; }
    to { opacity: 1; }
}

/* phones: arrows sit along the bottom so they do not cover the photo */
@media (max-width: 640px) {
    .landing-viewer-btn.is-prev,
    .landing-viewer-btn.is-next { top: auto; bottom: 1rem; transform: none; }
    .landing-viewer-btn.is-prev { left: calc(50% - 56px); }
    .landing-viewer-btn.is-next { right: calc(50% - 56px); }
    .landing-viewer-frame img { max-height: 70vh; max-height: 70dvh; }
}

/* ---------- Responsive ---------- */
@media (max-width: 1080px) {
    .landing-nav-links { display: none; }
    .landing-nav { grid-template-columns: 1fr auto; }
}

@media (max-width: 900px) {
    /* The hero keeps its negative top margin, so the top padding has to
       clear the nav bar as well as give the headline room. */
    /* Narrow screens: the copy first, then the photograph as its own band
       beneath it, fading in from the ground at its top edge -- so no text
       ever sits on the busy part of the picture. */
    .landing-hero {
        min-height: auto;
        flex-direction: column;
        align-items: stretch;
        padding-block: calc(var(--nav-h) + var(--sp-6)) 0;
    }
    .landing-hero-media {
        position: relative;
        inset: auto;
        order: 2;
        height: clamp(13rem, 55vw, 22rem);
        margin-top: var(--sp-4);
        -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 28%);
        mask-image: linear-gradient(to bottom, transparent 0%, #000 28%);
    }
    .landing-hero-scrim { display: none; }
    .landing-about { grid-template-columns: minmax(0, 1fr); }
    /* Stacked above the copy there is no gutter left to reach into, so
       the frame comes back inside the shell and rounds all four corners. */
    .landing-plates { margin-left: 0; margin-right: 0; }
    .landing-about-copy { margin-right: 0; }
    .landing-plate-stage { min-height: 0; }
    .landing-footer-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Below this width the wordmark and both nav buttons stop fitting on one
   line, so the mark carries the brand and the buttons keep their room. */
@media (max-width: 560px) {
    .landing-page .landing-brand > span { display: none; }
    .landing-nav { gap: var(--sp-2); padding-inline: 1rem; }
    .landing-nav-actions { gap: 0.9rem; }
    .landing-brand img { width: 32px; height: 32px; object-fit: contain; }
}

@media (max-width: 640px) {
    .landing-hero-buttons .landing-btn { flex: 1 1 auto; }
    /* The badge cannot keep its two lines on one row at this width, so it
       moves above both plates and is allowed to wrap. */
    .landing-badge {
        grid-column: 1 / -1;
        grid-row: 1;
        margin-left: 0;
        white-space: normal;
    }
    /* Phone footer: the brand across the top, the three link groups side
       by side under it, everything a size down -- one stacked column of
       nine links ran a full screen and a half. */
    .landing-footer {
        padding-block: var(--sp-4) var(--sp-3);
        font-size: var(--fs-sm);
    }
    .landing-footer-grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: var(--sp-3) var(--sp-2);
    }
    .landing-footer-grid > :first-child { grid-column: 1 / -1; }
    .landing-footer-brand { font-size: var(--fs-lg); }
    .landing-footer-brand img { width: 24px; }
    .landing-footer .tagline { margin-top: 0.4rem; max-width: none; }
    .landing-footer h4 { margin-bottom: 0.6rem; font-size: 0.6875rem; letter-spacing: 0.1em; }
    .landing-footer ul { gap: 0.5rem; }
    .landing-footer-bottom {
        flex-direction: column;
        margin-top: var(--sp-4);
        padding-top: var(--sp-2);
        font-size: var(--fs-xs);
    }

    /* More features: on a narrow screen a 50% radius made the backdrop a
       tall pointed arch; a fixed-height ellipse keeps it a low dome. */
    .lf-more::before {
        inset: 45px -40% 0;
        border-radius: 50% 50% 0 0 / 110px 110px 0 0;
    }
}

/* Attribution for the Philippine photographs in the coverage strip. */
.landing-photo-credits {
    max-width: 62rem;
    margin: 18px auto 0;
    padding: 0 24px;
    text-align: center;
    font-size: 0.72rem;
    line-height: 1.6;
    color: var(--mute);
}
.landing-photo-credits a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.landing-photo-credits a:hover { color: var(--accent); }

/* Native species strip: scientific name above the local name. */
.landing-slide-body .landing-slide-sci {
    margin: 0 0 4px;
    font-family: Georgia, 'Times New Roman', serif;
    font-style: italic;
    font-size: 0.85rem;
    opacity: 0.85;
}
.landing-carousel-lead {
    max-width: 36rem;
    margin: 12px auto 0;
    text-align: center;
    color: var(--body);
    line-height: 1.6;
}

/* Species cards open a larger view when clicked. */
.landing-slide { cursor: zoom-in; }
.landing-marquee.is-dragging .landing-slide { cursor: grabbing; }
.landing-slide:focus-visible { outline: 3px solid var(--leaf); outline-offset: 3px; }

/* Species lightbox: the photo on the left, its details on the right. */
.landing-lightbox {
    width: min(1060px, calc(100vw - 32px));
    max-height: calc(100dvh - 32px);
    padding: 0;
    border: 0;
    border-radius: var(--r);
    background: #0b1610;
    color: var(--bone);
    overflow: hidden;
    box-shadow: var(--sh-lg);
}
.landing-lightbox::backdrop {
    background: rgba(6, 20, 13, 0.78);
    backdrop-filter: blur(6px);
}
.landing-lightbox[open] { animation: lightbox-in 0.35s var(--ease); }
@keyframes lightbox-in { from { opacity: 0; transform: scale(0.97); } }
@media (prefers-reduced-motion: reduce) { .landing-lightbox[open] { animation: none; } }
.landing-lightbox figure {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 320px;
    margin: 0;
}
.lightbox-media {
    position: relative;
    background: #050d08;
}
/* Beats the page-wide `.landing-page img { height: auto }`. */
.landing-lightbox .lightbox-img {
    display: block;
    width: 100%;
    height: min(72vh, 640px);
    object-fit: contain;
}
.landing-lightbox figcaption {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 56px 28px 24px;
}
.landing-lightbox h3 {
    font-size: var(--fs-xl);
    color: var(--bone);
}
.lightbox-ranges {
    font-size: var(--fs-base);
    line-height: 1.6;
    color: #d3ddd5;
}
.lightbox-credit {
    font-size: var(--fs-xs);
    color: #9fb3a6;
}
.lightbox-credit a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.lightbox-credit a:hover { color: var(--leaf-soft); }
.lightbox-count {
    margin-top: auto;
    font-family: "JetBrains Mono", monospace;
    font-size: var(--fs-xs);
    letter-spacing: 0.08em;
    color: #9fb3a6;
}
.lightbox-close,
.lightbox-nav {
    position: absolute;
    z-index: 2;
    display: grid;
    place-items: center;
    width: 42px;
    height: 42px;
    padding: 0;
    border: 1px solid rgba(255, 255, 255, 0.18);
    border-radius: 50%;
    background: rgba(6, 20, 13, 0.55);
    color: #fff;
    cursor: pointer;
    transition: background-color 0.2s, border-color 0.2s;
}
.lightbox-close:hover,
.lightbox-nav:hover { background: var(--lime); border-color: var(--lime); }
.lightbox-close:focus-visible,
.lightbox-nav:focus-visible { outline: 3px solid var(--leaf-soft); outline-offset: 2px; }
.lightbox-close svg,
.lightbox-nav svg {
    width: 20px;
    height: 20px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}
.lightbox-close { top: 12px; right: 12px; }
.lightbox-nav { top: 50%; transform: translateY(-50%); }
.lightbox-nav.prev { left: 12px; }
.lightbox-nav.next { right: 12px; }

/* Phones: details move under the photo. */
@media (max-width: 760px) {
    .landing-lightbox figure { grid-template-columns: 1fr; }
    .landing-lightbox .lightbox-img { height: min(52vh, 420px); }
    .landing-lightbox figcaption { padding: 18px 20px 20px; gap: 6px; }
    .lightbox-count { margin-top: 6px; }
}

/* Nav links glide to their section instead of jumping. Off for people
   who ask their system for reduced motion. */
@media (prefers-reduced-motion: no-preference) {
    html { scroll-behavior: smooth; }
}
