/* Entrance animation for marketing mockups. Self-contained — remove this file
   + the matching <link>/<script> includes to revert.

   Applies to any element with [data-anim-mock]. JS adds .is-prepped on init
   (after capturing initial state) so hidden state never paints before JS is
   ready. JS then adds .in-view when the region scrolls into view, triggering
   the keyframes + transitions.

   Per-item stagger uses --anim-i (0-based child index) set by JS, multiplied
   by --anim-step (default 70ms). */

[data-anim-mock] {
  --anim-step: 70ms;
  --mock-ease-out: cubic-bezier(.22,1,.36,1);
  --mock-ease-soft: cubic-bezier(.25,1,.5,1);
}

/* Root entry — applies to the [data-anim-mock] element itself. Variants 1–5
   are assigned in document order by JS (data-anim-variant) so adjacent mocks
   don't share motion. Keyframe-based to avoid the same-frame race between
   is-prepped and in-view. */
[data-anim-mock].is-prepped {
  opacity: 0;
}
[data-anim-mock].in-view {
  animation: mockRise 700ms var(--mock-ease-out) forwards;
}
[data-anim-mock][data-anim-variant="1"].in-view {
  animation: mockRise 700ms var(--mock-ease-out) forwards;
}
[data-anim-mock][data-anim-variant="2"].in-view {
  animation: mockSlideInLeft 750ms var(--mock-ease-out) forwards;
}
[data-anim-mock][data-anim-variant="3"].in-view {
  animation: mockSlideInRight 750ms var(--mock-ease-out) forwards;
}
[data-anim-mock][data-anim-variant="4"].in-view {
  animation: mockZoomIn 650ms var(--mock-ease-soft) forwards;
}
[data-anim-mock][data-anim-variant="5"].in-view {
  animation: mockClipReveal 850ms var(--mock-ease-out) forwards;
}

