/* shikki.io — hero animation override CSS (W6 of Katagami DSL migration)
 *
 * Site-specific hero animation styles — relocated AS-IS from
 * `css/style.css`. Behavior is BIT-IDENTICAL; only the file path changed.
 *
 * Per `feedback_shikki-io-hero-animation-stays-as-override.md`:
 *   the hero glitch / CRT / scanline / scroll-cue keyframes are
 *   site-specific and STAY as a composition override. KatagamiWebEmit
 *   splices THIS file into the `<head>` of `dist/index.html` next to
 *   the generated styles at the slot resolution time.
 *
 * This file is parallel-artifact: it's NOT loaded by the live
 * `index.html` until W7's final cutover. The live site continues to
 * load the original `css/style.css` which still contains these rules.
 *
 * Surfaces covered:
 *   - .header-logo / .header-logo-img       (sigma-pattern crossfade)
 *   - .hero-terminal.reveal-up              (TV-on frame entrance)
 *   - .hero-terminal.is-glitching           (chromatic-aberration glitch)
 *   - .terminal-logo-intro.{is-appearing|is-bursting|is-disappearing|is-fading-out}
 *   - .terminal-content / .terminal-line    (typing reveal cascade)
 *   - .terminal-line-history                (Enter-echo line growth)
 *   - .terminal-line-cursor / .terminal-input  (in-terminal input)
 *   - .cursor-blink                         (final caret)
 *   - .reveal-up                            (Maya-style staggered entrance)
 *   - .scroll-cue                           (bob + smart-fit redundancy)
 *   - .mobile-splash                        (KatagamiAnimator portrait splash)
 *
 * NOTE on selector ownership: hero CSS uses generic class names like
 * `.reveal-up`, `.terminal-bar`, `.scroll-cue`. These are anchored to
 * the hero subtree by their parent (`.hero-terminal`, `.hero`) — the
 * site's main grid + header chrome don't reuse these names. Safe to
 * extract verbatim.
 */

/* ── Header logo — scroll-triggered crossfade (sigma-analytics pattern) ──
   v1.3 Fix 2 (2026-05-07): the WHOLE `#header-logo` anchor starts at
   opacity: 0 — fresh page load shows NO logo at all in the header. The
   anchor + img both fade in once the user scrolls past the hero
   terminal (controlled by `.is-scrolled` toggled in hero-animation.js
   via IntersectionObserver on `.hero-terminal`). Reduced-motion and the
   sub-481px mobile gate flatten the transition (the mobile header is
   `display:none` already at <=480px per css/style.css). */
/* Selectors: live page emits .header-logo (hand-rolled HTML); DSL emit
   produces <a class="ks-link" id="header-logo" ...> — we target BOTH
   so the fade rule works pre- AND post-W7-cutover. */
.header-logo,
#header-logo {
  /* v1.1.9: header-logo is the flame image only, hidden by default.
     Operator pattern (sigma-analytics): img fades in on scroll once the
     hero-badge leaves the viewport. No text wordmark — logo OR nothing. */
  position: relative;
  display: inline-flex;
  align-items: center;
  height: 48px;
  text-decoration: none;
  line-height: 1;
  /* Reserve width so the nav doesn't reflow when the img fades in. */
  width: 130px;
  /* Fix 2 — anchor starts fully invisible at fresh page load. The
     `.is-scrolled` class (added by initHeaderLogoScrollSwap once the
     hero-terminal scrolls past the header) flips opacity to 1. */
  opacity: 0;
  transition: opacity 0.3s ease-in-out;
  pointer-events: none;
}
.header-logo.is-scrolled,
#header-logo.is-scrolled {
  opacity: 1;
  pointer-events: auto;
}
.header-logo-img {
  display: block;
  height: 48px;
  width: auto;
  /* Fix 2 — img tracks the parent anchor's fade. Keep the slide-in
     transform on the img so the inner motion still composes nicely. */
  opacity: 1;
  transform: translateX(-12px);
  transition:
    transform 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.header-logo.is-scrolled .header-logo-img,
#header-logo.is-scrolled .header-logo-img {
  transform: translateX(0);
}
@media (prefers-reduced-motion: reduce) {
  .header-logo,
  #header-logo,
  .header-logo-img { transition: none; }
}

