/* Motion uses transforms and opacity only; every rule yields to the global pause and reduced motion. */
@font-face { font-family: Inter; font-style: normal; font-weight: 400 700; font-display: swap; src: url('/assets/site/inter-latin.woff2') format('woff2'); }
@font-face { font-family: 'JetBrains Mono'; font-style: normal; font-weight: 400 600; font-display: swap; src: url('/assets/site/jetbrains-mono-latin.woff2') format('woff2'); }
:root {
  --ease-reveal: cubic-bezier(.22,1,.36,1);
  --ease-swap: cubic-bezier(.645,.045,.355,1);
  --dur-reveal: 640ms;
  --dur-scene: 560ms;
  --dur-micro: 180ms;
  --reveal-shift: 24px;
}
body::before { content: ''; position: fixed; inset: 0; z-index: -1; pointer-events: none; background-image: radial-gradient(circle, color-mix(in srgb, var(--ink) 7%, transparent) 1px, transparent 1px); background-size: 24px 24px; -webkit-mask-image: linear-gradient(black, transparent 70%); mask-image: linear-gradient(black, transparent 70%); }

/* Short, light hovers. */
.button, .text-link, .nav-link, .copy-button, .site-preferences button, .brand-menu > * { transition: background-color var(--dur-micro), border-color var(--dur-micro), color var(--dur-micro), transform var(--dur-micro) var(--ease-reveal); }
.button:hover { transform: translateY(-1px); }
.cap, .sat-card, .sat-usage > div, .stage, .demo-story-media { transition: border-color var(--dur-micro), transform 240ms var(--ease-reveal), box-shadow 320ms var(--ease-reveal); }
.cap:not(.story-card):hover, .sat-card:hover, .sat-usage > div:hover, .stage:hover { transform: translateY(-3px); border-color: var(--hairline); }
.story-card { transition: border-color 320ms, box-shadow 420ms var(--ease-reveal); }
.site-header { transition: background-color 320ms, border-color 320ms; }

/* The pixel b assembles once on load, with the transaction lifecycle colours. */

/* Intro (~1.2 s, every load): the pixel b is built from falling, turning pieces that pass through the
   transaction states, the wordmark drops in behind a pixel mask, then the lockup flies to the header.
   Never with reduced motion; the runtime removes it at once under the global pause. */
@media (prefers-reduced-motion: no-preference) {
  .intro { position: fixed; inset: 0; z-index: 100; display: grid; place-items: center; background: var(--canvas); pointer-events: none; animation: intro-out 300ms ease 1500ms forwards; }
  .intro-lockup { width: min(56vw, 520px); height: auto; overflow: visible; transform-origin: 0 0; }
  .intro-piece { fill: var(--orange); transform-box: fill-box; transform-origin: center; animation: intro-drop 330ms steps(6, end) calc(var(--i) * 60ms) both, intro-mine 400ms linear calc(var(--i) * 60ms) both; }
  .intro-piece--ink { fill: var(--ink); animation-name: intro-drop, intro-mine-ink; }
  .intro-mark { animation: intro-clear 160ms ease 660ms both; }
  .intro-word { fill: var(--ink); }
  .intro-letter { animation: intro-letter 240ms steps(4, end) calc(500ms + var(--i) * 40ms) both; }
  #intro-pixels rect { fill: white; opacity: 0; animation: intro-pixel 1ms steps(1, end) calc(500ms + var(--d)) forwards; }
  .site-header .brand { animation: intro-brand 140ms ease 1500ms both; }
}
@keyframes intro-drop { from { transform: translate(calc(var(--dx) * 100%), -260%) rotate(calc(var(--turns) * 90deg)); } to { transform: none; } }
@keyframes intro-mine { 0% { fill: var(--pending); } 25% { fill: var(--relayed); } 50% { fill: var(--mempool); } 70% { fill: var(--confirming); } 85% { fill: var(--confirmed); } 100% { fill: var(--orange); } }
@keyframes intro-mine-ink { 0% { fill: var(--pending); } 50% { fill: var(--mempool); } 85% { fill: var(--confirmed); } 100% { fill: var(--ink); } }
@keyframes intro-clear { 50% { filter: brightness(1.8) drop-shadow(0 0 .2px var(--orange)); } }
@keyframes intro-letter { from { transform: translateY(-140px); opacity: 0; } 25% { opacity: 1; } to { transform: none; opacity: 1; } }
@keyframes intro-pixel { to { opacity: 1; } }
@keyframes intro-out { 0% { background-color: var(--canvas); } 99% { background-color: transparent; visibility: visible; } 100% { background-color: transparent; visibility: hidden; } }
@keyframes intro-brand { from { opacity: 0; } to { opacity: 1; } }

