/* ===========================================================================
   Venturis intro curtain
   ---------------------------------------------------------------------------
   Shown on first arrival at the domain only. Two black panels meet on a
   hairline, the opening sentence is typeset across that line, then the panels
   part and the landing page is underneath.

   Two house rules shape this file:

     • Every class is namespaced `vintro-` and every custom property `--vin-`,
       because landing.css already owns --ink, --paper and --rule on :root.
     • No font is imported here. The sentence takes whatever --font-display
       resolves to, which inside body.landing is the page's title face — so
       the curtain always opens onto a landing page set in the same voice it
       just spoke in. The river label is IBM Plex Sans Italic, requested once
       in the head of index.html because typography.css carries no italic.

   The markup is inert until the inline script in index.html adds
   `.vintro-armed` to <html>. A visitor with JavaScript off — or a returning
   visitor inside the same session — therefore never sees a black rectangle
   that nothing is going to open.
   =========================================================================== */

:root {
    --vin-ink: #06070A;
    --vin-sheet: #E3E7E3;

    /* Sequence timing. Every knob is here; js/intro.js owns only the beats
       between words. */
    --vin-t-fade: 220ms;   /* words leave      */
    --vin-t-open: 800ms;   /* panels part      */
}

/* The gate. Nothing in the curtain exists until JS arms it. */
.vintro { display: none; }
html.vintro-armed .vintro { display: block; }

/* There is deliberately no `overflow: hidden` scroll lock here. Taking the
   scrollbar away for the length of the sequence would widen the viewport by
   its own width, and .landing-nav is fixed to that viewport — so handing
   scrolling back mid-reveal would jog the whole page and the nav sideways at
   the exact moment the curtain is opening onto it.

   Scrolling is held off in js/intro.js instead, by treating any scroll intent
   as a request to skip: the curtain opens rather than resisting. */

/* Smooth scrolling is on globally; the scrollTo(0,0) that pins the page to the
   top under the curtain must be instant, not a visible glide once it lifts. */
html.vintro-armed { scroll-behavior: auto; }


/* ─────────────────────────────────────────
   THE CURTAIN
   Two black panels meeting on a hairline,
   drawn on the edge of the upper one.
   ───────────────────────────────────────── */
.vintro-panel {
    position: fixed;
    left: 0;
    right: 0;
    background: var(--vin-ink);
    z-index: 100000;
    transition: transform var(--vin-t-open) cubic-bezier(.76, 0, .18, 1);
    will-change: transform;
}

/* The top panel sits one step higher than the bottom one. Both meet on the
   same pixel, so at equal z-index the bottom panel — later in the document —
   would paint straight over the hairline below, and the seam the sentence is
   typeset around would never be visible. */
.vintro-panel--top { top: 0; height: calc(50% + 1px); z-index: 100001; }
.vintro-panel--bottom { top: 50%; bottom: 0; }

/* The seam lives on the panel edges, so it travels with them. It runs nearly
   the full width and only softens at the very ends. */
.vintro-panel--top::after,
.vintro-panel--bottom::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    height: 1px;
    background: linear-gradient(90deg,
        transparent 0%,
        rgba(227, 231, 227, .30) 5%,
        rgba(227, 231, 227, .36) 50%,
        rgba(227, 231, 227, .30) 95%,
        transparent 100%);
}

.vintro-panel--top::after { bottom: 0; }

.vintro-panel--bottom::before {
    top: 0;
    opacity: 0;
    transition: opacity 300ms linear;
}

html.vintro-opening .vintro-panel--bottom::before { opacity: 1; }
html.vintro-opening .vintro-panel--top { transform: translateY(-100%); }
html.vintro-opening .vintro-panel--bottom { transform: translateY(100%); }

/* The centre of the line, invisible until it flares just before opening. */
.vintro-node {
    position: fixed;
    top: 50%;
    left: 50%;
    width: 5px;
    height: 1px;
    margin: -1px 0 0 -2.5px;
    background: var(--vin-sheet);
    opacity: 0;
    z-index: 100003;
}

.vintro-node.is-firing { animation: vintro-fire 280ms cubic-bezier(.3, 0, .1, 1) forwards; }