@keyframes mockRise {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes mockSlideInLeft {
  from { opacity: 0; transform: translateX(-26px); }
  to   { opacity: 1; transform: translateX(0); }
}
@keyframes mockSlideInRight {
  from { opacity: 0; transform: translateX(26px); }
  to   { opacity: 1; transform: translateX(0); }
}
@keyframes mockZoomIn {
  from { opacity: 0; transform: scale(.9); }
  to   { opacity: 1; transform: scale(1); }
}
@keyframes mockClipReveal {
  from { opacity: 0; clip-path: inset(0 50% 0 50%); }
  to   { opacity: 1; clip-path: inset(0 0 0 0); }
}

/* ---- Initial hidden state (only after JS-prepped, prevents pre-script FOUC) ---- */
[data-anim-mock].is-prepped .m-kpi__value,
[data-anim-mock].is-prepped .m-delta,
[data-anim-mock].is-prepped .m-row__val,
[data-anim-mock].is-prepped .m-float,
[data-anim-mock].is-prepped .m-chip,
[data-anim-mock].is-prepped .m-score,
[data-anim-mock].is-prepped .m-rk,
[data-anim-mock].is-prepped .m-stat,
[data-anim-mock].is-prepped .m-net,
[data-anim-mock].is-prepped [data-anim-stagger] {
  opacity: 0;
  will-change: opacity, transform;
}

[data-anim-mock].is-prepped .m-bar > span,
[data-anim-mock].is-prepped .m-vol > span,
[data-anim-mock].is-prepped .m-clip__wave span {
  transition: width 900ms var(--mock-ease-out),
              height 700ms var(--mock-ease-out);
}

[data-anim-mock].is-prepped .m-spark path {
  transition: stroke-dashoffset 1100ms var(--mock-ease-out);
}

/* ---- In-view triggers ---- */
[data-anim-mock].in-view .m-kpi__value { animation: mockFade 450ms 50ms forwards; }
[data-anim-mock].in-view .m-delta      { animation: mockSlideUp 500ms 850ms forwards; }
[data-anim-mock].in-view .m-row__val   { animation: mockFade 500ms 750ms forwards; }
[data-anim-mock].in-view .m-float.a,
[data-anim-mock].in-view .m-float--a   { animation: mockPop 600ms 1150ms var(--mock-ease-soft) forwards; }
[data-anim-mock].in-view .m-float.b,
[data-anim-mock].in-view .m-float--b   { animation: mockPop 600ms 1500ms var(--mock-ease-soft) forwards; }

[data-anim-mock].in-view .m-chip,
[data-anim-mock].in-view .m-score,
[data-anim-mock].in-view .m-rk,
[data-anim-mock].in-view .m-stat {
  animation: mockPop 500ms var(--mock-ease-soft) forwards;
  animation-delay: calc(400ms + var(--anim-i, 0) * var(--anim-step));
}

[data-anim-mock].in-view [data-anim-stagger] {
  animation: mockSlideUp 480ms var(--mock-ease-out) forwards;
  animation-delay: calc(200ms + var(--anim-i, 0) * var(--anim-step));
}

/* Per-variant stagger so list children echo the parent's motion vocabulary. */
[data-anim-mock][data-anim-variant="2"].in-view [data-anim-stagger] {
  animation: mockSlideInSmallLeft 460ms var(--mock-ease-out) forwards;
  animation-delay: calc(200ms + var(--anim-i, 0) * var(--anim-step));
}
[data-anim-mock][data-anim-variant="3"].in-view [data-anim-stagger] {
  animation: mockSlideInSmallRight 460ms var(--mock-ease-out) forwards;
  animation-delay: calc(200ms + var(--anim-i, 0) * var(--anim-step));
}
[data-anim-mock][data-anim-variant="4"].in-view [data-anim-stagger] {
  animation: mockPop 460ms var(--mock-ease-soft) forwards;
  animation-delay: calc(200ms + var(--anim-i, 0) * var(--anim-step));
}
[data-anim-mock][data-anim-variant="5"].in-view [data-anim-stagger] {
  animation: mockTypeIn 540ms var(--mock-ease-out) forwards;
  animation-delay: calc(200ms + var(--anim-i, 0) * var(--anim-step));
}
@keyframes mockSlideInSmallLeft {
  from { opacity: 0; transform: translateX(-12px); }
  to   { opacity: 1; transform: translateX(0); }
}
@keyframes mockSlideInSmallRight {
  from { opacity: 0; transform: translateX(12px); }
  to   { opacity: 1; transform: translateX(0); }
}
@keyframes mockTypeIn {
  from { opacity: 0; clip-path: inset(0 100% 0 0); }
  to   { opacity: 1; clip-path: inset(0 0 0 0); }
}

@keyframes mockFade {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes mockSlideUp {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes mockPop {
  from { opacity: 0; transform: scale(.85) translateY(6px); }
  to   { opacity: 1; transform: scale(1) translateY(0); }
}

/* ---- Extra entry anims for less-common primitives ---- */
[data-anim-mock].is-prepped .m-av,
[data-anim-mock].is-prepped .m-head__meta,
[data-anim-mock].is-prepped .m-item__title,
[data-anim-mock].is-prepped .m-row__label {
  opacity: 0;
  will-change: opacity, transform;
}
[data-anim-mock].in-view .m-av {
  animation: mockPop 500ms var(--mock-ease-soft) forwards;
  animation-delay: calc(300ms + var(--anim-i, 0) * var(--anim-step));
}
[data-anim-mock].in-view .m-head__meta { animation: mockFade 500ms 350ms forwards; }
[data-anim-mock].in-view .m-row__label { animation: mockFade 450ms 250ms forwards; }
[data-anim-mock].in-view .m-item__title { animation: mockSlideUp 500ms 400ms forwards; }

/* ---- Continuous accents (after entry) ---- */

/* Live dot — radial ping. Used by .m-net--live (pseudo dot) and any .live-dot. */
[data-anim-mock] .m-net--live::before,
[data-anim-mock] .live-dot {
  animation: livePulse 1.8s ease-in-out infinite;
}
@keyframes livePulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(22,163,74,.55); transform: scale(1); }
  50%      { box-shadow: 0 0 0 6px rgba(22,163,74,0);  transform: scale(1.18); }
}

/* Bar shimmer — single sweep after fill, low-key, doesn't loop forever. */
[data-anim-mock] .m-bar > span { position: relative; }
[data-anim-mock].in-view .m-bar > span::after {
  content: "";
  position: absolute; top: 0; bottom: 0; left: -45%;
  width: 45%; pointer-events: none;
  background: linear-gradient(90deg, transparent 0%, rgba(255,255,255,.55) 50%, transparent 100%);
  animation: barShimmer 1.6s 1.6s ease-out 2;
}
@keyframes barShimmer {
  to { left: 110%; }
}

/* Float gentle bob after pop-in. */
[data-anim-mock].in-view .m-float.a,
[data-anim-mock].in-view .m-float--a {
  animation: mockPop 600ms 1150ms var(--mock-ease-soft) forwards,
             floatIdle 5s 2400ms ease-in-out infinite;
}
[data-anim-mock].in-view .m-float.b,
[data-anim-mock].in-view .m-float--b {
  animation: mockPop 600ms 1500ms var(--mock-ease-soft) forwards,
             floatIdle 5s 2900ms ease-in-out infinite;
}
@keyframes floatIdle {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-3px); }
}

