/* ============================================================================
   AMP · ALICE MARKET PLACE — ALIVE / MOTION LAYER (additive, self-contained)
   File: assets/alive/amp-alive.css   ·   pairs with: assets/alive/amp-alive.js
   --------------------------------------------------------------------------
   Purpose: make every page BREATHE by attaching living motion to the site's
   EXISTING selectors (.amp-stat / .amp-stat-num / .amp-statx / .amp-card-num /
   .amp-card / .amp-stat-row / .amp-table / .rev-band__value) WITHOUT fighting
   the engines already on the page (the v19 amp-life.js reveal/counter runtime
   and the inline #amp-wow-script count-up loop). This layer:
     1) count-up + a subtle POP on metrics scrolling into view
     2) periodic gentle re-pulse / glow so key data keeps breathing
     3) scroll-reveal cascade for sections / cards (only where none exists)
     4) hover life on cards & CTAs
     5) an overall tasteful living quality
   --------------------------------------------------------------------------
   HARD RULES honored here:
   · Pure CSS/SVG — zero external assets, zero downloads, zero logos.
   · GPU-only animation props (transform / opacity / box-shadow). No layout.
   · prefers-reduced-motion: REDUCE => no motion at all; numbers show final value.
   · Institutional restraint: slow loops, low amplitude, never a screensaver.
   · Idempotent: all state is class/attr driven; safe to load once per page.
   Token source of truth: assets/amp-design-system.css ( --amp-* ). Fallbacks
   are inlined so this layer is also correct if loaded before that file.
   Author: AMP ALIVE/MOTION engineer · 2026-06-03
   ========================================================================== */

/* The JS sets <html class="amp-alive-on"> only when motion is permitted AND
   the script booted. Every animated rule below is therefore scoped to
   .amp-alive-on, which means: no JS / reduced-motion / boot failure => the
   page is exactly its original static self. Safe by default. */

/* ---------------------------------------------------------------------------
   0 · Tokens (mirror of design-system; only used as fallbacks)
   ------------------------------------------------------------------------- */
