/* =====================================================================
   Tavio surface textures & motion utilities
   grain.css  (load after colors_and_type.css)
   ===================================================================== */

/* Subtle film grain for dark surfaces. Apply .grain to a green-black
   block; the noise sits at very low opacity above the fill but below
   content. Keep it ONLY on dark surfaces. */
.grain { position: relative; isolation: isolate; }
.grain > * { position: relative; z-index: 1; }
.grain::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: var(--grain-opacity, 0.5);
  mix-blend-mode: soft-light;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 160px 160px;
}

/* ---- marquee: slow, pausable ---- */
.marquee { overflow: hidden; display: flex; }
.marquee__track {
  display: flex;
  flex: 0 0 auto;
  min-width: 100%;
  gap: var(--space-7);
  padding-right: var(--space-7);
  animation: tavio-marquee var(--marquee-duration) linear infinite;
  will-change: transform;
}
.marquee:hover .marquee__track,
.marquee:focus-within .marquee__track { animation-play-state: paused; }
@keyframes tavio-marquee { to { transform: translateX(-100%); } }
@media (prefers-reduced-motion: reduce) {
  .marquee__track { animation: none; }
}

/* ---- the small hover lift ---- */
.lift { transition: transform var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out); }
.lift:hover { transform: translateY(-2px); }

/* ---- one orchestrated load: stagger children with --i ----
   The VISIBLE state is the default. The hidden-then-rise entrance only
   applies once JS adds `.is-loaded` (and only when motion is allowed), and
   the class is removed when the animation finishes. So any context without
   an actively-running animation: static capture, print/PDF, reduced motion,
   background tabs, no-JS: shows the content, never opacity:0. */
.load-seq > * { opacity: 1; transform: none; }
@media (prefers-reduced-motion: no-preference) {
  .load-seq.is-loaded > * {
    animation: tavio-rise var(--dur-load) var(--ease-out) both;
    animation-delay: calc(var(--i, 0) * 90ms);
  }
}
@keyframes tavio-rise {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: none; }
}
