/* ============================================================
   CINEMATIC INTRO — "The Garden / The False Dawn / The Sword"
   Shared by garden_w1.html and the _introtest.html harness.
   Acts:
     I   THE GARDEN   — plants part, Eve (Life) rises & glows,
                        the Serpent (Death) lurks. Serpent's-eye view.
     II  FALSE DAWN   — palette flips to blinding grey; watching
                        eyes over the hills, the grinning sun crests.
     III THE AWAKENING — Eve's cosmic face is the foreground; the
                        warrior / deliverer / Ezer / sword build.
   ============================================================ */

#introOverlay {
    position: fixed; inset: 0; z-index: 20000;
    display: flex; flex-direction: column; justify-content: center; align-items: center;
    background: #000;
    overflow: hidden;
    transition: opacity 1s ease, filter 1s ease;
}

/* Ambient dread heartbeat — a static red vignette whose OPACITY pulses.
   (Animating opacity is GPU-cheap; the earlier version animated a
   full-screen box-shadow every frame, which jams the compositor.) */
.pulse-void::before {
    content: ''; position: absolute; inset: 0; z-index: 13; pointer-events: none;
    background: radial-gradient(ellipse at center, rgba(0,0,0,0) 46%, rgba(120,0,16,0.6) 100%);
    opacity: 0.1;
    animation: dread-op 6s infinite ease-in-out;
}
@keyframes dread-op { 0%,100% { opacity: 0.05; } 50% { opacity: 0.2; } }
.pulse-void.dread::before      { animation-duration: 1.1s; opacity: 0.4; }
.pulse-void.dread-peak::before { animation-duration: 0.32s; opacity: 0.55; }

/* ===================== ACT I — THE GARDEN ===================== */
#gardenScene {
    position: absolute; inset: 0; opacity: 0; z-index: 5; overflow: hidden;
    transition: opacity 1.6s ease, filter 1.4s ease;
    background:
        radial-gradient(120% 75% at 50% 104%, rgba(40,60,32,0.65) 0%, rgba(6,8,14,0) 55%),
        linear-gradient(#05050b 0%, #090d14 48%, #16240f 84%, #070c06 100%);
}
#gardenScene.lit { opacity: 1; }
#gardenScene.creeping { animation: garden-creep 26s linear forwards; }
@keyframes garden-creep {
    0%   { transform: scale(1.02) translateY(0); }
    100% { transform: scale(1.14) translateY(-2%); }
}

/* DEPTH ORDER (back -> front):
   garden gradient (bg) < floorplants (.garden-bg, z2) < halo (z3) <
   Eve (z4) < grass (#grassFront, z6) < dragon-eye serpent (z7) <
   foreground plants (.fg-plant, z9) < vignette (z12).
   So Eve is nestled INTO the garden — leaves behind her, grass and
   parting foliage in front. */

/* Painted Eden backdrop — the far hills behind everything, dimmed to a
   twilight tone so the garden reads ominous, then lifts as Eve glows. */
#gardenBackdrop {
    position: absolute; inset: 0; width: 100%; height: 100%;
    object-fit: cover; object-position: center 40%;
    z-index: 1; pointer-events: none;
    filter: brightness(0.34) saturate(0.7) contrast(1.05) hue-rotate(-8deg);
    transition: filter 6s ease;
    /* This full-screen backdrop animates its `filter` for 6s. Promote it to its
       own layer so that per-frame repaint stays confined here instead of forcing
       the foliage/Eve/grass stacked above it to repaint too. */
    will-change: filter;
}
#gardenBackdrop.dawnlit { filter: brightness(0.5) saturate(0.85) contrast(1.05); }

/* Background foliage (floorplants) — the garden's back wall of leaves,
   deep and dim, sitting BEHIND Eve but in front of the backdrop. */