:root {
  --amp-alive-gold:      var(--amp-gold,   #C9A84C);
  --amp-alive-gold-hot:  var(--amp-gold-hot, #FFD56B);
  --amp-alive-glow:      rgba(201, 168, 76, 0.45);
  --amp-alive-glow-soft: rgba(201, 168, 76, 0.18);
  --amp-alive-ease:      var(--amp-ease,       cubic-bezier(0.16,0.84,0.36,1));
  --amp-alive-ease-io:   var(--amp-ease-inout, cubic-bezier(0.65,0,0.35,1));
}

/* ===========================================================================
   1 · COUNT-UP TARGETS — POP on reveal
   The JS adds .amp-alive-pop to a metric the instant it enters view (after the
   count-up settles, or immediately for already-driven numbers). The pop is a
   one-shot transform; it never touches text, so it composes safely on top of
   any existing count-up engine.
   =========================================================================== */
.amp-alive-on .amp-alive-pop {
  animation: amp-alive-pop 360ms var(--amp-alive-ease) 1;
  transform-origin: left center;
}
@keyframes amp-alive-pop {
  0%   { transform: scale(1);    }
  45%  { transform: scale(1.045);}
  100% { transform: scale(1);    }
}
/* numbers that are centered in their block pop from center */
.amp-alive-on .amp-alive-pop[data-amp-pop-origin="center"] { transform-origin: center center; }

/* ===========================================================================
   2 · PERIODIC RE-PULSE / GLOW — the "keeps breathing" beat
   The JS, on its single shared heartbeat, toggles .amp-alive-beat on a small
   rotating set of key data points. The class drives a soft gold halo that
   eases in and out once, then is removed — a gentle, occasional shimmer, NOT a
   continuous glow. Applied to chosen .amp-datapoint / lead metric per page.
   =========================================================================== */
.amp-alive-on .amp-alive-beat {
  animation: amp-alive-beat 1700ms var(--amp-alive-ease-io) 1;
}
@keyframes amp-alive-beat {
  0%   { text-shadow: 0 0 0     rgba(201,168,76,0);    }
  35%  { text-shadow: 0 0 18px  var(--amp-alive-glow); }
  100% { text-shadow: 0 0 0     rgba(201,168,76,0);    }
}
/* Box-bearing data points (chips / cells) breathe via box-shadow instead. */
.amp-alive-on .amp-alive-beat.amp-alive-beat--box {
  animation: amp-alive-beat-box 1700ms var(--amp-alive-ease-io) 1;
}
@keyframes amp-alive-beat-box {
  0%   { box-shadow: 0 0 0 0    rgba(201,168,76,0);    }
  35%  { box-shadow: 0 0 0 3px  var(--amp-alive-glow-soft); }
  100% { box-shadow: 0 0 0 0    rgba(201,168,76,0);    }
}

/* A standing soft pulse for genuine "live" status dots (opt-in only). */
.amp-alive-on .amp-alive-live-dot {
  animation: amp-alive-live 1900ms var(--amp-alive-ease-io) infinite;
}
@keyframes amp-alive-live {
  0%,100% { opacity: 0.55; box-shadow: 0 0 0 0   rgba(201,168,76,0.0); }
  50%     { opacity: 1;    box-shadow: 0 0 0 4px rgba(201,168,76,0.16); }
}

/* ===========================================================================
   3 · SCROLL-REVEAL CASCADE
   Only elements the JS tags with .amp-alive-reveal (i.e. NOT already carrying
   the page's own .lf-reveal) get this. Base state is hidden-but-laid-out;
   .is-shown (added by the observer) settles it. Stagger via --amp-alive-i.
   =========================================================================== */
/* Premium reveal: transform + opacity ONLY. translateY(20px) with a tasteful
   sub-1 scale settle (0.985 -> 1), eased over ~650ms on a smooth cubic-bezier.
   Reveals ONCE (the JS unobserves after .is-shown), so this is never a
   screensaver. Stagger is capped in JS (--amp-alive-i 0..5) so long lists
   don't lag; the per-step delay below keeps the whole cascade well under a
   second even at the cap. */
.amp-alive-on .amp-alive-reveal {
  opacity: 0;
  transform: translateY(20px) scale(0.985);
  transition:
    opacity 650ms cubic-bezier(0.22, 0.61, 0.36, 1),
    transform 650ms cubic-bezier(0.22, 0.61, 0.36, 1);
  transition-delay: calc(var(--amp-alive-i, 0) * 80ms);
  will-change: opacity, transform;
}
.amp-alive-on .amp-alive-reveal.is-shown {
  opacity: 1;
  transform: translateY(0) scale(1);
}

/* ===========================================================================
   4 · HOVER LIFE — cards & CTAs
   Applied via .amp-alive-lift, which the JS adds only to interactive cards /
   CTAs that DON'T already carry the page's .lf-lift hover behavior, so the two
   never stack. Translate is suppressed under reduced-motion by scoping to
   .amp-alive-on; color/border still react through the element's own styles.
   =========================================================================== */
.amp-alive-on .amp-alive-lift {
  transition:
    transform var(--amp-dur, 180ms) var(--amp-alive-ease),
    box-shadow var(--amp-dur, 180ms) var(--amp-alive-ease),
    border-color var(--amp-dur, 180ms) var(--amp-alive-ease);
}
.amp-alive-on .amp-alive-lift:hover {
  transform: translateY(-3px);
  box-shadow: 0 14px 34px rgba(0,0,0,0.34);
  border-color: var(--amp-gold-border, rgba(201,168,76,0.30));
}
.amp-alive-on .amp-alive-lift:active { transform: translateY(-1px) scale(0.995); }

/* CTA / link arrow nudge — opt-in via existing arrow glyphs or .amp-alive-arrow */
.amp-alive-on .amp-alive-arrow { transition: transform var(--amp-dur, 180ms) var(--amp-alive-ease); }
.amp-alive-on a:hover > .amp-alive-arrow,
.amp-alive-on button:hover > .amp-alive-arrow,
.amp-alive-on .amp-alive-lift:hover .amp-alive-arrow { transform: translateX(3px); }

/* A quiet gold keyline sweep for cards that opt in via data-amp-alive="sweep". */
.amp-alive-on [data-amp-alive~="sweep"] { position: relative; overflow: hidden; }
.amp-alive-on [data-amp-alive~="sweep"]::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(120deg, transparent 30%,
              var(--amp-alive-glow-soft) 50%, transparent 70%);
  transform: translateX(-120%);
  transition: transform 720ms var(--amp-alive-ease-io);
  pointer-events: none;
}
.amp-alive-on [data-amp-alive~="sweep"]:hover::after { transform: translateX(120%); }

/* ===========================================================================
   5 · OVERALL LIVING QUALITY — table row wake + section breath
   Tasteful, low amplitude. Rows in .amp-table wake their gold rule on hover;
   a section flagged data-amp-alive~="breath" gets an ultra-slow ambient
   gradient drift (GPU background-position) at very low opacity.
   =========================================================================== */
.amp-alive-on .amp-table tbody tr {
  transition: background var(--amp-dur, 180ms) var(--amp-alive-ease);
}
.amp-alive-on .amp-table tbody tr:hover {
  background: var(--amp-gold-fog, rgba(201,168,76,0.18));
}

.amp-alive-on [data-amp-alive~="breath"] { position: relative; }
.amp-alive-on [data-amp-alive~="breath"]::before {
  content: "";
  position: absolute; inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(60% 80% at 50% 110%, var(--amp-alive-glow-soft), transparent 70%);
  opacity: 0.5;
  animation: amp-alive-breath 26s var(--amp-alive-ease-io) infinite;
  will-change: opacity, transform;
}
@keyframes amp-alive-breath {
  0%,100% { opacity: 0.35; transform: scale(1)    translateY(0);    }
  50%     { opacity: 0.6;  transform: scale(1.04) translateY(-1.5%); }
}
/* keep breath strictly behind real content */
.amp-alive-on [data-amp-alive~="breath"] > * { position: relative; z-index: 1; }

/* ===========================================================================
   6 · REDUCED-MOTION + NO-JS HARD STOP (belt-and-suspenders)
   The .amp-alive-on gate already removes all motion when JS withholds it, but
   we ALSO honor the media query directly so a future stylesheet-only load is
   safe, and so any standing/infinite loop is killed for reduced-motion users.
   Numbers always end on their final value (count-up is JS-gated separately).
   =========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .amp-alive-on .amp-alive-pop,
  .amp-alive-on .amp-alive-beat,
  .amp-alive-on .amp-alive-beat--box,
  .amp-alive-on .amp-alive-live-dot,
  .amp-alive-on [data-amp-alive~="breath"]::before,
  .amp-alive-on [data-amp-alive~="sweep"]::after {
    animation: none !important;
    transition: none !important;
    text-shadow: none !important;
    box-shadow: none !important;
    transform: none !important;
  }
  /* The whole-page scroll-to-life cascade is class-driven: every broadened
     candidate (sections, cards, grid children, .amp-stat-row, figure,
     .foot__col, bare <section>) is tagged .amp-alive-reveal, so this single
     rule forces ALL of them fully visible & un-transformed under reduced
     motion — nothing is ever left hidden. */
  .amp-alive-on .amp-alive-reveal {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .amp-alive-on .amp-alive-lift:hover { transform: none !important; }
}

/* ===========================================================================
   7 · LIVE AFFORDANCE — Bloomberg-style "● LIVE" status mark   (ITEM A)
   Reuses the standing .amp-alive-live-dot pulse (§2). Here we only give the
   dot a presentation (inline gold disc) and an in-brand uppercase mono "Live"
   label. Placed on a genuinely live element (the first-cohort countdown).
   GPU-only (opacity/box-shadow from the live-dot keyframe). The label itself
   is static type. At most ONE standing live-dot per viewport (the ticker
   self-signals its own LIVE separately, in a different region).
   =========================================================================== */
.amp-alive-on .rev-countdown-livedot {
  display: inline-block;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--amp-alive-gold);
  vertical-align: middle;
  margin-right: 7px;
  position: relative;
  top: -1px;
}
.rev-countdown-livelbl {
  font-family: 'IBM Plex Mono', monospace;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--amp-alive-gold-hot, #FFD56B);
  margin-right: 8px;
}