/* Reel-clip captions — typewriter reveal after the clip stagger lands, then
   the highlighted <em> word blinks like live captioning. */
[data-anim-mock] .m-clip__caption {
  clip-path: inset(0 100% 0 0);
}
[data-anim-mock].in-view .m-clip__caption {
  animation: captionType 1.3s var(--mock-ease-out) forwards;
  animation-delay: calc(900ms + var(--anim-i, 0) * 220ms);
}
@keyframes captionType {
  from { clip-path: inset(0 100% 0 0); }
  to   { clip-path: inset(0 0% 0 0); }
}
[data-anim-mock].in-view .m-clip__caption em {
  animation: captionEmPulse 1.4s ease-in-out 3;
  animation-delay: calc(2400ms + var(--anim-i, 0) * 220ms);
}
@keyframes captionEmPulse {
  0%, 100% { filter: brightness(1); }
  50%      { filter: brightness(1.18); }
}

/* Clip wave gentle reactive bounce after entry — staggered per bar. */
[data-anim-mock] .m-clip__wave span { transform-origin: center bottom; }
[data-anim-mock].in-view .m-clip__wave span {
  animation: waveBounce 1.6s ease-in-out 5;
  animation-delay: calc(2000ms + var(--anim-i, 0) * 80ms);
}
@keyframes waveBounce {
  0%, 100% { transform: scaleY(1); }
  50%      { transform: scaleY(0.7); }
}

/* ---- Real-UI signals: active-row, "You" badge, live timestamp ---- */

[data-anim-mock] .is-anim-active {
  position: relative;
  background: rgba(255,106,1,.055);
  box-shadow: 0 0 0 1px rgba(255,106,1,.16), 0 8px 18px -16px rgba(22,28,45,.32);
  transform: translateY(-1px);
  transition: background 320ms var(--mock-ease-out),
              box-shadow 320ms var(--mock-ease-out),
              transform 320ms var(--mock-ease-out);
}
[data-anim-mock] .m-table tbody tr.is-anim-active td:first-child {
  box-shadow: none;
}
[data-anim-mock] .m-table tbody tr.is-anim-active td {
  background: rgba(255,106,1,.05);
  transition: background 320ms var(--mock-ease-out);
}

[data-anim-mock] .is-seq-target {
  box-shadow: 0 0 0 1px rgba(255,106,1,.2), 0 12px 24px -20px rgba(22,28,45,.42);
}

[data-anim-mock] .is-seq-action {
  transform: translateY(-1px);
  box-shadow: 0 0 0 3px rgba(255,106,1,.12);
  transition: transform 240ms var(--mock-ease-out), box-shadow 240ms var(--mock-ease-out);
}

[data-anim-mock].has-ui-sequence {
  position: relative;
}

[data-anim-mock] .m-ui-status {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  margin-left: 0.6em;
  padding: 0.28em 0.62em;
  border: 1px solid var(--border);
  border-radius: 9999px;
  background: var(--bg-card);
  color: var(--fg3);
  font-family: var(--font-mono);
  font-size: 0.62em;
  font-weight: 700;
  letter-spacing: .04em;
  line-height: 1;
  white-space: nowrap;
  transition: background 260ms var(--mock-ease-out),
              border-color 260ms var(--mock-ease-out),
              color 260ms var(--mock-ease-out);
}

[data-anim-mock] .m-ui-status::before {
  content: "";
  width: 0.55em;
  height: 0.55em;
  border-radius: 50%;
  background: var(--fg4);
  flex: 0 0 auto;
}

[data-anim-mock] .m-ui-status[data-state="working"] {
  background: rgba(255,106,1,.06);
  border-color: rgba(255,106,1,.2);
  color: var(--podseo-dark-orange);
}

[data-anim-mock] .m-ui-status[data-state="working"]::before {
  background: var(--bs-primary);
  box-shadow: 0 0 0 3px rgba(255,106,1,.12);
}

