/* ============================================================
   ADDITIVE ALIVENESS LAYER — motion-only presentation (Milo).
   Loaded after sections.css. All motion CSS is scoped under
   .motion-ready; static fallbacks under .motion-static / .is-solo /
   .is-reduced-motion. Content is ALIVE AT t0 — motion here is ambient
   / pointer / state-driven polish only, NEVER a content gate.

   This is the SHARED aliveness surface. Per-cell set-piece motion
   lives in each cell-N.css / cell-N.js. Stripped of all Sharp
   set-pieces (tilestone / design-planning / before-after / svc /
   work / reviews / team). Milo motion = steam-soft.
   ============================================================ */

/* Native cursor by default — no custom trailing cursor (reads as laggy). */

/* ---- Generic hover-pop — the scale-not-shift rule ----
   Any clickable card/tile a cell marks .lift gets a modest rise+scale on
   hover. Gated to hover-capable devices so touch never sticks a hover state. */
.motion-ready .lift,
.motion-ready .btn {
  transition:
    transform 320ms var(--ease-out),
    box-shadow 320ms var(--ease-out),
    border-color 320ms var(--ease-out),
    background 320ms var(--ease-out);
}
@media (hover: hover) {
  .motion-ready .lift:hover {
    transform: translate3d(0, -0.55rem, 0) scale(1.035);
    box-shadow: 0 24px 52px rgba(86, 63, 43, 0.22);   /* clearly-read lift (was -0.28rem/1.02, imperceptible per WIDE) */
  }
}

/* ---- Ambient hooks cells can attach to ----
   Cells add these classes (or [data-ambient]) to elements they want gently
   alive at rest: sun-through-glass light drift + a slow steam wisp. Both are
   GPU-cheap, respect reduced-motion (scoped under .motion-ready only), and
   loop forever — the "≥1 ambient-alive element per cell" coverage floor. */

/* sun-through-glass — a slow warm light sheen drift */
.motion-ready .amb-sun {
  position: relative;
  overflow: hidden;
}
.motion-ready .amb-sun::after {
  content: "";
  position: absolute;
  inset: -30% -60%;
  pointer-events: none;
  background: radial-gradient(closest-side, rgba(255, 244, 222, 0.5), transparent 70%);
  mix-blend-mode: screen;
  opacity: 0.55;
  animation: amb-sun-drift 14s ease-in-out infinite alternate;
}
@keyframes amb-sun-drift {
  from { transform: translate3d(-8%, -4%, 0) scale(1); }
  to   { transform: translate3d(10%, 6%, 0) scale(1.08); }
}

/* steam wisp — a soft rising, fading plume (attach to a coffee/hero element) */
.motion-ready .amb-steam {
  position: relative;
}
.motion-ready .amb-steam::before {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 60%;
  width: 34px;
  height: 90px;
  pointer-events: none;
  transform: translateX(-50%);
  background: radial-gradient(ellipse at 50% 100%, rgba(255, 255, 255, 0.42), transparent 68%);
  filter: blur(6px);
  opacity: 0;
  animation: amb-steam-rise 5.5s ease-in-out infinite;
}
@keyframes amb-steam-rise {
  0%   { opacity: 0;    transform: translate(-50%, 0) scale(0.8); }
  30%  { opacity: 0.5; }
  100% { opacity: 0;    transform: translate(-50%, -46px) scale(1.2); }
}

/* slow daypart-glyph pulse — a gentle breathing scale for sun glyphs / stars */
.motion-ready .amb-pulse {
  animation: amb-pulse 4.5s ease-in-out infinite;
  transform-origin: center;
}
@keyframes amb-pulse {
  0%, 100% { transform: scale(0.94); opacity: 0.72; }
  50%      { transform: scale(1.12); opacity: 1; }   /* wider amplitude so it reads as alive (was 1→1.08/0.9, imperceptible per WIDE) */
}

/* ticket-perf shimmer — a slow sweep along a perforation edge */
.motion-ready .amb-perf { position: relative; overflow: hidden; }
.motion-ready .amb-perf::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(100deg, transparent 40%, rgba(76, 181, 200, 0.14) 50%, transparent 60%);
  transform: translateX(-100%);
  animation: amb-perf-sweep 7s ease-in-out infinite;
}
@keyframes amb-perf-sweep {
  0%, 60% { transform: translateX(-100%); }
  100%    { transform: translateX(100%); }
}

/* ---- Reveal GPU-hint cleanup ----
   base.css sets will-change on every .js [data-reveal] so the reveal composites
   smoothly; clear it once revealed so long pages don't retain dozens of
   compositor layers at rest. (Loaded after base.css → wins on source order.) */
.js [data-reveal].is-in { will-change: auto; }

/* ---- Reduced-motion / static floor ----
   All ambient set-pieces early-return in motion.js (no .motion-ready), so the
   above never runs. Belt-and-suspenders: kill any residual animation. */
@media (prefers-reduced-motion: reduce) {
  .amb-sun::after,
  .amb-steam::before,
  .amb-pulse,
  .amb-perf::after { animation: none; }
}