@keyframes vintro-fire {
    0%   { opacity: 0;  width: 5px;  margin-left: -2.5px; box-shadow: 0 0 0 0 rgba(227, 231, 227, 0); }
    45%  { opacity: .9; width: 34px; margin-left: -17px;  box-shadow: 0 0 22px 3px rgba(227, 231, 227, .34); }
    100% { opacity: 0;  width: 5px;  margin-left: -2.5px; box-shadow: 0 0 0 0 rgba(227, 231, 227, 0); }
}


/* ─────────────────────────────────────────
   THE WORDS
   ───────────────────────────────────────── */
/* The sentence straddles the line: three typeset lines above it, two below,
   sharing one left edge so it still reads as one continuous sentence. */
.vintro-stage {
    position: fixed;
    inset: 0;
    z-index: 100002;
    pointer-events: none;
    font-family: var(--font-display);
    font-weight: 400;
    font-size: clamp(1.2rem, min(3.6vw, 4.75vh), 2.85rem);
    transition: opacity var(--vin-t-fade) ease;
}

.vintro-stage.is-gone { opacity: 0; }

.vintro-half {
    position: absolute;
    left: 0;
    right: 0;
    height: 50%;
    display: grid;
    justify-items: center;
    padding-left: 6vw;
    padding-right: 6vw;
}

.vintro-half--up   { top: 0;   align-items: end;   padding-bottom: 1.3em; }
.vintro-half--down { top: 50%; align-items: start; padding-top: 1.3em; }

.vintro-script {
    font-size: inherit;
    line-height: 1.3;
    letter-spacing: -.005em;
    text-align: left;
    color: var(--vin-sheet);
}

.vintro-script .vintro-row { display: block; white-space: nowrap; }

/* An invisible row carrying the longest line, so both halves size identically
   and their left edges line up once centred. */
.vintro-script .vintro-gauge { height: 0; overflow: hidden; }

.vintro-script w {
    display: inline-block;
    opacity: 0;
    transform: scale(1.07);
    transform-origin: 50% 62%;
    transition: opacity 90ms linear, transform 90ms linear;
}

.vintro-script w + w { margin-left: .28em; }

.vintro-script w.on {
    opacity: 1;
    transform: scale(1);
    transition: opacity 80ms linear, transform 300ms cubic-bezier(.14, .86, .26, 1);
}


/* ─────────────────────────────────────────
   THE RIVER
   ───────────────────────────────────────── */
/* The Thames along the bottom edge, drawn as an engraved outline. It lives
   inside the lower panel, so it sweeps away with it on open. */
.vintro-thames {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: clamp(92px, 24vh, 210px);
    pointer-events: none;
}

.vintro-thames svg { display: block; width: 100%; height: 100%; }

/* Map convention: rivers are named in italic, set along the reach — a drawn
   italic, not an algorithmic slant, which is why this is the one place the
   curtain reaches past the site's own faces. */
.vintro-thames-name {
    position: absolute;
    left: 27.5%;
    top: 25%;
    font-family: 'IBM Plex Sans', var(--font);
    font-style: italic;
    font-weight: 400;
    font-size: clamp(.68rem, .95vw, .84rem);
    letter-spacing: .26em;
    color: rgba(227, 231, 227, .22);
    transform: rotate(-4deg);
    transform-origin: 0 50%;
    white-space: nowrap;
}

@media (max-width: 1000px) {
    .vintro-thames-name { display: none; }
}


/* ─────────────────────────────────────────
   THE HANDOVER
   ───────────────────────────────────────── */
/* The landing page is already sitting underneath at full opacity, so instead
   of fading the page in we fade a page-coloured veil out from behind the
   parting panels. Same cross-fade, without wrapping the real markup in
   anything. */
.vintro-veil {
    position: fixed;
    inset: 0;
    background: var(--bg-primary, #fafaf9);
    z-index: 99999;
    pointer-events: none;
    opacity: 1;
    transition: opacity 500ms ease 350ms;
}

html.vintro-opening .vintro-veil { opacity: 0; }


@media (prefers-reduced-motion: reduce) {
    .vintro-panel,
    .vintro-node,
    .vintro-stage,
    .vintro-script w,
    .vintro-veil {
        transition-duration: 1ms !important;
        animation: none !important;
    }
}