/* ===========================================================================
   8 · SIGNATURE DOOR-MOMENT — $40M door gives way to the $1,000 door  (ITEM B)
   The JS adds .amp-door-armed to .rev-problem__metrics the instant the block
   scrolls into view (IntersectionObserver, one-shot, unobserve after firing).
   The choreography is a NARRATIVE HANDOFF, sequenced purely via transition-
   delay (NO new rAF; count-up is the engine's existing rAF):
     t≈0.0s   $40M has just finished counting up (engine) — then RECEDES:
              eases to ~0.5 opacity + subtle desaturate + slight scale-down.
     t≈0.6s   the arrow GLIDES left→right (translateX) and fades in — handoff.
     t≈1.1s   $1,000 ILLUMINATES: scale-settle + a one-time soft gold halo,
              becoming the visual hero. (Its count-up + gentle .beat are the
              engine's; this adds only the one-shot emphasis.)
   Total ≈ 1.9s. GPU-only (opacity / transform / filter / box-shadow). The
   --us hero color (#C9A84C) is already on the element statically, so the
   reduced-motion / no-JS final state is correct with zero motion.
   =========================================================================== */

/* Pre-arm transition channels (only under the motion gate; inert otherwise) */
.amp-alive-on .rev-problem__metric--old {
  transition:
    opacity 760ms var(--amp-alive-ease-io),
    transform 760ms var(--amp-alive-ease-io),
    filter 760ms var(--amp-alive-ease-io);
  will-change: opacity, transform, filter;
}
.amp-alive-on .rev-problem__metric--arrow {
  opacity: 0;
  transform: translateX(-14px);
  transition:
    opacity 620ms var(--amp-alive-ease) 600ms,
    transform 620ms var(--amp-alive-ease) 600ms;
  will-change: opacity, transform;
}
.amp-alive-on .rev-problem__metric--us {
  transition:
    transform 700ms var(--amp-alive-ease-io) 1100ms,
    box-shadow 700ms var(--amp-alive-ease-io) 1100ms;
  will-change: transform, box-shadow;
}