/* Hero frame: the lean and the light follow the pointer and the loop; the Sat steps in and bobs. */
.hero-app, [data-tilt] { transition: transform 600ms var(--ease-reveal), box-shadow 700ms ease, border-color 700ms ease; }
.hero-sat:not([hidden]) { animation: sat-enter 700ms var(--ease-reveal) 300ms both; }
.hero-sat:not([hidden]) img { animation: sat-bob 3.2s ease-in-out 1s infinite; }
.hero-sat:not([hidden]) .hero-sat-line { animation: sat-say 420ms var(--ease-reveal) 900ms both; }
@keyframes sat-enter { from { opacity: 0; transform: translateY(40px) rotate(-6deg); } to { opacity: 1; transform: none; } }
@keyframes sat-bob { 50% { transform: translateY(-8px) rotate(2deg); } }
@keyframes sat-say { from { opacity: 0; transform: translateY(8px) scale(.92); transform-origin: 0 100%; } to { opacity: 1; transform: none; } }

/* Loops: the poster is visible immediately; the video fades in only once it is playing. */
.loop-video { opacity: 0; transition: opacity 700ms var(--ease-reveal); }
[data-loop-video][data-video="playing"] .loop-video { opacity: 1; }
.view-switch button { transition: background-color var(--dur-micro), color var(--dur-micro); }

/* Sections enter once: 500-700 ms, 20-32 px. Without JavaScript nothing is hidden. */
html.reveal [data-reveal]:not(.is-revealed) { opacity: 0; transform: translateY(var(--reveal-shift)); }
html.reveal [data-reveal] { transition: opacity var(--dur-reveal) var(--ease-reveal) var(--reveal-delay, 0ms), transform var(--dur-reveal) var(--ease-reveal) var(--reveal-delay, 0ms); }

/* Capabilities rail: a quick crossfade between recorded terminals. */
@media (min-width: 1024px) {
  .js .session-panel--sticky { transition: opacity 180ms ease, visibility 180ms; }
  .js .session-panel--sticky figcaption { transform: translateY(6px); transition: transform 220ms var(--ease-reveal); }
  .js .session-panel--sticky[data-active] figcaption { transform: none; }
}
.install-indicator { transition: transform 220ms var(--ease-reveal), width 220ms var(--ease-reveal); }
.copy-button[data-copied="true"] .icon { animation: copy-tick 220ms var(--ease-reveal); }
@keyframes copy-tick { from { transform: scale(.7); } to { transform: scale(1); } }
.hero-cli-cursor { animation: hero-cli-blink 1.25s steps(1) infinite; }
@keyframes hero-cli-blink { 0%, 49% { opacity: 1; } 50%, 100% { opacity: .28; } }
#genesis-dialog[open] .eyebrow::before { animation: block-pulse 1.25s ease 2; }
@keyframes block-pulse { 50% { opacity: .28; } }

/* Global pause (footer control) and the OS preference both stop every animation. */
html[data-motion="paused"] *, html[data-motion="paused"] *::before, html[data-motion="paused"] *::after { animation: none !important; transition: none !important; }
html[data-motion="paused"] [data-reveal] { opacity: 1 !important; transform: none !important; }
html[data-motion="paused"] .intro { display: none; }
html[data-motion="paused"] .button:hover, html[data-motion="paused"] .cap:hover, html[data-motion="paused"] .stage:hover, html[data-motion="paused"] .sat-card:hover, html[data-motion="paused"] .sat-usage > div:hover { transform: none; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation: none !important; transition: none !important; }
  [data-reveal] { opacity: 1 !important; transform: none !important; }
  .loop-video { display: none; }
}