.garden-bg {
    position: absolute; bottom: -10%; height: 72%; z-index: 2; pointer-events: none;
    filter: brightness(0.3) saturate(0.6) blur(1.5px);
    opacity: 0.8;
}
.garden-bg.left  { left: -16%; }
.garden-bg.right { right: -16%; transform: scaleX(-1); }

/* Eve of Eden = Life. Keeps her black paper-cut matte (zine collage);
   grows toward us and glows as she is revealed. */
#gardenEve {
    position: absolute; bottom: 2%; left: 50%;
    height: 56%;
    transform: translateX(-50%) scale(0.8);
    transform-origin: bottom center;
    filter: brightness(0.6) contrast(1.05) saturate(0.85);
    opacity: 0.94; z-index: 4;
    transition: transform 13s ease, filter 7s ease, opacity 4s ease;
    /* Animates transform + filter (incl. a drop-shadow on .risen) for up to
       13s; keep its repaints on their own layer. */
    will-change: transform, filter;
}
#gardenEve.risen {
    transform: translateX(-50%) scale(1.18);
    filter: brightness(1.2) contrast(1.12) saturate(0.95) drop-shadow(0 0 55px rgba(195,218,255,0.8));
    opacity: 1;
}

/* Halo of life blooming behind her */
#eveHalo {
    position: absolute; bottom: 4%; left: 50%; width: 52%; height: 82%;
    transform: translateX(-50%) scale(0.5);
    background: radial-gradient(ellipse at center, rgba(215,228,255,0.5) 0%, rgba(150,190,255,0.16) 42%, rgba(0,0,0,0) 70%);
    opacity: 0; z-index: 3; pointer-events: none; mix-blend-mode: screen;
    transition: opacity 4s ease, transform 10s ease;
}
#eveHalo.on { opacity: 1; transform: translateX(-50%) scale(1.2); }

/* Grass — IN FRONT of Eve, behind the parting foreground plants. */
#grassFront {
    position: absolute; bottom: -3%; left: 50%; transform: translateX(-50%);
    width: 150%; height: 22%; object-fit: cover; object-position: center 12%;
    z-index: 6;
    filter: brightness(0.08) contrast(2.2); mix-blend-mode: multiply; opacity: 0.9;
}
#grassFront.sway { animation: grass-sway 7s ease-in-out infinite alternate; transform-origin: bottom center; }
@keyframes grass-sway {
    0%   { transform: translateX(-50%) skewX(-1.3deg); }
    100% { transform: translateX(-50%) skewX(1.5deg); }
}

/* The lurking Serpent = Death: a slit-pupil dragon eye glowing low in
   the grass (screen makes the pale eyeball glow, the slit stays dark). */
#serpentLurk {
    position: absolute; bottom: -8%; left: 50%;
    width: 30%; max-width: 380px; z-index: 7;
    transform: translateX(-50%) scale(0.9);
    opacity: 0; mix-blend-mode: screen;
    filter: brightness(0.85) contrast(1.3);
    transition: opacity 3.5s ease, bottom 7s ease;
}
#serpentLurk.rising { opacity: 0.72; bottom: 3%; }

/* Mid foreground plants (ferns / spekboom) — the layer we peer THROUGH;
   they sweep aside as Eve approaches. */
.fg-plant {
    position: absolute; bottom: -8%; z-index: 9; pointer-events: none;
    transition: transform 9s cubic-bezier(0.33,0,0.2,1), opacity 9s ease;
}
.fg-plant.ferns  { height: 74%; filter: brightness(0.5) saturate(0.85); }
.fg-plant.spek   { height: 54%; filter: brightness(0.55) saturate(0.9); }
.fg-plant.left   { left: -4%;  transform-origin: bottom left;  transform: translateX(6%) rotate(3deg); }
.fg-plant.right  { right: -4%; transform-origin: bottom right; transform: scaleX(-1) translateX(6%) rotate(3deg); }
.fg-plant.spek.left  { left: 6%; }
.fg-plant.spek.right { right: 6%; }
/* parted positions (as Eve approaches) */
.fg-plant.left.part   { transform: translateX(-64%) rotate(-14deg); }
.fg-plant.right.part  { transform: scaleX(-1) translateX(-64%) rotate(-14deg); }

