/* ==========================================================================
   Viola — Animations: cookie-bite loading screen, scroll reveal, mascots,
   marquee, pattern drift.
   RTL note: transform: translateX and box-shadow offsets do NOT auto-flip
   under dir="rtl". Reveal/hover motion standardizes on translateY; the
   marquee is explicitly dir="ltr" so its translateX math is stable.
   ========================================================================== */

/* ==========================================================================
   Page loader — Cookie Loading, Claude Design handoff (2026-07-09).
   HOME ONLY since 2026-07-11 (client: inner pages must open instantly) —
   #page-loader exists solely in index.html. The inline logo-cookie SVG
   pops in, is eaten in 5 scalloped bites + a final chomp, crumbs fly, brief
   empty hold, then loops — a pure 1.5s CSS cycle (sped up from the handoff's
   3s, client 2026-07-11; percentages untouched). The bites are NOT artwork:
   black circle clusters inside the svg's own <mask id="eat"> whose opacity
   flips 0→1 at each chomp. Pivots (cookie center 450,292) are SVG user units
   and REQUIRE transform-box: view-box. js/loader.js no longer steps bites —
   it only picks the fade-out moment (page loaded + the "all eaten" beat).
   ========================================================================== */
.page-loader {
  position: fixed;
  inset: 0;
  z-index: 999;
  display: grid;
  place-items: center;
  background: var(--loader-bg);
  transition: opacity 0.3s ease, visibility 0.3s ease;
}

.page-loader.is-hidden {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

.loader-stage {
  display: grid;
  justify-items: center;
  gap: var(--space-4);
  color: var(--loader-ink);
  transition: transform 0.3s var(--ease-brand), opacity 0.25s ease;
}

.page-loader.is-hidden .loader-stage {
  transform: translateY(-24px) scale(0.92);
  opacity: 0;
}

.loader-cookie {
  display: block;
  inline-size: min(200px, 42vmin);
  block-size: auto;
}

/* Rig plumbing — selectors/keyframes copied verbatim from the approved
   reference (Cookie Loading.html), only scoped under .page-loader. */
.page-loader #cookieWrap,
.page-loader #jolt,
.page-loader .crumb { transform-box: view-box; }

.page-loader #cookieWrap {
  transform-origin: 450px 292px;
  animation: v-pop 1.5s ease-in-out infinite;
}

.page-loader #jolt {
  transform-origin: 450px 292px;
  animation: v-jolt 1.5s ease-in-out infinite;
}

