/* ==========================================================================
   Garden of Eden — HERO ONLY
   Tokens copied from projects/garden-of-eden/design-system.md, which itself
   derives every value from the 18 real files audited in
   assets/garden-of-eden/ASSET_MANIFEST.md and the measured findings in
   knowledge/. No invented palette or spacing here.
   ========================================================================== */

:root {
  /* COLOR SYSTEM — measured (see design-system.md §COLOR SYSTEM) */
  --ground:             #14170A;
  --ground-raised:      #202007;
  --moss-1:             #2A2A10;
  --accent-gold:        #C2A959;
  --accent-gold-bright: #D6BA8F;
  --accent-coral:       #D24F2B;
  --text:               #E8DFCC;
  --text-strong:        #FFFFFF;

  /* SPACING — knowledge/design-systems/spacing-radius-elevation.md, unmodified */
  --sp-2: .5rem;  --sp-4: 1rem; --sp-6: 1.5rem; --sp-8: 2rem;

  /* MOTION — knowledge/design-systems/motion-tokens.md, unmodified */
  --dur-base:     300ms;
  --dur-slower:   700ms;
  --dur-entrance: 900ms;
  --ease-out:     cubic-bezier(.16, 1, .3, 1);
  --ease-in-out:  cubic-bezier(.65, 0, .35, 1);

  /* Local z-index scale for this hero's layer stack (depth order, not
     the site-wide scale in design-system.md §OVERLAY SYSTEM — this hero
     has no nav/frame/modal yet, so only the six required layers + scrim
     are named here). */
  --z-background:  1;
  --z-midground:   2;
  --z-atmosphere:  3;
  --z-product:     4;
  --z-foreground:  5;
  --z-scrim:       6;
  --z-type:        7;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  background: var(--ground);
  color: var(--text);
  font-family: 'Cormorant Garamond', 'EB Garamond', Georgia, 'Times New Roman', serif;
}

/* ==========================================================================
   Hero shell
   ========================================================================== */

.hero {
  position: relative;
  isolation: isolate;
  overflow: clip;
  min-block-size: 100vh; /* fallback first — svh must win where supported */
  min-block-size: 100svh;
  background: var(--ground);
}

.layer {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  pointer-events: none; /* every decorative layer — see design-system.md §OVERLAY SYSTEM */
}

/* --------------------------------------------------------------------------
   Hero environment — the single coordinated composition (background,
   midground, atmosphere, foreground). It is laid out LARGER than the hero
   on every side, so every layer inside is edge-to-edge-and-beyond by
   construction rather than by transform arithmetic. The camera pull-back
   then scales this one container; even at its most retracted the artwork
   still overhangs the viewport, so no motion here can expose the page
   behind it. The overscan is viewport-relative with an absolute floor, so
   it holds from a short laptop window to a 1920 desktop.
   -------------------------------------------------------------------------- */

.hero__environment {
  /* Overscan must exceed the curtain travel below, so a leaf layer
     translated inward at the start still overhangs its viewport edge. */
  --ovs-x: max(90px, 9vw);
  --ovs-y: max(90px, 9vh);
  /* How far each edge's foliage reaches inward before it is pulled away. */
  --curtain-x: max(64px, 6.5vw);
  --curtain-y: max(64px, 6.5vh);
  position: absolute;
  inset: calc(0px - var(--ovs-y)) calc(0px - var(--ovs-x));
  z-index: var(--z-background);
  pointer-events: none;
  /* the environment itself never moves — LAYER 1 is stable, only the
     curtain retreats; opacity is the load-reveal, see .hero-loading */
  transition: opacity .24s ease-out;
}

/* Load gate: hold the composition until every hero plate has decoded, so
   the user never sees plates popping in one at a time. Removed by
   hero.js (and by an inline failsafe timer in <head>). */
html.hero-loading .hero__environment { opacity: 0; }

/* ==========================================================================
   1. Background — hero_bg_eden_01.png (1672×941, measured)
   The LCP element. Never lazy-loaded (see index.html <link rel=preload>).
   ========================================================================== */

/* Optimized-media pass: full-bleed layers now deliver AVIF/WebP through
   <picture>. display:contents makes the wrapper layout-invisible, so the
   existing img rules (and hero.js's '.layer--background img' selectors)
   behave exactly as they did when the img was a direct child. */