/* FRONTMOST layer: olive branches raked across at ~45°, covering Eve at
   the start. This first layer PEELS AWAY as the serpent draws closer. */
.peel-branch {
    position: absolute; width: 108%; z-index: 11; pointer-events: none;
    filter: brightness(0.62) contrast(1.25) saturate(0.9) drop-shadow(0 8px 10px rgba(0,0,0,0.55));
    opacity: 0.96;
    transition: transform 6.5s cubic-bezier(0.32,0,0.2,1), opacity 6.5s ease;
}
/* Both branches drape from the top corners toward the centre at ~45°,
   overlapping over Eve so she is genuinely covered before the peel. */
.peel-branch.left  { top: -8%; left: -14%;  transform-origin: top left;
    transform: rotate(38deg); }
.peel-branch.right { top: -8%; right: -14%; transform-origin: top right;
    transform: scaleX(-1) rotate(38deg); }
.peel-branch.left.swept  { transform: rotate(12deg) translate(-54%, -42%); opacity: 0.1; }
.peel-branch.right.swept { transform: scaleX(-1) rotate(12deg) translate(-54%, -42%); opacity: 0.1; }

/* The lurking serpent flashes at the swell (jump-scare), not the sun */
#snakeFlash {
    position: absolute; top: 46%; left: 50%;
    width: 56%; max-width: 720px; z-index: 95;
    transform: translate(-50%,-50%) scale(0.75);
    opacity: 0; pointer-events: none; filter: contrast(1.4) brightness(1.1);
}
#snakeFlash.strike { animation: snake-strike 0.9s steps(3) 1 forwards; }
@keyframes snake-strike {
    0%   { opacity: 0; transform: translate(-50%,-50%) scale(0.7); }
    12%  { opacity: 1; transform: translate(-50%,-50%) scale(1.05); filter: invert(1) contrast(2); }
    30%  { opacity: 0.9; transform: translate(-48%,-52%) scale(1.0); filter: none; }
    55%  { opacity: 1; transform: translate(-52%,-49%) scale(1.1); filter: invert(1); }
    100% { opacity: 0; transform: translate(-50%,-50%) scale(1.25); }
}

/* Snake's-gaze vignette */
#serpentVignette {
    position: absolute; inset: 0; pointer-events: none; z-index: 12;
    background: radial-gradient(ellipse 82% 70% at 50% 46%, rgba(0,0,0,0) 40%, rgba(0,0,0,0.82) 100%);
    transition: opacity 1s ease;
}