.page-loader .crumb { opacity: 0; transform-origin: 450px 292px; }
.page-loader .bite { opacity: 0; fill: #000; }

@keyframes v-pop {
  0%   { transform: scale(0.4); opacity: 0; }
  6%   { transform: scale(1.07); opacity: 1; }
  9%   { transform: scale(1); opacity: 1; }
  74%  { transform: scale(1); opacity: 1; }
  76%, 100% { transform: scale(1); opacity: 0; }
}

@keyframes v-jolt {
  0% { transform: rotate(0deg) scale(1); }
  14.5% { transform: rotate(0deg) scale(1); }
  16.2% { transform: rotate(-2.4deg) scale(0.97); }
  20% { transform: rotate(0deg) scale(1); }
  27.5% { transform: rotate(0deg) scale(1); }
  29.2% { transform: rotate(2.4deg) scale(0.97); }
  33% { transform: rotate(0deg) scale(1); }
  40.5% { transform: rotate(0deg) scale(1); }
  42.2% { transform: rotate(-2.4deg) scale(0.97); }
  46% { transform: rotate(0deg) scale(1); }
  53.5% { transform: rotate(0deg) scale(1); }
  55.2% { transform: rotate(2.4deg) scale(0.97); }
  59% { transform: rotate(0deg) scale(1); }
  66.5% { transform: rotate(0deg) scale(1); }
  68.2% { transform: rotate(-2.4deg) scale(0.97); }
  72% { transform: rotate(0deg) scale(1); }
  100% { transform: rotate(0deg) scale(1); }
}

.page-loader .bite5 { animation: v-bite5 1.5s linear infinite; }
@keyframes v-bite5 { 0%, 70.5% { opacity: 0; } 71%, 100% { opacity: 1; } }
.page-loader .bite0 { animation: v-bite0 1.5s linear infinite; }
@keyframes v-bite0 { 0%, 14.5% { opacity: 0; } 15%, 100% { opacity: 1; } }
.page-loader .bite1 { animation: v-bite1 1.5s linear infinite; }
@keyframes v-bite1 { 0%, 27.5% { opacity: 0; } 28%, 100% { opacity: 1; } }
.page-loader .bite2 { animation: v-bite2 1.5s linear infinite; }
@keyframes v-bite2 { 0%, 40.5% { opacity: 0; } 41%, 100% { opacity: 1; } }
.page-loader .bite3 { animation: v-bite3 1.5s linear infinite; }
@keyframes v-bite3 { 0%, 53.5% { opacity: 0; } 54%, 100% { opacity: 1; } }
.page-loader .bite4 { animation: v-bite4 1.5s linear infinite; }
@keyframes v-bite4 { 0%, 66.5% { opacity: 0; } 67%, 100% { opacity: 1; } }

.page-loader .crumb0_0 { animation: v-crumb0_0 1.5s linear infinite; }
@keyframes v-crumb0_0 {
  0%, 14.6% { opacity: 0; transform: translate(0,0) scale(1); }
  15.8% { opacity: 1; transform: translate(8.8px, -16.9px) scale(1); }
  23%, 100% { opacity: 0; transform: translate(29.4px, -28.5px) scale(0.5); }
}
.page-loader .crumb0_1 { animation: v-crumb0_1 1.5s linear infinite; }
@keyframes v-crumb0_1 {
  0%, 14.6% { opacity: 0; transform: translate(0,0) scale(1); }
  15.8% { opacity: 1; transform: translate(14.9px, -6.4px) scale(1); }
  23%, 100% { opacity: 0; transform: translate(49.7px, 6.8px) scale(0.5); }
}
.page-loader .crumb1_0 { animation: v-crumb1_0 1.5s linear infinite; }
@keyframes v-crumb1_0 {
  0%, 27.6% { opacity: 0; transform: translate(0,0) scale(1); }
  28.8% { opacity: 1; transform: translate(-11.3px, -14.6px) scale(1); }
  36%, 100% { opacity: 0; transform: translate(-37.7px, -20.8px) scale(0.5); }
}
.page-loader .crumb1_1 { animation: v-crumb1_1 1.5s linear infinite; }
@keyframes v-crumb1_1 {
  0%, 27.6% { opacity: 0; transform: translate(0,0) scale(1); }
  28.8% { opacity: 1; transform: translate(-0.3px, -19.8px) scale(1); }
  36%, 100% { opacity: 0; transform: translate(-0.9px, -38.0px) scale(0.5); }
}
.page-loader .crumb2_0 { animation: v-crumb2_0 1.5s linear infinite; }
@keyframes v-crumb2_0 {
  0%, 40.6% { opacity: 0; transform: translate(0,0) scale(1); }
  41.8% { opacity: 1; transform: translate(-13.9px, 0.8px) scale(1); }
  49%, 100% { opacity: 0; transform: translate(-46.4px, 30.7px) scale(0.5); }
}
.page-loader .crumb2_1 { animation: v-crumb2_1 1.5s linear infinite; }
@keyframes v-crumb2_1 {
  0%, 40.6% { opacity: 0; transform: translate(0,0) scale(1); }
  41.8% { opacity: 1; transform: translate(-13.5px, -11.4px) scale(1); }
  49%, 100% { opacity: 0; transform: translate(-44.9px, -9.9px) scale(0.5); }
}
.page-loader .crumb3_0 { animation: v-crumb3_0 1.5s linear infinite; }
@keyframes v-crumb3_0 {
  0%, 53.6% { opacity: 0; transform: translate(0,0) scale(1); }
  54.8% { opacity: 1; transform: translate(12.4px, 3.6px) scale(1); }
  62%, 100% { opacity: 0; transform: translate(41.5px, 40.0px) scale(0.5); }
}
.page-loader .crumb3_1 { animation: v-crumb3_1 1.5s linear infinite; }
@keyframes v-crumb3_1 {
  0%, 53.6% { opacity: 0; transform: translate(0,0) scale(1); }
  54.8% { opacity: 1; transform: translate(2.1px, 10.1px) scale(1); }
  62%, 100% { opacity: 0; transform: translate(7.0px, 61.5px) scale(0.5); }
}
.page-loader .crumb4_0 { animation: v-crumb4_0 1.5s linear infinite; }
@keyframes v-crumb4_0 {
  0%, 66.6% { opacity: 0; transform: translate(0,0) scale(1); }
  67.8% { opacity: 1; transform: translate(-8.4px, 7.6px) scale(1); }
  75%, 100% { opacity: 0; transform: translate(-28.0px, 53.5px) scale(0.5); }
}
.page-loader .crumb4_1 { animation: v-crumb4_1 1.5s linear infinite; }
@keyframes v-crumb4_1 {
  0%, 66.6% { opacity: 0; transform: translate(0,0) scale(1); }
  67.8% { opacity: 1; transform: translate(-14.9px, -2.7px) scale(1); }
  75%, 100% { opacity: 0; transform: translate(-49.5px, 19.0px) scale(0.5); }
}

/* Frozen loader = the intact static cookie (bites/crumbs rest at opacity 0).
   The global reduced-motion block below already clamps everything; this is
   explicit insurance for the loader's opacity-driven bites. */
@media (prefers-reduced-motion: reduce) {
  .page-loader #cookieWrap,
  .page-loader #jolt,
  .page-loader .bite,
  .page-loader .crumb { animation: none !important; }
}

.loader-text {
  font-weight: 700;
  font-size: var(--fs-sm);
  color: var(--color-text-muted);
}

.loader-text .dot {
  display: inline-block;
  animation: dot-bounce 1.2s ease-in-out infinite;
}

.loader-text .dot:nth-child(2) { animation-delay: 0.15s; }
.loader-text .dot:nth-child(3) { animation-delay: 0.3s; }

@keyframes dot-bounce {
  0%, 60%, 100% { transform: translateY(0); }
  30% { transform: translateY(-5px); }
}

/* ==========================================================================
   CTA crumb burst (js/crumbs.js spawns and animates; this is just the look)
   ========================================================================== */
.cta-crumb {
  position: fixed;
  z-index: 998;
  border-radius: 2.5px;
  background: var(--color-brand-primary);
  pointer-events: none;
}

/* ==========================================================================
   Scroll reveal
   ========================================================================== */
[data-reveal] {
  opacity: 0;
  transform: translateY(30px);
  transition: opacity var(--dur-slow) var(--ease-brand), transform var(--dur-slow) var(--ease-brand);
}

[data-reveal].is-visible {
  opacity: 1;
  transform: translateY(0);
}

[data-reveal="fade"] {
  transform: none;
}

[data-reveal="pop"] {
  transform: translateY(18px) scale(0.94);
}

[data-reveal="pop"].is-visible {
  transform: translateY(0) scale(1);
  transition-timing-function: var(--ease-bounce);
}

/* Stagger helper: apply data-reveal-delay="1..6" for cascading reveals */
[data-reveal-delay="1"] { transition-delay: 0.08s; }
[data-reveal-delay="2"] { transition-delay: 0.16s; }
[data-reveal-delay="3"] { transition-delay: 0.24s; }
[data-reveal-delay="4"] { transition-delay: 0.32s; }
[data-reveal-delay="5"] { transition-delay: 0.4s; }
[data-reveal-delay="6"] { transition-delay: 0.48s; }

/* ==========================================================================
   Mascot idle float + hover wiggle
   ========================================================================== */
.mascot-idle {
  animation: mascot-float 4.5s ease-in-out infinite;
}

@keyframes mascot-float {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50% { transform: translateY(-10px) rotate(-2deg); }
}

.mascot-idle:hover {
  animation: mascot-wiggle 0.6s var(--ease-bounce);
}

@keyframes mascot-wiggle {
  0% { transform: rotate(0deg) scale(1); }
  30% { transform: rotate(-6deg) scale(1.08); }
  60% { transform: rotate(5deg) scale(1.05); }
  100% { transform: rotate(0deg) scale(1.05); }
}

/* ==========================================================================
   Marquee strip (brand words + mascots, explicitly LTR for stable math)
   2026-07-08: rebuilt as two identical .marquee__group halves, each sliding
   exactly -100% of its OWN width. The old single-track -50% math ignored the
   flex gap between the two halves, so every loop restart visibly jumped and
   clipped words. Each group now carries its own leading gap
   (padding-inline-start) so the seam spacing is identical everywhere.
   ========================================================================== */
.marquee {
  overflow: hidden;
  padding-block: var(--space-3);
  border-block: 2px solid var(--color-border-soft);
}

.marquee__track {
  display: flex;
  inline-size: max-content;
}

.marquee__group {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  padding-inline-start: var(--space-5);
  flex: none;
  animation: marquee-scroll 30s linear infinite;
}

/* 2026-07-07: hover-pause removed by client request — the strip never stops */
@keyframes marquee-scroll {
  from { transform: translateX(0); }
  to { transform: translateX(-100%); }
}

.marquee__item {
  font-size: var(--fs-xl);
  font-weight: 700;
  color: var(--color-brand-primary);
  white-space: nowrap;
}

.marquee__item--outline {
  color: transparent;
  -webkit-text-stroke: 1.6px var(--color-brand-tertiary);
}

.marquee__mascot {
  inline-size: 44px;
  block-size: 44px;
  object-fit: contain;
  flex: none;
}

/* ==========================================================================
   Pattern drift (slow, ambient) — every .pattern-band uses these keyframes
   (base.css); -680px = exactly two 340px tiles, so the loop is seamless.
   ========================================================================== */
@keyframes pattern-drift {
  from { background-position: 0 0; }
  to { background-position: -680px 0; }
}

/* ==========================================================================
   Reduced motion
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }

  [data-reveal] {
    opacity: 1;
    transform: none;
  }

  .marquee__group,
  .pattern-band {
    animation: none;
  }
}