/* ── Hero terminal — TV-off-on entrance ── */
.terminal-logo-intro.is-appearing {
  animation: anim-hero-logo-in 520ms cubic-bezier(0.4, 0, 0.2, 1) forwards;
}
.terminal-logo-intro.is-bursting {
  /* Stays visible at full size; only filter/transform jitter momentarily.
     Equivalent to gallery cell #5 (CRT degauss). */
  animation: anim-hero-logo-burst 700ms steps(14, end) forwards;
  opacity: 1;
  transform: scale(1);
}
.terminal-logo-intro.is-disappearing {
  /* Pixel-glitch dissolve — gallery cell #7. */
  animation: anim-hero-logo-out 720ms steps(18, end) forwards;
}

/* APPEAR — TV-off reverse seeded by phosphor flash. */
@keyframes anim-hero-logo-in {
  0%   { opacity:0; transform:scale(0); filter:brightness(1) saturate(0) drop-shadow(0 0 0 transparent) }
  10%  { opacity:0.85; transform:scale(0.012); filter:brightness(5) saturate(0) drop-shadow(0 0 12px white) }
  22%  { opacity:1; transform:scaleY(0.025) scaleX(1.12); filter:brightness(3.5) saturate(0.4) drop-shadow(0 0 28px white) }
  35%  { opacity:1; transform:scaleY(0.06) scaleX(1.08); filter:brightness(3) saturate(0.6) drop-shadow(0 0 24px white) }
  55%  { opacity:1; transform:scaleY(0.6) scaleX(1.04); filter:brightness(2.2) saturate(0.9) drop-shadow(0 0 18px white) }
  72%  { opacity:1; transform:scale(1.06); filter:brightness(2.4) saturate(1.1) drop-shadow(0 0 22px white) }
  85%  { opacity:1; transform:scale(1.02); filter:brightness(1.6) saturate(1.1) drop-shadow(0 0 10px var(--purple)) }
  100% { opacity:1; transform:scale(1); filter:brightness(1) saturate(1) drop-shadow(0 0 0 transparent) }
}