/* ===================== ACT II — THE FALSE DAWN ===================== */
/* The retina-burn flash */
#heavyFlashOverlay {
    position: absolute; inset: 0; z-index: 90; pointer-events: none; opacity: 0;
}
#heavyFlashOverlay.heavy-flash { animation: crt-retina-burn 3s cubic-bezier(0.1,1,0.1,1) forwards; }
@keyframes crt-retina-burn {
    0%   { background-color: #FFFFFF; opacity: 1; }
    5%   { background-color: #FFFFFF; opacity: 0.85; }
    15%  { background-color: transparent; opacity: 0.3; }
    100% { background-color: transparent; opacity: 0; }
}

/* The blinding grey false-daylight (recreates the reference), CONSTRUCTED
   SLOWLY after the snake-flash: bg fades, hills rise, eyes open, sun
   crests the left hill, title eases out of a blur. */
#dawnScene {
    position: absolute; inset: 0; opacity: 0; z-index: 40; overflow: hidden; pointer-events: none;
    background: linear-gradient(#d2cdbe 0%, #dad6ca 44%, #c5c8bf 62%, #99a495 100%);
    transition: opacity 1.4s ease;
}
#dawnScene.on { opacity: 1; }
#dawnScene.glitch { animation: mainframe-tear 0.4s steps(2) 1; }

/* The strained, watching eyes — the BACKMOST layer, huge behind the
   hills, with feathered/blurred edges (a soft transparent vignette so
   there's no hard rectangle). They open slowly. */
#dawnEyes {
    position: absolute; top: -6%; left: 63%;
    width: 88%; max-width: 1100px;
    mix-blend-mode: multiply; z-index: 41; opacity: 0;
    transform: translateX(-50%) scale(1.06);
    filter: contrast(1.08);
    /* feather the edges into the sky */
    -webkit-mask-image: radial-gradient(ellipse 62% 60% at 50% 42%, #000 45%, transparent 82%);
            mask-image: radial-gradient(ellipse 62% 60% at 50% 42%, #000 45%, transparent 82%);
    transition: opacity 3s ease, transform 3.4s ease;
}
#dawnEyes.open { opacity: 1; transform: translateX(-50%) scale(1); }

/* Soft transparent blur-halo framing the eyes */
#dawnGlow {
    position: absolute; inset: 0; z-index: 42; pointer-events: none; opacity: 0;
    background:
        radial-gradient(ellipse 50% 46% at 20% 62%, rgba(255,214,120,0.55) 0%, rgba(255,180,80,0) 60%),
        radial-gradient(ellipse 70% 55% at 55% 40%, rgba(0,0,0,0) 42%, rgba(70,66,58,0.45) 100%);
    filter: blur(3px);
    transition: opacity 4s ease;
}
#dawnGlow.on { opacity: 1; }

/* Painted rolling hills (keyed, transparent sky) — rise into place. */
#dawnHills {
    position: absolute; left: 0; bottom: 0; width: 100%; height: 52%;
    object-fit: cover; object-position: center 60%;
    z-index: 45; pointer-events: none;
    filter: grayscale(0.45) brightness(1.0) contrast(1.03);
    transform: translateY(40%);
    transition: transform 3.2s cubic-bezier(0.2,0.7,0.3,1);
}
#dawnHills.up { transform: translateY(0); }

/* The grinning sun crests the far-LEFT hill SLOWLY, behind the hills. */
#falseSun {
    position: absolute; bottom: 33%; left: 20%;
    width: 34.8%; max-width: 435px; z-index: 44; opacity: 0;
    transform: translate(-50%, 105%) scale(0.9);
    filter: drop-shadow(0 0 60px rgba(240,200,90,0.85));
    transition: transform 5.5s cubic-bezier(0.25,0.6,0.3,1), opacity 1.4s ease;
}
#falseSun.crest { opacity: 1; transform: translate(-50%, 0%) scale(1); }

/* The title constructs slowly — letters ease together out of a blur. */
#dawnText {
    position: absolute; top: 27%; left: 50%; transform: translateX(-50%); z-index: 46;
    font-family: Georgia, 'Times New Roman', serif; font-size: 40px; letter-spacing: 16px;
    color: #f9f6ee; text-align: center; line-height: 1.1;
    text-shadow: 0 3px 22px rgba(0,0,0,0.6), 0 0 3px rgba(0,0,0,0.4);
    opacity: 0; filter: blur(7px);
    transition: opacity 2.4s ease, letter-spacing 2.8s ease, filter 2.4s ease;
}
#dawnText.on { opacity: 1; letter-spacing: 3px; filter: blur(0); }

@keyframes mainframe-tear {
    0%   { transform: translate(0,0); filter: invert(0); }
    20%  { transform: translate(-6px,5px); filter: invert(1) hue-rotate(90deg); }
    40%  { transform: translate(6px,-3px); filter: invert(0); }
    60%  { transform: translate(-3px,2px); filter: grayscale(1) contrast(2); }
    100% { transform: translate(0,0); filter: none; }
}

