/* ============================================================================
   Hero v2
   ----------------------------------------------------------------------------
   Loaded after styles.css. Scoped under .hero-v2; the header keeps its .hero
   class so the two scripts that measure its bottom edge - page rails stopping
   there, nav reclaiming its white bar there - keep working untouched.

   What this replaces: a stock night-skyline video under an 80% black scrim,
   with the copy centred on top. Generic, and ~2MB above the fold to say nothing.

   What it does NOT replace it with: a console. The first pass at this hero put
   an animated status panel on the right - pulsing dot, travelling indicator,
   ticking bars - and it looked like every generated "fintech" hero on the
   internet. Looping motion and dashboard chrome are the tell. They are gone.

   The composition now is three moves and no more:
     1. one large left-aligned serif headline in a lot of empty space,
     2. the supporting line and the two CTAs directly under it,
     3. two marks under the buttons, Canton and Litecoin.

   The right half of the frame is empty on purpose. Until 2026-09-29 a hairline
   rail of four facts ran across the bottom and anchored it; the marks replaced
   it, and the headline block now carries the composition on its own.
   ========================================================================== */

.hero-v2 {
  --hv-line:     rgba(255, 255, 255, 0.12);
  --hv-dim:      rgba(255, 255, 255, 0.50);
  min-height: 100svh;
}

/* The base plane: the gradient the old hero already used, warmed slightly at the
   top so there is a light source for the blooms to belong to. */