[data-anim-mock] .m-ui-status[data-state="done"] {
  background: #ECFDF5;
  border-color: #A7F3D0;
  color: #047857;
}

[data-anim-mock] .m-ui-status[data-state="done"]::before {
  background: #16a34a;
}

[data-anim-mock] .m-ui-cursor {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 8;
  width: 0.72em;
  height: 0.72em;
  border-radius: 9999px;
  background: var(--fg1);
  box-shadow: 0 4px 12px -6px rgba(22,28,45,.5);
  opacity: 0;
  pointer-events: none;
  transform: translate3d(var(--cursor-x, 0), var(--cursor-y, 0), 0) scale(.92);
  transition: opacity 220ms var(--mock-ease-out),
              transform 620ms var(--mock-ease-out);
}

[data-anim-mock].is-cursor-visible .m-ui-cursor {
  opacity: .86;
  transform: translate3d(var(--cursor-x, 0), var(--cursor-y, 0), 0) scale(1);
}

[data-anim-mock] .m-ui-cursor::after {
  content: "";
  position: absolute;
  inset: -0.42em;
  border: 1px solid rgba(255,106,1,.28);
  border-radius: 9999px;
  background: rgba(255,106,1,.1);
  opacity: 0;
  transform: scale(.6);
}

[data-anim-mock].is-seq-click .m-ui-cursor::after {
  animation: cursorTap 520ms var(--mock-ease-out);
}

@keyframes cursorTap {
  0%   { opacity: 0; transform: scale(.55); }
  35%  { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(1.35); }
}

[data-anim-mock] .m-ui-toast {
  position: absolute;
  right: 1em;
  bottom: 1em;
  z-index: 9;
  display: inline-flex;
  align-items: center;
  gap: 0.55em;
  max-width: min(20em, calc(100% - 2em));
  padding: 0.6em 0.78em;
  border: 1px solid rgba(22,163,74,.18);
  border-radius: 0.7em;
  background: var(--bg-card);
  color: var(--fg1);
  box-shadow: 0 18px 32px -24px rgba(22,28,45,.42);
  font-size: 0.78em;
  font-weight: 700;
  line-height: 1.2;
  opacity: 0;
  pointer-events: none;
  transform: translateY(8px) scale(.98);
  transition: opacity 260ms var(--mock-ease-out),
              transform 260ms var(--mock-ease-out);
}

[data-anim-mock] .m-ui-toast::before {
  content: "";
  width: 0.65em;
  height: 0.65em;
  border-radius: 50%;
  background: #16a34a;
  box-shadow: 0 0 0 3px rgba(22,163,74,.1);
  flex: 0 0 auto;
}

[data-anim-mock] .m-ui-toast.is-visible {
  opacity: 1;
  transform: translateY(0) scale(1);
}

[data-anim-mock] .is-self { position: relative; }
[data-anim-mock] .is-self::after {
  content: "You";
  position: absolute; top: 50%; right: 0.7em;
  transform: translateY(-50%);
  font-family: var(--font-mono);
  font-size: 0.58em; font-weight: 800; letter-spacing: .06em;
  background: var(--bs-primary); color: #fff;
  padding: 0.22em 0.5em; border-radius: 9999px;
  pointer-events: none;
  line-height: 1;
}

/* Live stamp appended into .m-head */
[data-anim-mock] .m-head .live-stamp {
  display: inline-flex; align-items: center; gap: 0.45em;
  margin-left: 0.6em;
  font-family: var(--font-mono);
  font-size: 0.62em; font-weight: 700;
  color: var(--fg3);
  letter-spacing: .06em; text-transform: uppercase;
}
[data-anim-mock] .m-head .live-stamp::before {
  content: ""; width: 0.5em; height: 0.5em; border-radius: 50%;
  background: #16a34a;
  animation: livePulse 1.8s ease-in-out infinite;
  flex-shrink: 0;
}
[data-anim-mock] .m-head .live-stamp em {
  font-style: normal;
  color: var(--fg2);
  font-variant-numeric: tabular-nums;
}

/* ---- Subtle continuous accents for illustration mocks (aiflow/discoflow/leak) ---- */

/* Connector arrows between steps breathe to signal flow direction. */
[data-anim-mock].in-view .aiflow__sep svg,
[data-anim-mock].in-view .discoflow__sep svg {
  animation: flowPulse 2.6s ease-in-out infinite;
}
@keyframes flowPulse {
  0%, 100% { opacity: 0.45; transform: translateX(0); }
  50%      { opacity: 1;    transform: translateX(2px); }
}