/* ===================== ACT III — THE AWAKENING ===================== */
/* The warrior (She-Ra) is layered FURTHEST BACK and arrives late. Sized
   and raised so she clears the lower narration + button band. */
#sheraAwaken {
    position: absolute; bottom: 22%; left: 50%;
    width: 44%; max-width: 560px;
    transform: translateX(-50%) translateY(12%) scale(0.86);
    opacity: 0; z-index: 60; pointer-events: none;
    filter: drop-shadow(0 0 34px rgba(150,180,255,0.5));
    transition: opacity 4s ease, transform 5s ease;
}
#sheraAwaken.rise { opacity: 0.8; transform: translateX(-50%) translateY(0) scale(1); }
/* She recedes so the Sword can stand alone at the final beat */
#sheraAwaken.rise.fade { opacity: 0; transform: translateX(-50%) translateY(-6%) scale(1.04); transition: opacity 3.5s ease, transform 4s ease; }

/* The Sword of Protection — rises through her, still BEHIND the face. */
#theSword {
    position: absolute; bottom: 24%; left: 50%;
    height: 62%;
    transform: translateX(-50%) translateY(28%) scale(0.9) rotate(0.5deg);
    opacity: 0; z-index: 62; pointer-events: none;
    filter: drop-shadow(0 0 30px rgba(180,220,255,0.85)) drop-shadow(0 0 60px rgba(120,160,255,0.5));
    transition: opacity 2.5s ease, transform 3.5s cubic-bezier(0.2,0.7,0.3,1);
}
#theSword.drawn { opacity: 0.95; transform: translateX(-50%) translateY(0%) scale(1) rotate(0.5deg); }

/* Eve's cosmic face is the transparent FOREGROUND, on top of everything. */
#introEve {
    position: absolute; inset: 0; width: 100%; height: 100%;
    object-fit: cover; object-position: center 28%;
    opacity: 0; mix-blend-mode: screen; z-index: 70; pointer-events: none;
    filter: contrast(1.05) drop-shadow(0 0 50px rgba(80,120,255,0.35));
    transition: opacity 2.5s ease, filter 4s ease;
}
#introEve.bloom { opacity: 1; }
#introEve.charged { filter: contrast(1.15) saturate(1.3) drop-shadow(0 0 80px rgba(120,160,255,0.6)); }

/* ===================== SHARED — narration + buttons ===================== */
#introText {
    position: absolute; bottom: 14%; left: 50%; transform: translateX(-50%); z-index: 80;
    color: #f5f5f5; font-family: 'Courier New', Courier, monospace; font-size: 26px;
    text-align: center; max-width: 82%;
    /* legible over the busy cosmic face without a hard box */
    text-shadow: 0 0 14px #000, 0 0 24px #000, 2px 2px 6px #000;
    min-height: 34px; opacity: 1;
}
#introText::after {
    content: '_'; margin-left: 4px; color: #f5f5f5;
    animation: caret-blink 0.9s step-end infinite;
}
#introText.empty::after { content: ''; }
@keyframes caret-blink { 50% { opacity: 0; } }

