/* calm-layer.css — CoryBuilt
   Purpose: keep the star-trail hero and parallax as the arrival moment, then
   let them recede so text is the thing you look at. Motion becomes an event,
   not a condition.

   Load this AFTER your existing site CSS so it wins on specificity ties.

   How it works:
     - .hero gets a charcoal scrim behind its content (readable text over stars).
     - After ~9s, <html> gains .is-settled (set by calm-layer.js) and the hero
       animation drops to a slow idle at low opacity.
     - Parallax layers stop translating once settled; they hold position.
     - Scroll-reveal happens once per element and is never re-triggered.
   Change ONLY the selectors in the "SITE HOOKS" block to match your markup. */

/* ── SITE HOOKS ─────────────────────────────────────────────────────────────
   Adjust these to your existing class names if they differ. */
:root {
  --calm-scrim: rgba(16, 16, 19, 0.74);   /* charcoal over the star field */
  --calm-scrim-edge: rgba(8, 8, 10, 0.94);
  --calm-settle-ms: 2400ms;
}

/* Charcoal bed. The hero art stays visible through it; type sits on a
   consistent value so contrast no longer depends on where a star trail lands. */
.hero::after,
.chapter-hero::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    radial-gradient(120% 90% at 50% 30%, transparent 0%, var(--calm-scrim) 62%),
    linear-gradient(180deg, var(--calm-scrim-edge) 0%, var(--calm-scrim) 26%,
                    var(--calm-scrim) 74%, var(--calm-scrim-edge) 100%);
}

.hero > *:not(canvas):not(video):not(.hero__art),
.chapter-hero > *:not(canvas):not(video):not(.hero__art) {
  position: relative;
  z-index: 2;
}

/* The star field itself: full presence on arrival, then a quiet idle. */
.hero canvas,
.hero__art,
.starfield {
  transition:
    opacity var(--calm-settle-ms) cubic-bezier(0.4, 0, 0.2, 1),
    filter var(--calm-settle-ms) cubic-bezier(0.4, 0, 0.2, 1);
}

html.is-settled .hero canvas,
html.is-settled .hero__art,
html.is-settled .starfield {
  opacity: 0.42;
  filter: saturate(0.7) blur(0.3px);
}

/* Parallax: translate during the arrival, hold still afterward. */
html.is-settled [data-parallax],
html.is-settled .parallax-layer {
  transform: none !important;
  transition: transform var(--calm-settle-ms) cubic-bezier(0.4, 0, 0.2, 1);
}

/* Any looping decorative animation stops once settled. Ambient loops are the
   main reason the page felt busy; one-shot reveals are kept. */
html.is-settled .is-ambient,
html.is-settled [data-motion='ambient'] {
  animation-play-state: paused;
  opacity: 0.5;
  transition: opacity var(--calm-settle-ms) ease;
}

/* Scroll reveal, one shot, no re-trigger, no per-card stagger. */
[data-reveal] {
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 600ms ease, transform 600ms cubic-bezier(0.22, 1, 0.36, 1);
}
[data-reveal].is-revealed {
  opacity: 1;
  transform: none;
}

/* Readability floor for body copy sitting over art. */
.hero p,
.chapter-hero p,
.hero__lede {
  max-width: 62ch;
  text-wrap: pretty;
}

/* Focus must stay visible against the darker scrim. */
:where(a, button, [tabindex]):focus-visible {
  outline: 2px solid #35b9c2;
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  .hero canvas,
  .hero__art,
  .starfield { opacity: 0.35; }
  [data-parallax], .parallax-layer { transform: none !important; }
  [data-reveal] { opacity: 1; transform: none; transition: none; }
  .is-ambient, [data-motion='ambient'] { animation: none !important; }
}