/* Armed state — the handoff plays */
.amp-alive-on .rev-problem__metrics.amp-door-armed .rev-problem__metric--old {
  opacity: 0.5;
  transform: scale(0.965);
  filter: saturate(0.55);
}
.amp-alive-on .rev-problem__metrics.amp-door-armed .rev-problem__metric--arrow {
  opacity: 1;
  transform: translateX(0);
}
.amp-alive-on .rev-problem__metrics.amp-door-armed .rev-problem__metric--us {
  transform: scale(1.035);
  box-shadow: 0 0 0 1px rgba(201,168,76,0.34), 0 14px 42px rgba(201,168,76,0.18);
}
/* one-time gold halo settle on the hero, fired alongside the arm (no loop) */
.amp-alive-on .rev-problem__metrics.amp-door-armed .rev-problem__metric--us.amp-door-illuminate {
  animation: amp-door-illuminate 1500ms var(--amp-alive-ease-io) 1100ms 1;
}
@keyframes amp-door-illuminate {
  0%   { box-shadow: 0 0 0 1px rgba(201,168,76,0.34), 0 0   0    rgba(201,168,76,0);    }
  45%  { box-shadow: 0 0 0 1px rgba(201,168,76,0.55), 0 0  30px rgba(201,168,76,0.34); }
  100% { box-shadow: 0 0 0 1px rgba(201,168,76,0.34), 0 14px 42px rgba(201,168,76,0.18); }
}

/* ===========================================================================
   9 · REDUCED-MOTION HARD STOP for ITEM A + ITEM B (belt-and-suspenders)
   Neutralizes every new animation/transition added above. Final state:
   both metrics fully visible, arrow visible & in place, $1,000 gold-emphasized
   via its existing static color — NO motion.
   =========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .amp-alive-on .rev-countdown-livedot {
    animation: none !important;
    box-shadow: none !important;
    opacity: 1 !important;
  }
  .amp-alive-on .rev-problem__metric--old,
  .amp-alive-on .rev-problem__metric--arrow,
  .amp-alive-on .rev-problem__metric--us,
  .amp-alive-on .rev-problem__metrics.amp-door-armed .rev-problem__metric--old,
  .amp-alive-on .rev-problem__metrics.amp-door-armed .rev-problem__metric--arrow,
  .amp-alive-on .rev-problem__metrics.amp-door-armed .rev-problem__metric--us,
  .amp-alive-on .rev-problem__metrics.amp-door-armed .rev-problem__metric--us.amp-door-illuminate {
    animation: none !important;
    transition: none !important;
    transform: none !important;
    opacity: 1 !important;
    filter: none !important;
    box-shadow: none !important;
  }
}
