/* ==========================================================================
   JPSA — motion layers. Decoration only: every word stays real HTML above
   them, and without this file (and the grain element and motion.js) the site
   looks and works exactly as before.

   1.  Grain: a still film grain over the whole site. No JavaScript.
   2.  Light: slow light behind every section, both heroes, the call-to-action
       band and the footer, in colours taken from the palette. CSS animation.
   2b. Depth: that light and the hero's giant letter move slower than the page
       while scrolling (CSS scroll-driven animations). src/scripts/motion.js does
       the same where those are missing, and stops the light while off screen.

   The values sit on :root. In development, MotionPanel.astro changes them live.
   ========================================================================== */

:root {
  --fx-grain: 0.1;       /* grain opacity */
  --fx-glow-dark: 0.7;   /* light: black sections, the inner pages' hero, the footer */
  --fx-glow-home: 0.875; /* light: the home page hero (black) */
  --fx-glow-light: 0.35; /* light: white, paper and grey sections */
  --fx-glow-warm: 0.35;  /* light: red and yellow sections, the call-to-action band */
  --fx-drift: 20s;       /* one loop of the light */
  --fx-depth: 1.5;       /* how far the light and the giant letter lag behind the page */
  --fx-phone-glow: 1;
  --fx-phone-slow: 1;
}
@media (max-width: 720px) {
  :root { --fx-phone-glow: 0.65; --fx-phone-slow: 1.6; } /* phones: lighter and slower */
}

/* ---------- 1. Grain ---------- */
/* hard-light: noise above mid-grey lightens, below it darkens, and mid-grey
   leaves the colour as it is, so the grain shows on white and on black alike. */
.fx-grain {
  position: fixed;
  inset: 0;
  z-index: 2000; /* above everything, the header included; clicks pass through */
  pointer-events: none;
  opacity: var(--fx-grain);
  mix-blend-mode: hard-light;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='g' x='0' y='0' width='1' height='1' color-interpolation-filters='sRGB'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1'/%3E%3CfeComponentTransfer%3E%3CfeFuncR type='linear' slope='2' intercept='-.5'/%3E%3CfeFuncG type='linear' slope='2' intercept='-.5'/%3E%3CfeFuncB type='linear' slope='2' intercept='-.5'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23g)'/%3E%3C/svg%3E") 0 0 / 200px 200px;
}

/* ---------- 2. Light ---------- */
/* Colours per kind of section, all from the palette: red light in the dark, warm yellow
   (with a touch of red) on white, deeper shade on red, red warmth on yellow. */
.section { --fx-a: var(--yellow); --fx-b: color-mix(in srgb, var(--red) 40%, transparent); --fx-glow: var(--fx-glow-light); }
.page-hero,
.home-hero,
.section--black,
.site-footer { --fx-a: var(--red); --fx-b: var(--red-deep); --fx-glow: var(--fx-glow-dark); }
.section--red,
.cta-band { --fx-a: var(--red-deep); --fx-b: var(--black); --fx-glow: var(--fx-glow-warm); }
.section--yellow { --fx-a: var(--red); --fx-b: var(--red-deep); --fx-glow: var(--fx-glow-warm); }
.home-hero { --fx-glow: var(--fx-glow-home); }

.page-hero,
.home-hero,
.section,
.cta-band,
.site-footer { isolation: isolate; } /* keeps the light (z-index: -1) above the section's own colour */
.section { overflow: clip; }          /* the others already clip */

.page-hero::before,
.home-hero::before,
.section::before,
.cta-band::before,
.site-footer::before {
  content: "";
  position: absolute;
  inset: -30% -20%; /* room to drift without showing an edge */
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(34% 40% at 24% 32%, var(--fx-a), transparent 70%),
    radial-gradient(30% 36% at 76% 70%, var(--fx-b), transparent 70%);
  opacity: calc(var(--fx-glow) * var(--fx-phone-glow));
  animation: fx-drift calc(var(--fx-drift) * var(--fx-phone-slow)) linear infinite;
}
.section:nth-of-type(even)::before { scale: -1 1; } /* neighbours mirror each other */