.hero-v2 .hero__bg {
  background:
    radial-gradient(ellipse 100% 70% at 50% -10%, rgba(255,255,255,0.055) 0%, transparent 60%),
    radial-gradient(ellipse 120% 95% at 50% 28%,
      #3c3c3c 0%, #242424 28%, #181818 58%, #121212 100%);
}

/* --------------------------------------------------------- ambient motion */

/* Three light blooms drifting across the plane. The rules that keep this classy
   rather than decorative:

   - Long cycles. 68s, 83s and 97s, chosen so no two align and the arrangement
     never visibly repeats. Anything under ~20s registers as an animation and
     the eye starts tracking it instead of reading.
   - Transform only. Each is a static gradient moved with translate3d, so this
     stays on the compositor - no paint per frame, no layout, no battery cost.
   - Barely there. Peak alpha 0.075. If you can point at a bloom and say where
     its edge is, it is too strong.
   - Slightly different colour temperatures - one warm, one neutral, one cool.
     That temperature difference is the whole trick: three identical white
     blobs read as CSS, three at different temperatures read as light.

   Deliberately NOT particles, a node graph, a scanline or anything that moves
   in a straight line at constant speed. Those are the generated-hero tells. */
/* No filter: blur() here, deliberately. Each radial gradient already fades to
   fully transparent by ~70% of its radius, so a blur on top changed nothing you
   could see while costing ~2.2 megapixels of blur per frame at 1x - near 9 on a
   2x display, every frame, for three layers. The softness is free in the
   gradient; buying it twice is what makes ambient backgrounds spin laptop fans.
   This way the animation is pure compositor transform work. */
.hero-v2__bloom {
  position: absolute;
  border-radius: 50%;
  will-change: transform;
  pointer-events: none;
}

.hero-v2__bloom--a {
  width: 68vw;
  height: 62vh;
  top: -16vh;
  left: -8vw;
  background: radial-gradient(circle at 50% 50%,
              rgba(255, 248, 235, 0.075) 0%, rgba(255, 248, 235, 0) 68%);
  animation: hv-drift-a 68s ease-in-out infinite alternate;
}

.hero-v2__bloom--b {
  width: 58vw;
  height: 66vh;
  top: 8vh;
  right: -14vw;
  background: radial-gradient(circle at 50% 50%,
              rgba(255, 255, 255, 0.055) 0%, rgba(255, 255, 255, 0) 70%);
  animation: hv-drift-b 83s ease-in-out infinite alternate;
}

.hero-v2__bloom--c {
  width: 76vw;
  height: 54vh;
  bottom: -22vh;
  left: 12vw;
  background: radial-gradient(circle at 50% 50%,
              rgba(226, 236, 255, 0.05) 0%, rgba(226, 236, 255, 0) 72%);
  animation: hv-drift-c 97s ease-in-out infinite alternate;
}

/* Each ends somewhere it did not start and takes a different route there. The
   scale drift is what stops them reading as rigid objects sliding on a plane. */
@keyframes hv-drift-a {
  0%   { transform: translate3d(0, 0, 0) scale(1); }
  50%  { transform: translate3d(9vw, 5vh, 0) scale(1.09); }
  100% { transform: translate3d(3vw, 11vh, 0) scale(1.02); }
}

@keyframes hv-drift-b {
  0%   { transform: translate3d(0, 0, 0) scale(1.04); }
  50%  { transform: translate3d(-11vw, 7vh, 0) scale(1); }
  100% { transform: translate3d(-5vw, -4vh, 0) scale(1.1); }
}

@keyframes hv-drift-c {
  0%   { transform: translate3d(0, 0, 0) scale(1); }
  50%  { transform: translate3d(7vw, -6vh, 0) scale(1.07); }
  100% { transform: translate3d(-6vw, -2vh, 0) scale(1.03); }
}

/* ----------------------------------------------------------- glyph cascade */

/* The mask is what makes this wearable on an institutional page. The cascade is
   at full strength out in the empty right of the frame and falls away to nothing
   before it reaches the headline, so no glyph ever moves behind text. Running it
   edge to edge would be unreadable and would look like a template.

   The layer is dimmed here rather than by drawing dimmer glyphs, because the
   canvas needs its own internal contrast: the leading character is drawn at full
   white with a glow so it stays brighter than the trail behind it. Flattening
   that on the canvas and compensating with opacity loses the falling read. */
.hero-v2__rain {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0.7;
  pointer-events: none;

  /* Two-axis mask, composited. Measured against the real layout rather than
     guessed: the copy block occupies 13.7%-55.1% of the frame, and the spec rail
     sits in the bottom ~12%. So the cascade is allowed the whole right 42% at
     full strength, from just under the nav down to just above the rail, and is
     cut everywhere those two elements actually are.

     The earlier single radial was clear of the type but only lit a narrow band -
     about 0.15% of the frame in painted pixels, which is why it was invisible in
     practice. This opens the safe area up to its real size instead of dimming
     the whole thing to stay out of trouble.

     mask-composite: intersect keeps only where both gradients are opaque;
     -webkit-mask-composite: source-in is the same thing for older WebKit. */
  -webkit-mask-image:
    linear-gradient(to right, transparent 0 58%, rgba(0,0,0,0.25) 66%,
                    rgba(0,0,0,0.72) 76%, #000 84%, #000 100%),
    linear-gradient(to bottom, transparent 0, #000 7%, #000 78%, transparent 88%);
  -webkit-mask-composite: source-in;
  mask-image:
    linear-gradient(to right, transparent 0 58%, rgba(0,0,0,0.25) 66%,
                    rgba(0,0,0,0.72) 76%, #000 84%, #000 100%),
    linear-gradient(to bottom, transparent 0, #000 7%, #000 78%, transparent 88%);
  mask-composite: intersect;
}

/* Stacked, there is no empty side to put the cascade in - it would sit directly
   under the headline, which is the one thing the mask exists to prevent. */
@media (max-width: 900px) {
  .hero-v2__rain { display: none; }
}

/* Fractal noise at 3%. Flat dark fills read as a screen; the same fill under
   grain reads as a surface, and it also breaks up the banding that large soft
   gradients show on 8-bit panels. The position shuffle is slow and tiny - just
   enough that the texture is alive rather than printed on. */
.hero-v2__grain {
  position: absolute;
  inset: -100px;
  opacity: 0.032;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: hv-grain 6s steps(4) infinite;
}

@keyframes hv-grain {
  0%   { transform: translate3d(0, 0, 0); }
  25%  { transform: translate3d(-3px, 2px, 0); }
  50%  { transform: translate3d(2px, -3px, 0); }
  75%  { transform: translate3d(-2px, -2px, 0); }
  100% { transform: translate3d(0, 0, 0); }
}

/* ------------------------------------------------------------------ layout */

.hero-v2 .hero__main {
  align-items: center;
  justify-content: flex-start;
  padding-top: calc(var(--nav-h) + clamp(24px, 5vh, 56px));
  padding-bottom: clamp(40px, 6vh, 72px);
}

.hero-v2 .hero__copy {
  max-width: 100%;
  text-align: left;
}

/* Breaks after "engines" on tablet and up, so the two lines stay close in length. */
.hero-v2 .hero__title {
  font-size: var(--fs-display);
  line-height: 1.06;
  letter-spacing: -0.032em;
  max-width: 34ch;
}

.hero-v2 .hero__ctas {
  justify-content: flex-start;
  margin-top: clamp(28px, 3vw, 40px);
}

/* --------------------------------------------------------------- logo row */

/* 2026-09-29 [Matias]: two marks under the buttons, Canton and Litecoin. They
   replace the four fact spec rail that ran across the foot of the hero, and
   index.astro records what that took off the page.

   They went into that rail first, hairline above and a rule between, and sat
   there awkwardly: at the foot of the frame they read as a footer, not as part of
   the pitch. Under the buttons they belong to the headline. No hairline and no
   rule here, deliberately; the spacing alone groups them, as it did for the 25
   September row this position is borrowed from. */
.hero-v2__marks {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  column-gap: clamp(36px, 5vw, 64px);
  row-gap: 22px;
  margin-top: clamp(40px, 5vw, 64px);
}

.hero-v2__marks dl { margin: 0; }

.hero-v2__marks dt {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--hv-dim);
}

.hero-v2__marks dd { margin: 12px 0 0; }

/* One height for both. The two lockups are the same shape, a round symbol beside
   a one line wordmark, so equal heights read as equal weight. 29px is also the
   floor: any lower and the Litecoin mark drops under the 100px width its
   guidelines set for screens. Never recoloured or filtered, see index.astro. */
.hero-v2__mark {
  display: block;
  width: auto;
  height: 29px;
}

/* ------------------------------------------------------------ entrance */

/* One fade, once, on load. Nothing here loops: a looping hero is the thing that
   makes a page look templated, and it is also the thing a reader's eye cannot
   stop tracking while trying to read the headline. */
@media (prefers-reduced-motion: no-preference) {
  .hero-v2 .hero__title,
  .hero-v2 .hero__ctas,
  .hero-v2__marks {
    animation: hv-rise 0.9s cubic-bezier(0.22, 0.75, 0.2, 1) both;
  }
  .hero-v2 .hero__ctas  { animation-delay: 0.08s; }
  .hero-v2__marks       { animation-delay: 0.16s; }
}

@keyframes hv-rise {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: none; }
}

/* Everything ambient stops dead. The blooms keep their starting positions, so
   the hero still has its light and its grain - it simply holds still. Slowing
   the drift down instead would miss the point: the objection to background
   motion is the motion, not its speed. */
@media (prefers-reduced-motion: reduce) {
  .hero-v2__bloom,
  .hero-v2__grain { animation: none; }
}

/* --------------------------------------------------------- breakpoints */

@media (max-width: 640px) {
  /* 2026-09-13 [Matias]: full screen on phones too, as on desktop. This was
     min-height: auto, which with the spec rail gone left a hero only as tall as the
     headline and buttons. */
  .hero-v2 .hero__main { padding-bottom: 40px; }
  /* The one literal size in this file, and it is a BREAKPOINT CAP, not a tier of its
     own: --fs-display bottoms out at 44px, which is still too big for this headline on
     a 375px screen. Caps like this are fine; a new size for a new component is not. */
  .hero-v2 .hero__title { font-size: clamp(2.1rem, 8.5vw, 2.6rem); max-width: 100%; }

  /* The marks show on phones, unlike the spec rail they replaced, which was hidden
     here on 2026-09-13 [Matias] as four rows of small print repeated further down.
     Two marks are one short row and appear nowhere else. Same 29px height: they
     fit side by side at 320px, and the Litecoin mark stays above its 64px small
     screen minimum. */
  .hero-v2__marks { margin-top: 36px; }
}