.initiate-btn {
    position: relative; z-index: 82;
    background: transparent; color: var(--stark-white);
    border: 1px dashed var(--stark-white);
    padding: 12px 24px; font-family: 'Courier New', Courier, monospace; font-size: 16px;
    cursor: pointer; animation: blink 2s infinite;
}
.initiate-btn:hover { background: var(--stark-white); color: #000; }

.forge-btn {
    position: absolute; bottom: 4%; left: 50%; transform: translateX(-50%);
    z-index: 82; margin-top: 30px;
    background: transparent; color: var(--neon-pink);
    border: 2px solid var(--neon-pink);
    padding: 15px 30px; font-family: 'Courier New', Courier, monospace; font-size: 20px;
    font-weight: bold; cursor: pointer; display: none; opacity: 0;
    transition: opacity 2s ease, background 0.3s; box-shadow: 0 0 15px var(--neon-pink);
}
.forge-btn.visible { display: block; opacity: 1; pointer-events: auto; animation: pulse 2s infinite; }
.forge-btn:hover { background: var(--neon-pink); color: #000; }
.flicker-prompt { animation: terminal-flicker 0.1s infinite; }
@keyframes terminal-flicker { 0%{opacity:1} 50%{opacity:0.85} 100%{opacity:1} }
@keyframes pulse {
    0%   { box-shadow: 0 0 10px var(--neon-pink); }
    50%  { box-shadow: 0 0 30px var(--neon-pink); }
    100% { box-shadow: 0 0 10px var(--neon-pink); }
}
@keyframes blink { 50% { opacity: 0; } }

.skip-btn {
    position: absolute; bottom: 20px; right: 25px; z-index: 82;
    background: transparent; color: #555; border: none;
    font-family: 'Courier New', Courier, monospace; font-size: 12px;
    cursor: pointer; padding: 8px; display: none; transition: color 0.3s;
}
.skip-btn.visible { display: block; }
.skip-btn:hover { color: var(--stark-white); text-decoration: underline; }

/* The exit shatter */
.shatter-effect { animation: shatter 0.5s forwards; }
@keyframes shatter {
    0%   { filter: contrast(1) brightness(1); transform: scale(1); }
    20%  { filter: contrast(3) brightness(2) invert(1); transform: scale(1.05) skew(10deg); }
    40%  { filter: contrast(3) brightness(2); transform: scale(0.95) skew(-10deg); opacity: 0.8; }
    60%  { filter: contrast(5) brightness(3); transform: scale(1.1); opacity: 0.4; }
    100% { filter: contrast(1) brightness(0); opacity: 0; transform: scale(1); }
}

/* ============================================================
   REDUCED MOTION — honor prefers-reduced-motion. The story still
   plays (the JS timeline fires every beat), but continuous motion,
   parallax zooms, strobes, and full-screen luminance flashes are
   removed. The two that matter most here: the retina-burn white flash
   and the inverting snake jump-scare are exactly the rapid luminance
   flips this setting exists to suppress.
   The slow directional eases (Eve rising, the sun cresting, the hills,
   the sword) are LEFT intact on purpose — they're gentle 3–13s fades,
   not a health trigger, and rewriting their transforms would risk
   mispositioning the layered scene.
   NOTE: this only touches the reduced-motion path. To also soften the
   DEFAULT flash for everyone, tone down #heavyFlashOverlay.heavy-flash
   and #snakeFlash.strike above — they are deliberately left at full
   intensity for the standard experience.
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
    /* Looping / ambient motion: stop it. */
    #gardenScene.creeping,
    #grassFront.sway,
    .pulse-void::before,
    .forge-btn.visible,
    .flicker-prompt,
    .initiate-btn,
    #introText::after,
    #fieldManualBtn { animation: none !important; }

    /* The jump-scare is removed; the dawn still arrives by fade. */
    #snakeFlash.strike { animation: none !important; opacity: 0 !important; }

    /* Retina-burn white flash -> a brief, soft dark veil: same "blackout
       before the false dawn" beat, no white strobe. */
    #heavyFlashOverlay.heavy-flash { animation: rm-veil 1.6s ease forwards !important; }

    /* Glitch tear and exit shatter -> plain fades, no invert/strobe. */
    #dawnScene.glitch { animation: none !important; }
    .shatter-effect  { animation: rm-fade 0.5s ease forwards !important; }
}
@keyframes rm-veil { 0% { background-color: rgba(18,18,22,0.55); opacity: 1; } 100% { background-color: rgba(18,18,22,0); opacity: 0; } }
@keyframes rm-fade { to { opacity: 0; } }
