/* FVA70K Studio showcase animation system.
   Public pages only: this file is linked from index, studio, and docs pages
   only, and every rule is scoped under body.fva-public. Portal pages never
   load it and are untouched, so the builder portal interior stays clean.
   Animated properties are transform and opacity only. Nothing here moves
   layout, and nothing here hides content when JavaScript is absent: the
   reveal hidden state only applies once the script adds the fva-js class. */

/* Scroll progress bar (studio and docs pages; JavaScript sets scaleX). */
body.fva-public .fva-progress { position: fixed; top: 0; left: 0; right: 0; height: 3px; z-index: 9999; pointer-events: none; }
body.fva-public .fva-progress i { display: block; height: 100%; width: 100%; background: linear-gradient(90deg, #4ade80, #C9A06B); transform-origin: left center; transform: scaleX(0); animation: fva-progglow 2.4s ease-in-out infinite alternate; }
@keyframes fva-progglow { from { opacity: 0.85; } to { opacity: 1; } }

/* Emerald to gold accent bar. The inner strip is twice as wide as the bar
   and slides with transform only, so the gradient appears to flow. */
body.fva-public .fva-accent { width: 120px; height: 3px; border-radius: 99px; overflow: hidden; margin: 0 0 20px; }
body.fva-public .fva-accent i { display: block; width: 200%; height: 100%; background: linear-gradient(90deg, #4ade80, #C9A06B, #4ade80); animation: fva-pan 3s linear infinite; }
@keyframes fva-pan { from { transform: translateX(0); } to { transform: translateX(-50%); } }

/* Landing hero glow. Static radial gradient, animated with transform and
   opacity only, contained inside the hero so it can never overflow. */
body.fva-landing .wrap { position: relative; overflow: hidden; }
body.fva-landing .fva-hero-glow { position: absolute; left: 50%; top: 50%; width: min(560px, 90vw); height: min(560px, 90vw); border-radius: 50%; background: radial-gradient(circle at 35% 35%, rgba(74, 222, 128, 0.28), rgba(201, 160, 107, 0.16) 45%, transparent 70%); pointer-events: none; z-index: 0; animation: fva-drift 12s ease-in-out infinite alternate; }
/* Second hero glow, gold-led and drifting the other way, so the hero
   always has two layers of motion crossing each other. Same rules as the
   first: static gradient, transform and opacity only, clipped by .wrap. */
body.fva-landing .fva-hero-glow2 { position: absolute; left: 62%; top: 28%; width: min(420px, 80vw); height: min(420px, 80vw); border-radius: 50%; background: radial-gradient(circle at 65% 65%, rgba(201, 160, 107, 0.22), rgba(74, 222, 128, 0.12) 45%, transparent 70%); pointer-events: none; z-index: 0; animation: fva-drift2 15s ease-in-out infinite alternate; }
body.fva-landing .wrap > :not(.fva-hero-glow):not(.fva-hero-glow2) { position: relative; z-index: 1; }
@keyframes fva-drift { from { transform: translate(-50%, -50%) scale(1); opacity: 0.7; } to { transform: translate(-42%, -58%) scale(1.25); opacity: 1; } }
@keyframes fva-drift2 { from { transform: translate(-50%, -50%) scale(1); opacity: 0.6; } to { transform: translate(-58%, -42%) scale(1.2); opacity: 0.95; } }

/* Kinetic headline words (created by JavaScript on the landing hero only).
   Without JavaScript no spans exist and the headline renders plain. */
body.fva-public .fva-word { display: inline-block; animation: fva-rise 0.6s cubic-bezier(0.22, 1.2, 0.36, 1) both; }
/* After the entrance rise finishes, the green brand words keep breathing
   gently, so the hero never sits still. The class is added by JavaScript
   on animationend, which replaces the finished rise with the pulse, so
   the two never fight over the same transform. The pulse widens only
   (scaleX) and shimmers opacity: it never grows vertically, so a wrapped
   headline on a narrow phone can never overlap its own next line. */
body.fva-public .fva-word.fva-live { animation: fva-wordpulse 3.2s ease-in-out infinite alternate; }
@keyframes fva-wordpulse { from { transform: scaleX(1); opacity: 1; } to { transform: scaleX(1.03); opacity: 0.94; } }
@keyframes fva-rise { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: translateY(0); } }

/* Scroll reveals. The hidden state only applies once JavaScript adds the
   fva-js class to <html>, so content is never hidden without JavaScript.
   Stagger delays arrive through --fva-d, set by JavaScript, so hover
   transitions on the same elements are never delayed. */
html.fva-js body.fva-public [data-fva-reveal] { opacity: 0; transform: translateY(24px) scale(0.98); transition: opacity 0.6s ease var(--fva-d, 0ms), transform 0.6s cubic-bezier(0.22, 1.2, 0.36, 1) var(--fva-d, 0ms); }
html.fva-js body.fva-public [data-fva-reveal].fva-in { opacity: 1; transform: translateY(0) scale(1); }

/* Hover lifts on cards, theme cards, endpoint rows, and landing links. */
body.fva-public .card, body.fva-public .theme-card, body.fva-public .ep, body.fva-public .links a { transition: transform 0.25s ease, opacity 0.25s ease; }
body.fva-public .card:hover, body.fva-public .theme-card:hover, body.fva-public .ep:hover, body.fva-public .links a:hover { transform: translateY(-3px); }
/* Revealed elements need a stronger hover rule, or the reveal transform
   would win and the lift would never show. */
html.fva-js body.fva-public [data-fva-reveal].fva-in.card:hover, html.fva-js body.fva-public [data-fva-reveal].fva-in.theme-card:hover, html.fva-js body.fva-public [data-fva-reveal].fva-in.ep:hover { transform: translateY(-3px); transition: transform 0.25s ease, opacity 0.25s ease; }

/* Cursor-follow glow. JavaScript positions the glow div with transform and
   fades it with opacity; hosts are relative with hidden overflow so the
   glow can never spill past a card or past the viewport. */
body.fva-public .card, body.fva-public .theme-card, body.fva-public .ep, body.fva-public .links a { position: relative; overflow: hidden; }
body.fva-public .fva-glow { position: absolute; left: 0; top: 0; width: 220px; height: 220px; border-radius: 50%; background: radial-gradient(circle, rgba(74, 222, 128, 0.18), rgba(201, 160, 107, 0.12) 40%, transparent 70%); pointer-events: none; opacity: 0; transition: opacity 0.2s ease; }

/* Status message pop on the studio surface, and rising order rows. */
body.fva-public .fva-msg-pop { animation: fva-rise 0.35s ease both; }
body.fva-public .fva-row-in { animation: fva-rise 0.4s ease both; }

/* Docs endpoint counter, derived live from the endpoint rows. The fixed
   minimum width keeps the line stable while the number counts up. */
body.fva-public .fva-stat { color: #9ca3af; font-size: 14px; margin-bottom: 24px; }
body.fva-public .fva-stat b { color: #4ade80; font-size: 20px; display: inline-block; min-width: 2ch; }
/* Counter finish pop: a quick scale bounce when the count lands. */
body.fva-public .fva-count-done { animation: fva-pop 0.35s ease; }
@keyframes fva-pop { 0% { transform: scale(1); } 50% { transform: scale(1.18); } 100% { transform: scale(1); } }

/* Docs note contrast: the page's own note grey is below the readable
   threshold on the dark background, so the animated docs page lifts it to
   the same muted grey used everywhere else. Content is unchanged. */
body.fva-docs .note { color: #9ca3af; }

/* Docs to build call to action. */
body.fva-public .fva-cta { margin-top: 24px; color: #9ca3af; font-size: 15px; }
body.fva-public .fva-cta a { color: #4ade80; font-weight: 700; }

/* Reduced motion: everything static and fully visible. Every showcase
   animation is listed here, so no new motion can slip past this block. */
@media (prefers-reduced-motion: reduce) {
  body.fva-public .fva-accent i, body.fva-public .fva-word, body.fva-public .fva-word.fva-live, body.fva-public .fva-progress i, body.fva-public .fva-count-done { animation: none !important; }
  body.fva-public .fva-hero-glow, body.fva-public .fva-hero-glow2, body.fva-public .fva-glow { display: none !important; }
  html.fva-js body.fva-public [data-fva-reveal] { opacity: 1 !important; transform: none !important; transition: none !important; }
  body.fva-public .card, body.fva-public .theme-card, body.fva-public .ep, body.fva-public .links a { transition: none !important; }
  body.fva-public .fva-msg-pop, body.fva-public .fva-row-in { animation: none !important; }
}