/* "You" highlight in parsed citation viz — soft accent ring. */
[data-anim-mock].in-view .viz-parse .ln--us {
  animation: usRing 3.4s ease-in-out infinite;
  animation-delay: 1600ms;
}
@keyframes usRing {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255,106,1,0); }
  50%      { box-shadow: 0 0 0 4px rgba(255,106,1,.08); }
}

/* Filled pips in gap matrix — gentle staggered pulse so coverage reads as live. */
[data-anim-mock].in-view .viz-gaps .pip--on {
  animation: pipBreathe 2.8s ease-in-out infinite;
}
[data-anim-mock].in-view .viz-gaps .gr:nth-child(2) .pip--on { animation-delay: 200ms; }
[data-anim-mock].in-view .viz-gaps .gr:nth-child(3) .pip--on { animation-delay: 400ms; }
[data-anim-mock].in-view .viz-gaps .gr:nth-child(4) .pip--on { animation-delay: 600ms; }
@keyframes pipBreathe {
  0%, 100% { opacity: 0.75; }
  50%      { opacity: 1; }
}

/* Dashed "empty" indicators in leak viz get a faint scanner sweep. */
[data-anim-mock].in-view .lv-eps .ep::after,
[data-anim-mock].in-view .lv-meta .row .dash {
  background-image: linear-gradient(90deg, transparent 0%, rgba(255,106,1,.18) 50%, transparent 100%);
  background-size: 60% 100%;
  background-repeat: no-repeat;
  background-position: -60% 0;
  animation: dashSweep 3.4s ease-in-out infinite;
}
[data-anim-mock].in-view .lv-eps .ep:nth-child(2)::after { animation-delay: 350ms; }
[data-anim-mock].in-view .lv-eps .ep:nth-child(3)::after { animation-delay: 700ms; }
[data-anim-mock].in-view .lv-meta .row:nth-child(2) .dash { animation-delay: 400ms; }
[data-anim-mock].in-view .lv-meta .row:nth-child(3) .dash { animation-delay: 800ms; }
@keyframes dashSweep {
  0%   { background-position: -60% 0; }
  60%  { background-position: 160% 0; }
  100% { background-position: 160% 0; }
}

/* Ghost platform tiles in discovery viz get a slow fade-in/out so unreached
   surfaces feel like "coming soon" rather than dead. */
[data-anim-mock].in-view .df-tiers .pl--ghost {
  animation: ghostBreathe 4s ease-in-out infinite;
}
@keyframes ghostBreathe {
  0%, 100% { opacity: 0.4; }
  50%      { opacity: 0.7; }
}

@media (prefers-reduced-motion: reduce) {
  [data-anim-mock].in-view .aiflow__sep svg,
  [data-anim-mock].in-view .discoflow__sep svg,
  [data-anim-mock].in-view .viz-parse .ln--us,
  [data-anim-mock].in-view .viz-gaps .pip--on,
  [data-anim-mock].in-view .lv-eps .ep::after,
  [data-anim-mock].in-view .lv-meta .row .dash,
  [data-anim-mock].in-view .df-tiers .pl--ghost {
    animation: none !important;
  }
  [data-anim-mock].is-prepped { opacity: 1 !important; transform: none !important; animation: none !important; }
  [data-anim-mock].is-prepped .m-kpi__value,
  [data-anim-mock].is-prepped .m-delta,
  [data-anim-mock].is-prepped .m-row__val,
  [data-anim-mock].is-prepped .m-float,
  [data-anim-mock].is-prepped .m-chip,
  [data-anim-mock].is-prepped .m-score,
  [data-anim-mock].is-prepped .m-rk,
  [data-anim-mock].is-prepped .m-stat,
  [data-anim-mock].is-prepped .m-net,
  [data-anim-mock].is-prepped [data-anim-stagger] {
    opacity: 1 !important; animation: none !important;
  }
  [data-anim-mock].is-prepped .m-bar > span,
  [data-anim-mock].is-prepped .m-vol > span,
  [data-anim-mock].is-prepped .m-clip__wave span { transition: none !important; }
  [data-anim-mock].is-prepped .m-spark path { transition: none !important; }
  [data-anim-mock] .m-ui-cursor,
  [data-anim-mock] .m-ui-toast,
  [data-anim-mock] .m-ui-status { animation: none !important; transition: none !important; }
}