.layer--background picture,
.layer--midground picture { display: contents; }

.layer--background { z-index: var(--z-background); }
.layer--background img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  object-position: 50% 40%;
  transform-origin: 50% 45%;
  will-change: transform;
}

/* Entrance shade — replaces the old animated brightness() filter on the
   background image. A solid overlay whose opacity GSAP animates is pure
   compositor work; animating filter repainted the full-viewport texture
   every frame (the jank the KB's parallax recipe warns about). */
.hero__entrance-shade {
  z-index: var(--z-background);
  background: var(--ground);
  opacity: 0; /* raised by hero.js only when motion is allowed */
}

/* ==========================================================================
   2. Midground — hero_product_environment_01.png (1536×1024, measured)
   A second, deeper plate of the same garden — not a costume shot, it
   contains no figure. Used as a soft-masked "further in" reveal so two
   non-matching photographs read as depth rather than a jump cut.
   ========================================================================== */

.layer--midground { z-index: var(--z-midground); }
.layer--midground img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  object-position: 50% 55%;
  transform-origin: 50% 55%;
  will-change: transform, opacity;
  -webkit-mask-image: radial-gradient(ellipse 58% 55% at 50% 48%, #000 55%, transparent 100%);
          mask-image: radial-gradient(ellipse 58% 55% at 50% 48%, #000 55%, transparent 100%);
}

/* ==========================================================================
   3. Atmosphere — story_video_eden_environment_01.mp4 (1366×768, measured)
   plus a CSS haze glow (no atmosphere asset — grain/particle/caustic
   overlays are not delivered; see design-system.md §OVERLAY SYSTEM).
   ========================================================================== */

.layer--atmosphere { z-index: var(--z-atmosphere); }

.atmosphere__video {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  object-position: 50% 45%;
  mix-blend-mode: screen; /* video has no alpha — see design-system.md §VIDEO TREATMENT */
  will-change: opacity;
}

.atmosphere__haze {
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse at 50% 28%,
              rgb(214 186 143 / .16) 0%,
              rgb(214 186 143 / .05) 45%,
              transparent 70%);
  mix-blend-mode: screen;
}

/* ==========================================================================
   4. Product — required layer, no asset exists (products/ is empty;
   hero_product_environment_01.png contains no figure). Deliberately
   empty. Sized so a real costume cutout can drop in later without any
   other layer needing to change.
   ========================================================================== */

.layer--product {
  z-index: var(--z-product);
  display: grid;
  place-items: end center;
}

/* ==========================================================================
   5. Foreground — four real cutouts, framing/parting the scene.
   Each keeps its own delivered aspect ratio; none are stretched to a
   canvas they weren't built for (see design-system.md §IMAGE TREATMENT
   re: the left/right layers' portrait-vs-landscape mismatch).
   ========================================================================== */

.layer--foreground { z-index: var(--z-foreground); }

.fg { position: absolute; display: block; }

/* Each edge group pivots on its OWN outer edge, so growth reaches inward
   and retreat pulls back toward that edge — the anchored edge itself
   never leaves the viewport. */
.fg--top    { transform-origin: 50% 0%; }
.fg--left   { transform-origin: 0% 50%; }
.fg--right  { transform-origin: 100% 50%; }
.fg--bottom { transform-origin: 50% 100%; }

/* The .fg--* classes now sit on <picture> (a real box — hero.js animates
   these elements, so display:contents is not an option here). The inner
   img fills the picture's box; object-position comes from the variant. */
.fg img {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  object-position: inherit;
}

.fg--top {
  /* hero_fg_vines_top_01.png — 1672×941, matches the background's own
     canvas almost exactly, so it can behave like a second full-bleed
     layer aligned to the top edge. Capped short of its full height so
     the longest hanging tendrils don't reach into the typography band. */
  top: 0; left: 0;
  inline-size: 100%;
  block-size: auto;
  min-block-size: 34%;
  object-fit: cover;
  object-position: top;
  will-change: transform;
}