/* BURST — CRT degauss-style RGB split + jitter pulse, returns to clean. */
@keyframes anim-hero-logo-burst {
  0%, 100% { transform:translate(0,0) scale(1); filter:hue-rotate(0deg) saturate(1) drop-shadow(0 0 0 transparent) drop-shadow(0 0 0 transparent); opacity:1 }
  10% { transform:translate(-3px,1px) scale(1); filter:hue-rotate(60deg) saturate(1.5) drop-shadow(4px 0 0 #ff5050) drop-shadow(-4px 0 0 #50c8ff) }
  20% { transform:translate(4px,-2px) scale(1); filter:hue-rotate(-30deg) saturate(1.4) drop-shadow(-4px 0 0 #ff5050) drop-shadow(4px 0 0 #50c8ff) }
  30% { transform:translate(-2px,3px) scale(1); filter:hue-rotate(120deg) saturate(1.3) drop-shadow(3px 1px 0 #ff5050) drop-shadow(-3px -1px 0 #50c8ff) }
  45% { transform:translate(3px,0) scale(1); filter:hue-rotate(180deg) brightness(1.4) drop-shadow(-5px 0 0 #ff5050) drop-shadow(5px 0 0 #50c8ff) }
  60% { transform:translate(-4px,-1px) scale(1); filter:hue-rotate(45deg) saturate(0.6) drop-shadow(2px 2px 0 #ff5050) drop-shadow(-2px -2px 0 #50c8ff) }
  80% { transform:translate(0,2px) scale(1); filter:hue-rotate(-90deg) saturate(0.5) }
}

/* DISAPPEAR — pixel-glitch slice dissolve. */
@keyframes anim-hero-logo-out {
  0%   { clip-path:inset(0 0 0 0); transform:translate(0,0); opacity:1; filter:hue-rotate(0deg) }
  12%  { clip-path:inset(0 0 0 0); transform:translate(-4px,2px); filter:hue-rotate(45deg) saturate(1.4); opacity:1 }
  24%  { clip-path:inset(20% 0 30% 0); transform:translate(4px,-2px); filter:hue-rotate(-30deg); opacity:1 }
  36%  { clip-path:inset(40% 60% 30% 0); transform:translate(-3px,1px); filter:hue-rotate(90deg) brightness(1.4); opacity:1 }
  48%  { clip-path:inset(10% 0 70% 30%); transform:translate(3px,-3px); filter:hue-rotate(180deg); opacity:1 }
  60%  { clip-path:inset(50% 20% 30% 50%); transform:translate(-2px,0); filter:hue-rotate(-90deg) saturate(0.5); opacity:1 }
  72%  { clip-path:inset(70% 0 0 80%); transform:translate(0,1px); filter:hue-rotate(270deg) brightness(1.6); opacity:1 }
  84%  { clip-path:inset(85% 50% 0 0); opacity:0.4; transform:translate(2px,0) }
  100% { clip-path:inset(100% 0 0 0); opacity:0; transform:translate(0,0) }
}

/* Hero-terminal frame entrance: TV-off reverse instead of fade-up. */
.hero-terminal.reveal-up { opacity: 0; transform: scale(0); }
.hero-terminal.reveal-up.is-entered {
  animation: anim-hero-frame-on 520ms cubic-bezier(0.4, 0, 0.2, 1) forwards;
  opacity: 1;
  transform: none;
  transition: none;
}
@keyframes anim-hero-frame-on {
  0%   { opacity:0; transform:scale(0); filter:brightness(1) }
  10%  { opacity:0.9; transform:scale(0.012); filter:brightness(4) saturate(0) }
  22%  { opacity:1; transform:scaleY(0.025) scaleX(1.06); filter:brightness(2.5) saturate(0.4) }
  35%  { opacity:1; transform:scaleY(0.06) scaleX(1.04); filter:brightness(2) saturate(0.6) }
  55%  { opacity:1; transform:scaleY(0.6) scaleX(1.02); filter:brightness(1.5) saturate(0.9) }
  72%  { opacity:1; transform:scale(1.03); filter:brightness(1.3) saturate(1.05) }
  100% { opacity:1; transform:scale(1); filter:brightness(1) saturate(1) }
}

.terminal-logo-intro.is-fading-out {
  /* v1.1.25: 90s CRT TV-power-off — vertical squish to a bright scanline,
     then horizontal collapse to a point, then a final fade. No transition;
     this runs as a keyframe so the multi-stage curve is preserved. */
  animation: hero-logo-tv-off 520ms step-end forwards;
  /* step-end ensures the final state holds; the keyframes use cubic-bezier
     easings on each stage internally via discrete percent stops. */
  animation-timing-function: linear;
}
@keyframes hero-logo-tv-off {
  /* Stage 1 — full → thin bright horizontal band (vertical squish + bloom). */
  0% {
    opacity: 1;
    transform: scaleY(1) scaleX(1);
    filter: brightness(1) contrast(1) saturate(1);
  }
  18% {
    opacity: 1;
    transform: scaleY(0.6) scaleX(1.02);
    filter: brightness(1.4) contrast(1.15) saturate(1.2);
  }
  32% {
    opacity: 1;
    transform: scaleY(0.06) scaleX(1.08);
    filter: brightness(2.5) contrast(1.4) saturate(0.6);
  }
  /* Stage 2 — bright scanline holds + slightly widens (CRT bloom). */
  40% {
    opacity: 1;
    transform: scaleY(0.025) scaleX(1.12);
    filter: brightness(3) contrast(1.5) saturate(0.4);
  }
  /* Stage 3 — horizontal collapse to a point (the "phosphor dot"). */
  68% {
    opacity: 1;
    transform: scaleY(0.02) scaleX(0.04);
    filter: brightness(3.5) contrast(1.3) saturate(0.3);
  }
  82% {
    opacity: 1;
    transform: scaleY(0.012) scaleX(0.012);
    filter: brightness(4) contrast(1) saturate(0.2);
  }
  /* Stage 4 — flash white, then vanish. */
  90% {
    opacity: 0.85;
    transform: scale(0.008);
    filter: brightness(5) contrast(0.6) saturate(0);
  }
  100% {
    opacity: 0;
    transform: scale(0);
    filter: brightness(1);
  }
}
@media (prefers-reduced-motion: reduce) {
  .terminal-logo-intro.is-fading-out {
    animation: none;
    opacity: 0;
    transform: scale(0);
    transition: opacity 200ms ease-out;
  }
}

/* ── Hero-terminal glitch (easter-egg) ─────────────────── */
/* v1.1.34: glitch rule needs higher specificity than `.reveal-up.is-entered`
   (which sets `animation: anim-hero-frame-on ...`) — otherwise the entrance
   animation rule wins and the glitch never plays. Match the same triple-class
   selector so the cascade picks the glitch when `.is-glitching` is added. */
.hero-terminal.reveal-up.is-glitching,
.hero-terminal.is-glitching {
  animation: hero-terminal-glitch 0.9s steps(18, end) 1 !important;
}
@keyframes hero-terminal-glitch {
  0%, 100% {
    transform: translate(0, 0);
    filter: none;
  }
  6% {
    transform: translate(-3px, 2px);
    filter: hue-rotate(60deg) saturate(1.4);
    box-shadow:
      -4px 0 0 rgba(255, 80, 80, 0.5),
       4px 0 0 rgba(80, 200, 255, 0.5),
       0 24px 80px rgba(0, 0, 0, 0.5);
  }
  14% {
    transform: translate(3px, -1px) skewX(0.5deg);
    filter: hue-rotate(-30deg) contrast(1.3);
    box-shadow:
      3px -2px 0 rgba(255, 80, 80, 0.45),
     -3px  2px 0 rgba(80, 200, 255, 0.45);
  }
  22% {
    transform: translate(-2px, 0);
    filter: hue-rotate(180deg) saturate(0.7);
    clip-path: polygon(0 0, 100% 0, 100% 28%, 78% 28%, 78% 48%, 100% 48%, 100% 100%, 0 100%);
  }
  30% {
    transform: translate(0, 3px);
    filter: hue-rotate(-90deg);
    clip-path: none;
  }
  38% {
    transform: translate(2px, -2px);
    filter: hue-rotate(45deg) brightness(1.15);
    box-shadow:
      -2px 0 0 rgba(255, 80, 80, 0.6),
       2px 0 0 rgba(80, 200, 255, 0.6);
  }
  46% {
    transform: translate(-3px, 1px) skewX(2deg);
    filter: hue-rotate(0deg) contrast(1.5);
    clip-path: polygon(0 0, 100% 0, 100% 60%, 35% 60%, 35% 80%, 100% 80%, 100% 100%, 0 100%);
  }
  54% {
    transform: translate(0, 0);
    filter: invert(0.08);
    clip-path: none;
  }
  62% {
    transform: translate(2px, 0);
    filter: hue-rotate(120deg);
    box-shadow:
       5px 0 0 rgba(255, 80, 80, 0.4),
      -5px 0 0 rgba(80, 200, 255, 0.4);
  }
  70% {
    transform: translate(-1px, -2px) skewY(0.5deg);
    filter: hue-rotate(0deg) saturate(1.3);
  }
  78% {
    transform: translate(0, 1px);
    filter: contrast(1.4);
    clip-path: polygon(0 0, 100% 0, 100% 70%, 60% 70%, 60% 90%, 100% 90%, 100% 100%, 0 100%);
  }
  86% {
    transform: translate(1px, 0);
    filter: none;
    clip-path: none;
  }
  94% {
    transform: translate(0, -1px);
    filter: hue-rotate(20deg);
  }
}
@media (prefers-reduced-motion: reduce) {
  .hero-terminal.is-glitching { animation: none; }
}

/* ── Terminal content reveal cascade (typing + line-in) ── */
.terminal-content.is-revealed .terminal-line.typed {
  opacity: 1;
  clip-path: inset(0 100% 0 0);
  animation: typing-line var(--typing-dur, 1.5s) steps(var(--chars, 36), end) forwards;
}
@keyframes typing-line {
  from { clip-path: inset(0 100% 0 0); }
  to   { clip-path: inset(0 0 0 0); }
}
.terminal-content.is-revealed .terminal-line {
  opacity: 0;
  animation: terminal-line-in 480ms ease-out forwards;
}
/* v1.1.38: typing slowed (operator: "a little too fast" + fade also).
   Typing 600/650/1000 → 950/1000/1500. Fade 320 → 480. Cadence between
   line starts kept at 220ms ("timing between each line is good"). */
.terminal-content.is-revealed .terminal-line:nth-child(1)  { animation-delay:   80ms; } /* $ spawn TYPED 950 → 1030 */
.terminal-content.is-revealed .terminal-line:nth-child(2)  { animation-delay: 1130ms; } /* +100 breath; ▸ agent-0 → 1610 */
.terminal-content.is-revealed .terminal-line:nth-child(3)  { animation-delay: 1350ms; } /* ▸ agent-1 → 1830 */
.terminal-content.is-revealed .terminal-line:nth-child(4)  { animation-delay: 1570ms; } /* ▸ agent-2 → 2050 */
.terminal-content.is-revealed .terminal-line:nth-child(5)  { animation-delay: 1790ms; } /* ✓ mesh ready → 2270 */
.terminal-content.is-revealed .terminal-line:nth-child(6)  { animation-delay: 2470ms; } /* +200 group gap; $ dispatch TYPED 1000 → 3470 */
.terminal-content.is-revealed .terminal-line:nth-child(7)  { animation-delay: 3570ms; } /* +100 breath; ▸ dispatching 0 → 4050 */
.terminal-content.is-revealed .terminal-line:nth-child(8)  { animation-delay: 3790ms; } /* ▸ dispatching 1 → 4270 */
.terminal-content.is-revealed .terminal-line:nth-child(9)  { animation-delay: 4010ms; } /* ▸ dispatching 2 → 4490 */
.terminal-content.is-revealed .terminal-line:nth-child(10) { animation-delay: 4230ms; } /* ✓ task completed → 4710 */
.terminal-content.is-revealed .terminal-line:nth-child(11) { animation-delay: 4450ms; } /* ▸ shikki idle → 4930 */
.terminal-content.is-revealed .terminal-line:nth-child(12) { animation-delay: 4670ms; } /* (blank) → 5150 */
.terminal-content.is-revealed .terminal-line:nth-child(13) { animation-delay: 5250ms; } /* +100 breath; $ install TYPED 1500 → 6750 */
.terminal-content.is-revealed .terminal-line:nth-child(14) { animation-delay: 6850ms; } /* +100 breath; cursor → 7330 */

@keyframes terminal-line-in {
  from { opacity: 0; transform: translateY(2px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ── Echo-line growth (in-terminal Enter handler) ── */
.terminal-line-history {
  opacity: 0;
  max-height: 0;
  overflow: hidden;
  transform: translateY(2px);
  transition:
    max-height 0.32s ease-out,
    opacity 0.32s ease-out 0.08s,
    transform 0.32s ease-out 0.08s;
}
.terminal-line-history.is-entered {
  opacity: 1;
  max-height: 1.6em;
  transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
  .terminal-line-history { transition: none; }
}

/* ── Cursor blink + typed-mode short-circuit ── */
.cursor-blink {
  display: inline-block;
  width: 0.55em;
  height: 1em;
  background: var(--green);
  vertical-align: text-bottom;
  margin-left: 0.15em;
  animation: cursor-blink-keys 0.9s step-end infinite;
}
@keyframes cursor-blink-keys {
  0%, 50%   { opacity: 1; }
  51%, 100% { opacity: 0; }
}
.terminal-line-cursor.is-typed {
  opacity: 1 !important;
  animation: none !important;
  transform: none !important;
}

/* ── Maya-style staggered entrance ── */
.reveal-up {
  opacity: 0;
  transform: translateY(20px);
  transition:
    opacity 0.55s ease-out,
    transform 0.55s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity, transform;
}
.reveal-up.is-entered {
  opacity: 1;
  transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
  .reveal-up {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* ── Scroll cue (bob + smart-fit + on-screen gate) ── */
.scroll-cue.is-hidden {
  opacity: 0;
  pointer-events: none;
  transition: opacity 300ms ease-out;
}
.scroll-cue.is-redundant {
  display: none !important;
}
@media (prefers-reduced-motion: reduce) {
  .scroll-cue { transition: none; }
}
.scroll-cue.is-revealed { opacity: 0.7; }
.scroll-cue.is-revealed.is-onscreen { animation-play-state: running; }
@keyframes scroll-cue-bob {
  /* v1.1.39: keep translateX(-50%) for absolute centering; bob composes Y. */
  0%, 100% { transform: translateX(-50%) translateY(0); }
  50%      { transform: translateX(-50%) translateY(6px); }
}

/* ── a11y — reduced motion bypasses intro + bob ── */
@media (prefers-reduced-motion: reduce) {
  .terminal-logo-intro { display: none; }
  .terminal-content[hidden] { display: block !important; }
  .terminal-content .terminal-line {
    opacity: 1 !important;
    animation: none !important;
  }
  /* v1.3 Fix 2 — reduced-motion still hides the header logo at fresh
     page load (visibility = "logo invisible until past first section"
     is a content rule, not a motion rule). The is-scrolled state still
     flips it to opaque without the transition. */
  .header-logo {
    transition: none;
  }
  .header-logo-img {
    transform: translateX(0);
    transition: none;
  }
  .scroll-cue { animation: none; }
  .terminal-line.typing { animation: none; width: auto; border-right: none; }
}

/* ── v1.3 Fix 4 — progressive hero-portrait animation ──
   Replaces the full-screen mobile-splash overlay. The portrait video
   is mounted INLINE by hero-animation.js into the
   [data-slot="hero-portrait-anim"] marker. Mobile-only; desktop hides
   the slot via initHeroPortraitAnim's display:none short-circuit. */
[data-slot="hero-portrait-anim"] {
  display: block;
  width: 100%;
  margin: 0 auto 1.25rem;
  text-align: center;
  /* Desktop default — JS swaps display:none for >480px viewports.
     CSS gate also applies a hard cap below to survive JS-disabled
     visitors. */
}
@media (min-width: 481px) {
  [data-slot="hero-portrait-anim"] { display: none; }
}
.hero-portrait-video,
.hero-portrait-still {
  display: block;
  margin: 0 auto;
  width: 100%;
  max-width: 320px;
  height: auto;
  border-radius: var(--radius, 12px);
  background: transparent;
  user-select: none;
  -webkit-user-drag: none;
}

/* ── v1.3 Fix 6 — App-Store-style download CTA chip ──
   `#hero-download-cta` is the secondary inline button next to
   `#hero-cta`. Visual: dark fill with accent-primary outline glow,
   pill-radius, an Apple-symbol leading hint, two-line label.
   Replaces the previous .mobile-cta-app + #mobile-beta-cta pair. */
#hero-download-cta {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-family: var(--mono, ui-monospace, monospace);
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--fg, #f8f8f2);
  background: linear-gradient(180deg, #1f2230 0%, #14161e 100%);
  border: 1px solid var(--purple, #bd93f9);
  padding: 0.65rem 1.1rem 0.65rem 0.9rem;
  border-radius: 999px;
  text-decoration: none;
  box-shadow:
    0 0 0 1px rgba(189, 147, 249, 0.18) inset,
    0 4px 14px rgba(0, 0, 0, 0.35);
  transition:
    box-shadow 0.25s ease-out,
    transform 0.18s ease-out,
    border-color 0.25s ease-out;
}
#hero-download-cta::before {
  /* App-Store-style leading apple glyph. Decorative only. */
  content: "";
  display: inline-block;
  width: 14px;
  height: 14px;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M16.4 1.5c.1 1.6-.5 3-1.5 4.1-1 1.1-2.6 1.9-4.1 1.8-.1-1.5.6-3 1.6-4 1-1 2.6-1.8 4-1.9zM21 17.4c-.6 1.4-1 2-1.7 3.2-1 1.6-2.4 3.6-4.2 3.6-1.5 0-2-.9-4.1-.9s-2.6.9-4.1.9c-1.8.1-3.1-1.7-4.1-3.3-2.7-4.3-3-9.4-1.3-12.1 1.2-1.9 3-3 4.8-3 1.7 0 2.7.9 4.1.9 1.4 0 2.2-.9 4.2-.9 1.5 0 3.1.8 4.2 2.2-3.7 2-3.1 7.3 0 9.4z'/></svg>") no-repeat center / contain;
          mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M16.4 1.5c.1 1.6-.5 3-1.5 4.1-1 1.1-2.6 1.9-4.1 1.8-.1-1.5.6-3 1.6-4 1-1 2.6-1.8 4-1.9zM21 17.4c-.6 1.4-1 2-1.7 3.2-1 1.6-2.4 3.6-4.2 3.6-1.5 0-2-.9-4.1-.9s-2.6.9-4.1.9c-1.8.1-3.1-1.7-4.1-3.3-2.7-4.3-3-9.4-1.3-12.1 1.2-1.9 3-3 4.8-3 1.7 0 2.7.9 4.1.9 1.4 0 2.2-.9 4.2-.9 1.5 0 3.1.8 4.2 2.2-3.7 2-3.1 7.3 0 9.4z'/></svg>") no-repeat center / contain;
}
#hero-download-cta:hover,
#hero-download-cta:focus-visible {
  border-color: var(--green, #50fa7b);
  box-shadow:
    0 0 0 1px rgba(80, 250, 123, 0.32) inset,
    0 6px 20px rgba(0, 0, 0, 0.45),
    0 0 24px rgba(189, 147, 249, 0.35);
  transform: translateY(-1px);
  outline: none;
}
@media (prefers-reduced-motion: reduce) {
  #hero-download-cta { transition: none; }
  #hero-download-cta:hover { transform: none; }
}

/* ── v1.3 Fix 7 — inline hero CTA row ──
   `.hero` lays out badge / h1 / tagline / CTA-row / portrait-anim slot
   / scroll-cue vertically. The CTA-row is an HStack at desktop and
   stacks vertically on mobile (< 481px) so each CTA gets full width. */
.hero .ks-hstack {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  justify-content: center;
  align-items: center;
  margin-bottom: 2.5rem;
}
@media (max-width: 480px) {
  .hero .ks-hstack {
    flex-direction: column;
    width: 100%;
    max-width: 22rem;
  }
  .hero .ks-hstack > * {
    width: 100%;
    text-align: center;
    justify-content: center;
  }
  /* Override the default .hero-cta margin so the CTA row tightens. */
  .hero .ks-hstack #hero-cta { margin-bottom: 0; }
}