/* Moves the whole loop at an even pace, so it is never standing still. */
@keyframes fx-drift {
  0%, 100% { transform: translate3d(-6%, -4%, 0) rotate(-4deg) scale(1); }
  25% { transform: translate3d(2%, -6%, 0) rotate(0deg) scale(1.06); }
  50% { transform: translate3d(6%, 2%, 0) rotate(4deg) scale(1.1); }
  75% { transform: translate3d(-1%, 6%, 0) rotate(1deg) scale(1.04); }
}

/* ---------- 2b. Depth while scrolling ---------- */
/* translate (not transform), so it adds to the drift instead of replacing it. */
@supports (animation-timeline: view()) {
  /* inset 0: measured from the edges of the screen, like motion.js (the default would follow
     the page's scroll-padding-top, which is there for the sticky header's anchor jumps). */
  .page-hero,
  .home-hero,
  .section,
  .cta-band,
  .site-footer { view-timeline: --fx block; view-timeline-inset: 0; }
  .section::before,
  .cta-band::before,
  .site-footer::before {
    animation: fx-drift calc(var(--fx-drift) * var(--fx-phone-slow)) linear infinite, fx-depth linear both;
    animation-timeline: auto, --fx;
  }
  .page-hero::before,
  .home-hero::before {
    animation: fx-drift calc(var(--fx-drift) * var(--fx-phone-slow)) linear infinite, fx-depth-top linear both;
    animation-timeline: auto, --fx;
    animation-range: normal, exit-crossing;
  }
  .page-hero__ghost {
    animation: fx-ghost linear both;
    animation-timeline: --fx;
    animation-range: exit-crossing;
  }
  /* Home hero: the giant word lags behind. */
  .home-hero__word {
    animation: fx-word linear both;
    animation-timeline: --fx;
    animation-range: exit-crossing;
  }
}
/* An explicit "from": an implied one would get the default ease instead of linear. */
@keyframes fx-depth { from { translate: 0 calc(-10% * var(--fx-depth)); } to { translate: 0 calc(10% * var(--fx-depth)); } }
@keyframes fx-depth-top { from { translate: 0 0; } to { translate: 0 calc(16% * var(--fx-depth)); } }
@keyframes fx-ghost { from { translate: 0 0; } to { translate: 0 calc(40% * var(--fx-depth)); } }
@keyframes fx-word { from { translate: 0 0; } to { translate: 0 calc(22% * var(--fx-depth)); } }

/* The same movement from motion.js where scroll-driven animations are missing:
   --fx-p runs from -1 to 1 across a section (cover), and from 0 to 1 as a hero's top
   edge crosses the top of the screen and its bottom edge follows (exit-crossing). */
.fx-js .section::before,
.fx-js .cta-band::before,
.fx-js .site-footer::before { translate: 0 calc(var(--fx-p, 0) * 10% * var(--fx-depth)); }
.fx-js .page-hero::before,
.fx-js .home-hero::before { translate: 0 calc(var(--fx-p, 0) * 16% * var(--fx-depth)); }
.fx-js .page-hero__ghost { translate: 0 calc(var(--fx-p, 0) * 40% * var(--fx-depth)); }
.fx-js .home-hero__word { translate: 0 calc(var(--fx-p, 0) * 22% * var(--fx-depth)); }

/* Off screen (motion.js adds .fx-idle a quarter of a screen away): no animation at all, so the
   browser keeps no layer for it. Two classes, so it wins over the shorthands above. */
.page-hero.fx-idle::before,
.home-hero.fx-idle::before,
.section.fx-idle::before,
.cta-band.fx-idle::before,
.site-footer.fx-idle::before { animation: none; }

/* ---------- Without clipping, reduced motion, print ---------- */
/* Browsers without overflow: clip get the light standing still, inside each section. */
@supports not (overflow: clip) {
  .section::before { inset: 0; animation: none; translate: none; }
}
/* Phones and tablets: the word stands still (:root raises this above the motion.js rules). */
@media (max-width: 900px) {
  :root .home-hero__word { animation: none; translate: none; }
}
/* Everything stands still; the grain and the light stay, where they start. */
@media (prefers-reduced-motion: reduce) {
  .page-hero::before,
  .home-hero::before,
  .section::before,
  .cta-band::before,
  .site-footer::before,
  .page-hero__ghost,
  :root .home-hero__word { animation: none; translate: none; }
}
@media print, (forced-colors: active) {
  .fx-grain,
  .page-hero::before,
  .home-hero::before,
  .section::before,
  .cta-band::before,
  .site-footer::before { display: none; }
}