.fg--left {
  /* hero_fg_leaves_left_01.png — 1024×1536 portrait. Used as a vertical
     edge-hanging element, not a full-canvas overlay (it wasn't built at
     the background's canvas size — see design-system.md). Its inner edge
     is feathered: the raw asset is rectangular, and an unmasked edge
     reads as a vertical seam splitting the hero into two photographs. */
  left: 0; top: 0;
  block-size: 100%;
  inline-size: auto;
  max-inline-size: 42%;
  object-fit: cover;
  object-position: left top;
  will-change: transform;
  -webkit-mask-image: linear-gradient(to right, #000 55%, transparent 96%);
          mask-image: linear-gradient(to right, #000 55%, transparent 96%);
}

.fg--right {
  /* hero_fg_leaves_right_01.png — 1024×1536 portrait, mirrored edge
     position. Confirmed visually distinct from the left file, not a
     duplicate — see ASSET_MANIFEST.md §6.5. Inner edge feathered for the
     same seam reason as .fg--left. */
  right: 0; top: 0;
  block-size: 100%;
  inline-size: auto;
  max-inline-size: 42%;
  object-fit: cover;
  object-position: right top;
  will-change: transform;
  -webkit-mask-image: linear-gradient(to left, #000 55%, transparent 96%);
          mask-image: linear-gradient(to left, #000 55%, transparent 96%);
}

.fg--bottom {
  /* hero_fg_leaves_bottom_01.png — 2048×768. Known matte/fringing defect
     at its edges (see ASSET_MANIFEST.md §6.4) — used as delivered, not
     regenerated; the defect is out of scope for this implementation. */
  bottom: 0; left: 50%;
  translate: -50% 0; /* separate property — leaves `transform` to the curtain animation */
  inline-size: 112%;
  block-size: auto;
  min-block-size: 34%;
  object-fit: cover;
  object-position: bottom;
  will-change: transform;
}

/* ==========================================================================
   Scrim — CSS only, per knowledge/patterns/gradient-scrim-legibility.md.
   Three stops, bottom-weighted, tinted to --ground rather than pure black.
   ========================================================================== */

.layer--scrim {
  z-index: var(--z-scrim);
  background: linear-gradient(to top,
              rgb(20 23 10 / .82) 0%,
              rgb(20 23 10 / .30) 42%,
              rgb(20 23 10 / 0)   72%);
}

/* ==========================================================================
   6. Typography — live text. No wordmark asset exists in brand/, so this
   is real content, not an image standing in for one. Structure follows
   knowledge/components/hero-title-lockup.md exactly: eyebrow → display →
   context → one CTA.
   ========================================================================== */

.layer--type {
  z-index: var(--z-type);
  pointer-events: none;
  display: grid;
  place-items: center;
  padding-inline: var(--sp-6);
}

.lockup {
  pointer-events: auto;
  display: grid;
  justify-items: center;
  gap: clamp(.75rem, 2vw, 1.25rem);
  text-align: center;
  /* Wide enough to actually contain the display line — a tight measure
     (26ch) is narrower than the title, and the browser left-aligns the
     overflow, which reads as the whole lockup sitting right of centre. */
  max-inline-size: min(92vw, 46rem);
  margin-block-start: 0; /* sit dead-centre in the hero (both axes) */
}

.lockup__eyebrow {
  margin: 0;
  font-family: system-ui, -apple-system, 'Segoe UI', sans-serif;
  font-size: .8125rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: .3em;
  color: var(--accent-gold-bright);
  text-shadow: 0 1px 12px rgb(20 23 10 / .9); /* insurance on top of the scrim */
}

.lockup__display {
  margin: 0;
  font-weight: 300;
  font-style: normal;
  line-height: .95;
  letter-spacing: -.01em;
  font-size: clamp(2.75rem, 9vw, 6.5rem);
  color: var(--text-strong);
  text-wrap: balance;
}

.lockup__context {
  margin: 0;
  font-family: system-ui, -apple-system, 'Segoe UI', sans-serif;
  font-size: .875rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: .3em;
  color: var(--text);
  opacity: .85;
}

.lockup__cta {
  margin-block-start: var(--sp-2);
  display: inline-flex;
  align-items: center;
  padding: .9rem 2.25rem;
  border: 1px solid rgb(232 223 204 / .55);
  border-radius: 9999px;
  color: var(--text-strong);
  text-decoration: none;
  font-family: system-ui, -apple-system, 'Segoe UI', sans-serif;
  font-size: .8125rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .12em;
  background: transparent;
  box-shadow: 0 0 20px transparent; /* declared transparent, not none — spacing-radius-elevation.md */
  transition:
    color var(--dur-base) var(--ease-out),
    background-color var(--dur-base) var(--ease-out),
    border-color var(--dur-base) var(--ease-out),
    box-shadow var(--dur-base) var(--ease-out),
    letter-spacing var(--dur-base) var(--ease-out);
}

.lockup__cta:hover,
.lockup__cta:focus-visible {
  color: var(--ground);
  background-color: var(--accent-gold);
  border-color: var(--accent-gold);
  letter-spacing: .16em;
  box-shadow: 0 0 20px var(--accent-gold);
}

.lockup__cta:focus-visible { outline: 2px solid var(--accent-gold-bright); outline-offset: 3px; }

/* ==========================================================================
   Responsive — knowledge/ux/responsive-strategy.md: reduce/drop ornament
   on small screens rather than shrinking it in place.
   ========================================================================== */

@media (max-width: 767px) {
  /* Edge-hanging portrait leaf layers eat too much of a 390px viewport —
     drop them, per responsive-strategy.md "decorative frame: reduce or
     drop." The top/bottom bands stay; they cost far less width. */
  .fg--left, .fg--right { display: none; }

  .fg--top    { min-block-size: 22%; }
  .fg--bottom { min-block-size: 24%; inline-size: 130%; }

  .lockup { max-inline-size: 92vw; }
  .lockup__eyebrow { letter-spacing: .22em; }
  .lockup__context { letter-spacing: .22em; }
}

/* ==========================================================================
   Reduced motion — CSS covers the static end-state; hero.js additionally
   gates every JS-driven animation (autoplay video, GSAP timeline, the
   mouse-parallax loop) per knowledge/ux/motion-accessibility.md, since a
   media query alone cannot stop a playing <video> or a running tween.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  .lockup__cta { transition: none; }
}

/* ==========================================================================
   Cinematic scene mode (desktop — scenes.js adds html.scene-mode).
   The document is still the scroll container internally, but the user
   never drives it directly: no scrollbar, no rubber-banding.
   ========================================================================== */

html.scene-mode {
  scrollbar-width: none;
  overscroll-behavior: none;
}
html.scene-mode::-webkit-scrollbar { display: none; }

/* ==========================================================================
   Touch devices — same scene model via native controlled snapping:
   one swipe settles on one scene; scroll-snap-stop prevents a fast
   swipe from skipping scenes. (Story beats are unpinned on mobile —
   plain 100svh scenes — so snap targets are honest section bounds.)
   ========================================================================== */

@media (max-width: 767px) {
  html { scroll-snap-type: y proximity; }
  .hero,
  .beat,
  .cscene,
  .finale {
    scroll-snap-align: start;
    scroll-snap-stop: always;
  }
}

/* ==========================================================================
   First-frame guarantee — the hero's "closed garden" state is rendered by
   CSS from the very first paint (html.js is set inline in <head> before
   render), so there is never a flash of the resting composition followed
   by a snap into the setup state. hero.js then writes the identical
   values inline via gsap.set and animates them open — no visual jump.
   Applies only when motion is allowed; no-JS and reduced-motion paint
   the complete resting hero instead.
   ========================================================================== */

@media (prefers-reduced-motion: no-preference) {
  /* LAYER 1 (background) and the environment are NOT transformed here —
     the garden is stable. Only the curtain and the tonal overlays start
     displaced, so the opening reads as foliage being pulled away rather
     than a camera pulling back. */
  html.js .hero__entrance-shade  { opacity: .6; }
  html.js .layer--midground img  { opacity: 0; transform: scale(1.04); }
  html.js .atmosphere__video     { opacity: 0; }
  html.js .atmosphere__haze      { opacity: .42; }

  /* LAYER 3 — the botanical curtain, closed: each edge group reaches
     inward along its own axis and sits slightly larger, so the four
     sides together enclose the centre. */
  html.js .fg--top {
    transform: translateY(var(--curtain-y)) scale(1.16) rotate(-.35deg);
  }
  html.js .fg--left {
    transform: translateX(var(--curtain-x)) scale(1.16) rotate(.5deg);
  }
  html.js .fg--right {
    transform: translateX(calc(0px - var(--curtain-x))) scale(1.16) rotate(-.5deg);
  }
  html.js .fg--bottom {
    transform: translateY(calc(0px - var(--curtain-y))) scale(1.16) rotate(.3deg);
  }

  html.js .lockup [data-reveal] { opacity: 0; transform: translateY(26px); }
}
