/* gleam.html, the Vision page. The one page where the beam runs at full power:
   dark "accelerator" bands alternate with the white canvas, and every moving thing
   is a point being earned. Shared program styles are in program.css.
   See DESIGN.md § Points program. */

.v-band {
  position: relative;
  padding: clamp(56px, 10vh, 120px) 0 clamp(72px, 14vh, 160px);
  color: var(--fg);
}

.v .points-h2 {
  margin: 0 0 clamp(24px, 4vh, 40px);
  font-size: clamp(1.75rem, 3.6vw, 2.75rem);
  letter-spacing: -0.03em;
}

/* Hero: the accelerator. The beam enters from the left edge, a pulse rides it per
   point, and at its end it shatters into the particles that become the counter. */

.v-hero {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  color: var(--on-ink);
  background: var(--ink);
}

.v-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -2;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.055) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.055) 1px, transparent 1px);
  background-size: 56px 56px;
  -webkit-mask-image: radial-gradient(
    ellipse 80% 70% at 70% 75%,
    #000,
    transparent 75%
  );
  mask-image: radial-gradient(
    ellipse 80% 70% at 70% 75%,
    #000,
    transparent 75%
  );
}

.v-canvas {
  position: absolute;
  inset: 0;
  z-index: -1;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.v-hero-in {
  display: flex;
  flex-direction: column;
  min-height: calc(100svh - 62px);
  padding-top: clamp(28px, 7vh, 96px);
  padding-bottom: 80px;
}

@media (min-width: 900px) {
  .v-hero-in {
    padding-bottom: clamp(40px, 7vh, 80px);
  }
}

.v-hero .points-kicker {
  color: var(--on-ink-muted);
}

.v-title {
  font-size: clamp(2.75rem, 9.5vw, 7.75rem);
  line-height: 0.96;
  letter-spacing: -0.05em;
  max-width: 10em;
}

/* Crystals glint, they don't pulse. On a whole point a band of light sweeps
   left to right across the counter, then GLEAM a beat later, like one ray
   passing over both. The band is the point's colour washed toward white,
   with faint prism fringes, so it reads as light rather than an alert. */
.v-gleam {
  --hit: var(--on-ink);
  position: relative;
}
.v-gleam-word,
.gc .od-s {
  background: linear-gradient(
      100deg,
      var(--on-ink) 38%,
      color-mix(in oklab, var(--beam-purple) 30%, var(--on-ink)) 44%,
      color-mix(in oklab, var(--hit) 55%, #fff) 48%,
      color-mix(in oklab, var(--hit) 55%, #fff) 52%,
      color-mix(in oklab, var(--beam-sky) 30%, var(--on-ink)) 56%,
      var(--on-ink) 62%
    )
    0 0 / 300% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.v-gleam.glow .v-gleam-word {
  animation: glint 1.2s ease-in-out 0.2s both;
}

@keyframes glint {
  from {
    background-position: 100% 0;
  }
  to {
    background-position: 0 0;
  }
}

/* The cartoon shorthand for a gem: a four-point star that opens, turns a
   little and closes on a letter's edge just after the glint passes. */
.v-twinkle {
  position: absolute;
  width: 0.26em;
  height: 0.26em;
  margin: -0.13em 0 0 -0.13em;
  background: radial-gradient(
    circle,
    #fff 25%,
    color-mix(in oklab, var(--hit) 45%, #fff) 70%
  );
  clip-path: polygon(
    50% 0,
    58% 42%,
    100% 50%,
    58% 58%,
    50% 100%,
    42% 58%,
    0 50%,
    42% 42%
  );
  pointer-events: none;
  animation: twinkle 1.1s ease-in-out 0.75s both;
}

@keyframes twinkle {
  0% {
    opacity: 0;
    transform: scale(0) rotate(-20deg);
  }
  40% {
    opacity: 1;
    transform: scale(1) rotate(0);
  }
  100% {
    opacity: 0;
    transform: scale(0) rotate(25deg);
  }
}

.v-hero .line {
  color: var(--on-ink-muted);
}

.v-track {
  display: grid;
  gap: 24px;
  margin-top: auto;
  padding-top: clamp(40px, 8vh, 96px);
}

.v-beam {
  width: auto;
  height: 10px;
  flex-direction: column;
  margin-left: calc(50% - 50vw);
  margin-right: 16%;
  -webkit-mask-image: linear-gradient(90deg, #000 78%, transparent);
  mask-image: linear-gradient(90deg, #000 78%, transparent);
}

.v-meter {
  position: relative;
  min-width: 0;
}

/* The counter. Integer digits roll like an arcade odometer; each whole point
   punches, splits into beam colours for a frame and drops a +1. */

.gc {
  --hit: var(--on-ink);
  display: flex;
  align-items: flex-end;
  gap: 0.12em;
  font-size: clamp(6rem, 32vw, 12rem);
  font-weight: 760;
  line-height: 1;
  letter-spacing: -0.055em;
  font-variant-numeric: tabular-nums;
  transform-origin: 15% 85%;
}

.gc-num {
  position: relative;
  display: inline-flex;
}
.gc-int {
  display: inline-flex;
}

.gc-side {
  display: flex;
  flex-direction: column;
  padding-bottom: 0.1em;
  letter-spacing: -0.02em;
}
.gc-dec {
  font-size: 0.3em;
  line-height: 1;
  color: var(--on-ink-muted);
}
.gc-unit {
  margin-top: 0.5em;
  font-size: 0.1em;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--on-ink-muted);
}

/* The digits are separate rolling columns, so each gets its own glint,
   staggered to read as one sweep across the number. */
.gc.land .od-s {
  animation: glint 1s ease-in-out both;
  animation-delay: calc(var(--i, 0) * 70ms);
}

/* Digits settle into place instead of overshooting and bouncing back */
.v .od-s:not(.snap) {
  transition: transform 0.8s cubic-bezier(0.25, 0.8, 0.3, 1);
}

.gc-plus {
  position: absolute;
  right: -0.05em;
  top: -0.05em;
  font-size: 0.17em;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: color-mix(in oklab, var(--hit) 55%, #fff);
  pointer-events: none;
  animation: gc-float 2s ease-out forwards;
}

@keyframes gc-float {
  0% {
    opacity: 0;
    transform: translate(0, 0.3em);
  }
  30% {
    opacity: 0.7;
  }
  60% {
    transform: translate(-0.12em, -0.7em);
  }
  100% {
    opacity: 0;
    transform: translate(0.15em, -1.4em);
  }
}

html:not(.js) .v-meter,
html:not(.js) .tl-now-count {
  display: none;
}

@media (min-width: 900px) {
  .v-track {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: end;
    gap: 0;
  }
  .v-beam {
    margin-right: 0;
    margin-bottom: 0.55em;
    align-self: end;
    font-size: clamp(6rem, 32vw, 12rem);
  }
  .v-meter {
    padding-left: 32px;
  }
}

/* You earn GLEAM by: two rows, each with a signal that fires on every point */

.v-today {
  background: var(--paper);
}

.v .vision-today {
  max-width: none;
}

.v .vision-today li {
  position: relative;
  padding: clamp(24px, 4.5vh, 44px) 72px clamp(24px, 4.5vh, 44px) 0;
  border-color: #dcdcdc;
  font-size: clamp(1.25rem, 2.6vw, 2rem);
  line-height: 1.25;
  letter-spacing: -0.015em;
  text-wrap: pretty;
}

.v .vision-today strong {
  display: block;
  margin-bottom: 10px;
  font-size: clamp(2.75rem, 8vw, 6rem);
  line-height: 0.95;
  letter-spacing: -0.05em;
}

.v-sig {
  --hit: var(--fg);
  position: absolute;
  right: 0;
  top: 50%;
  width: 56px;
  height: 14px;
  margin-top: -7px;
}
.v-sig i {
  position: absolute;
  top: 2px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--fg);
}
.v-sig-hold i {
  right: 0;
}
.v-sig-hold::after {
  content: "";
  position: absolute;
  right: -7px;
  top: -5px;
  width: 24px;
  height: 24px;
  border: 2px solid var(--hit);
  border-radius: 50%;
  opacity: 0;
}
.v-sig-invite::before {
  content: "";
  position: absolute;
  left: 5px;
  right: 5px;
  top: 6px;
  height: 2px;
  background: #d4d4d4;
}
.v-sig-invite i:first-child {
  left: 0;
}
.v-sig-invite i:last-child {
  right: 0;
}
.v-sig-invite::after {
  content: "";
  position: absolute;
  left: 5px;
  top: 5px;
  width: 12px;
  height: 4px;
  border-radius: 2px;
  background: var(--hit);
  opacity: 0;
}

.tick .v-sig i {
  animation: sig-hit 0.55s ease-out;
}
.tick .v-sig-hold::after {
  animation: sig-ring 0.7s ease-out;
}
.tick .v-sig-invite::after {
  animation: sig-run 0.55s cubic-bezier(0.5, 0, 0.5, 1);
}
.tick .v-sig-invite i:last-child {
  animation-delay: 0.4s;
}

@keyframes sig-hit {
  0% {
    background: var(--hit);
    transform: scale(1.7);
  }
  100% {
    background: var(--fg);
    transform: none;
  }
}
@keyframes sig-ring {
  0% {
    opacity: 1;
    transform: scale(0.4);
  }
  100% {
    opacity: 0;
    transform: scale(1.6);
  }
}
@keyframes sig-run {
  0% {
    opacity: 1;
    transform: translateX(0);
  }
  90% {
    opacity: 1;
  }
  100% {
    opacity: 0;
    transform: translateX(34px);
  }
}

/* The wallet: one statement, lit line by line as it scrolls through, and the
   window the white light passes through to come out as the beam */

.v-wallet {
  background: #fff;
  overflow: hidden;
}

.v .v-big {
  max-width: 15em;
  margin: 0;
  font-size: clamp(2.25rem, 6.4vw, 5.25rem);
  font-weight: 650;
  line-height: 1.04;
  letter-spacing: -0.045em;
  text-wrap: balance;
}

.v-big span {
  display: block;
  transition: opacity 0.6s var(--ease-out);
}
.v-big span:last-child {
  display: inline;
  padding-bottom: 0.04em;
  background: var(--beam-run) no-repeat 0 100% / 0% 0.09em;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
  transition:
    opacity 0.6s var(--ease-out),
    background-size 1.1s var(--ease-out) 0.15s;
}
.motion .v-big span:not(.lit) {
  opacity: 0.16;
}
.v-big span:last-child.lit,
html:not(.motion) .v-big span:last-child {
  background-size: 100% 0.09em;
}

.v-prism {
  display: block;
  width: 100%;
  max-width: 720px;
  height: auto;
  margin: clamp(40px, 7vh, 72px) 0 clamp(32px, 5vh, 56px);
  overflow: visible;
}
.v-prism line {
  stroke-width: 3;
  stroke-linecap: round;
}
.pr-in {
  stroke: var(--fg);
}
.pr-pane {
  fill: rgba(255, 255, 255, 0.6);
  stroke: #cfcfcf;
  stroke-width: 1.5;
}
.pr-in,
.pr-out {
  stroke-dasharray: 260;
  stroke-dashoffset: 0;
}
.motion .v-prism:not(.in) .pr-in,
.motion .v-prism:not(.in) .pr-out {
  stroke-dashoffset: 260;
}
.motion .v-prism:not(.in) .pr-pane {
  opacity: 0;
  transform: scale(0.9);
}
.motion .v-prism .pr-in {
  transition: stroke-dashoffset 0.7s cubic-bezier(0.6, 0, 0.9, 0.4);
}
.motion .v-prism .pr-pane {
  transform-box: fill-box;
  transform-origin: center;
  transition:
    opacity 0.3s 0.55s,
    transform 0.5s cubic-bezier(0.3, 1.6, 0.5, 1) 0.55s;
}
.motion .v-prism .pr-out {
  transition: stroke-dashoffset 0.9s var(--ease-out) 0.7s;
}

.v .v-sub {
  font-size: clamp(1.25rem, 2vw, 1.625rem);
  line-height: 1.4;
  letter-spacing: -0.01em;
  color: var(--muted);
}
/* Each choice gets its own beam colour, underlined as the sentence passes
   the reading line. Inline blocks, so a phrase moves as one. */
.v-sub b {
  --c: var(--beam-red);
  display: inline-block;
  font-weight: 600;
  color: var(--fg);
  background: linear-gradient(var(--c), var(--c)) no-repeat 0 100% / 0% 0.09em;
  transition: background-size 0.7s var(--ease-out);
}
.v-sub b:nth-of-type(2) { --c: var(--beam-sky); }
.v-sub b:nth-of-type(3) { --c: var(--beam-green); }
.v-sub b.lit,
html:not(.motion) .v-sub b {
  background-size: 100% 0.09em;
}
/* Rewound: the line runs back the way it came */
.v-sub b.back {
  background-position: 100% 100%;
}

/* The timeline: history scrolls sideways while the page scrolls down. The lit
   beam is time passing; it stops at "you are here" and the counter starts there. */

.v-tl {
  position: relative;
  background: var(--ink);
  color: var(--on-ink);
}

.tl-sticky {
  padding: 96px 0;
}
.tl-viewport {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
}
.tl-viewport::-webkit-scrollbar {
  display: none;
}

.motion .tl-sticky {
  position: sticky;
  top: 0;
  height: 100svh;
  display: flex;
  align-items: center;
  padding: 0;
}
.motion .tl-viewport {
  width: 100%;
  overflow: hidden;
}

.tl-track {
  --step: 112px;
  --gap: 132px;
  --above: 290px;
  --below: 230px;
  position: relative;
  display: flex;
  width: max-content;
  margin: 0;
  padding: var(--above) 0 var(--below) var(--gutter);
  list-style: none;
}
.motion .tl-track {
  will-change: transform;
}

.tl-track::before {
  content: "";
  position: absolute;
  left: 0;
  width: var(--now-x, 100%);
  top: var(--above);
  height: 1px;
  background: rgba(255, 255, 255, 0.16);
}

.tl-fill {
  position: absolute;
  left: 0;
  top: calc(var(--above) - 4px);
  width: var(--fill, 100%);
  height: 9px;
  background: var(--beam-stack);
  pointer-events: none;
}
.tl-fill::after {
  content: "";
  position: absolute;
  right: -10px;
  top: -6px;
  width: 21px;
  height: 21px;
  border-radius: 50%;
  background: #fff;
  box-shadow:
    0 0 18px 6px rgba(255, 255, 255, 0.55),
    0 0 60px 18px rgba(115, 201, 232, 0.35);
}

.tl-item {
  position: relative;
  flex: none;
  width: var(--step);
  height: 0;
}
.tl-item::after {
  content: "";
  position: absolute;
  left: -5px;
  top: -5px;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: #3a3a3a;
  transition:
    background-color 0.3s,
    box-shadow 0.3s;
}
.tl-item.lit::after {
  background: #fff;
  box-shadow: 0 0 10px 2px rgba(255, 255, 255, 0.45);
}
.tl-item[data-year]:not(:nth-child(2)) {
  margin-left: var(--gap);
}

.tl-item[data-year]::before {
  content: attr(data-year);
  position: absolute;
  left: -0.06em;
  bottom: 170px;
  font-size: clamp(80px, 13vw, 180px);
  font-weight: 750;
  line-height: 0.8;
  letter-spacing: -0.06em;
  white-space: nowrap;
  color: rgba(255, 255, 255, 0.06);
  transition: color 0.4s;
}
.tl-item[data-year].lit::before {
  color: rgba(255, 255, 255, 0.16);
}

.tl-card {
  position: absolute;
  left: 0;
  bottom: 18px;
  width: calc(var(--step) * 2 - 18px);
  padding: 0 0 0 12px;
  border-left: 1px solid rgba(255, 255, 255, 0.2);
  opacity: 0.38;
  transition: opacity 0.4s var(--ease-out);
}
.tl-item:nth-child(odd) .tl-card {
  bottom: auto;
  top: 18px;
}
.tl-item.lit .tl-card,
html:not(.motion) .tl-card {
  opacity: 1;
}
.tl-card time {
  display: block;
  margin-bottom: 4px;
  font: 500 0.6875rem/1.4 var(--mono);
  letter-spacing: 0.02em;
  color: var(--on-ink-muted);
}
.tl-card span {
  display: block;
  font-size: 0.9375rem;
  line-height: 1.3;
  letter-spacing: -0.01em;
  text-wrap: pretty;
}

.tl-now {
  position: relative;
  flex: none;
  width: 0;
  height: 0;
  margin-left: var(--step);
}

.tl-now-dot {
  position: absolute;
  left: -11px;
  top: -11px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: #fff;
  box-shadow:
    0 0 0 5px rgba(255, 255, 255, 0.14),
    0 0 28px 8px rgba(115, 201, 232, 0.6);
  transition: box-shadow 0.5s;
}
.tl-now-dot::before,
.tl-now-dot::after {
  content: "";
  position: absolute;
  inset: -2px;
  border: 2px solid var(--beam-sky);
  border-radius: 50%;
  opacity: 0;
}
.tl-now.on .tl-now-dot {
  box-shadow:
    0 0 0 6px rgba(255, 255, 255, 0.18),
    0 0 44px 14px rgba(115, 201, 232, 0.75),
    0 0 120px 40px rgba(139, 18, 255, 0.25);
}
.tl-now.on .tl-now-dot::before {
  animation: beacon 2.4s cubic-bezier(0.2, 0.6, 0.3, 1) infinite;
}
.tl-now.on .tl-now-dot::after {
  animation: beacon 2.4s cubic-bezier(0.2, 0.6, 0.3, 1) 1.2s infinite;
}

@keyframes beacon {
  0% {
    opacity: 0.9;
    transform: scale(1);
  }
  100% {
    opacity: 0;
    transform: scale(4.5);
  }
}

.tl-now-label {
  position: absolute;
  left: -2px;
  bottom: 30px;
  white-space: nowrap;
  font-size: 1.125rem;
  font-weight: 650;
  letter-spacing: -0.015em;
}

.tl-now-count {
  position: absolute;
  left: -2px;
  top: 28px;
  white-space: nowrap;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--on-ink-muted);
  transform-origin: 0 50%;
}
.tl-now-count b {
  font-size: 2.25rem;
  font-weight: 760;
  letter-spacing: -0.04em;
  color: var(--on-ink);
  font-variant-numeric: tabular-nums;
}
.tl-now-count b + span {
  margin-right: 4px;
  font-variant-numeric: tabular-nums;
}
.tl-now-count.land {
  animation: gc-land 0.45s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.tl-now-count.land b {
  animation: gc-split 0.4s steps(5, end);
}

.tl-next {
  position: relative;
  flex: none;
  width: 196px;
  height: 0;
  margin: 0 var(--gutter) 0 76px;
  padding-left: 14px;
}
.tl-next::before {
  content: "";
  position: absolute;
  right: 100%;
  top: -1px;
  width: 76px;
  height: 3px;
  background: repeating-linear-gradient(
    90deg,
    rgba(255, 255, 255, 0.7) 0 8px,
    transparent 8px 16px
  );
}
.tl-now.on + .tl-next::before {
  animation: future 0.8s linear infinite;
}
.motion .tl-next::before {
  transform: scaleX(var(--next, 0));
  transform-origin: 0 50%;
}
.motion .tl-next span {
  opacity: var(--next, 0);
  transform: translateX(calc((1 - var(--next, 0)) * 24px));
}
.tl-next span {
  position: absolute;
  left: 14px;
  right: 0;
  top: -0.68em;
  font-size: 1.125rem;
  font-weight: 650;
  line-height: 1.3;
  letter-spacing: -0.015em;
}

@keyframes future {
  to {
    background-position: 16px 0;
  }
}

@media (min-width: 900px) {
  .tl-track {
    --step: 140px;
    --gap: 220px;
    --above: 340px;
    --below: 260px;
  }
  .tl-item[data-year]::before {
    bottom: 190px;
  }
  .tl-card span {
    font-size: 1rem;
  }
  .tl-next {
    width: 320px;
    margin-left: 180px;
  }
  .tl-next::before {
    width: 180px;
  }
  .tl-next span {
    font-size: 1.375rem;
  }
}

@media (max-height: 640px) {
  .tl-track {
    --above: 250px;
    --below: 200px;
  }
  .tl-item[data-year]::before {
    bottom: 150px;
    font-size: 72px;
  }
}

/* Rewards: the tokenomics, from points to GLEAM to what staking unlocks */

.v-rewards {
  background: var(--paper);
}

.v-rewards .points-h2 {
  max-width: 11em;
  font-size: clamp(2.5rem, 7vw, 5.25rem);
  line-height: 0.98;
  letter-spacing: -0.05em;
}
.v-rewards .vision-lead {
  font-size: clamp(1.25rem, 2.2vw, 1.75rem);
  letter-spacing: -0.015em;
}

.v-rewards-kicker {
  font: 600 0.8125rem/1 var(--mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

/* Tokenomics reads top to bottom: earn, airdrop, stake. A beam-coloured
   rail joins the steps and draws downward as the section arrives. */

.v-flow {
  --rail: 3px;
  --node: 44px;
  position: relative;
  max-width: 52rem;
  margin: clamp(40px, 7vh, 72px) 0 0;
  padding: 0;
  list-style: none;
}
.v-flow::before {
  content: "";
  position: absolute;
  left: calc(var(--node) / 2 - var(--rail) / 2);
  top: calc(var(--node) / 2);
  bottom: 0;
  width: var(--rail);
  background: linear-gradient(
    var(--beam-red),
    var(--beam-purple),
    var(--beam-sky),
    var(--beam-yellow),
    var(--beam-green)
  );
  border-radius: var(--rail);
  transform-origin: top;
}

.v-step {
  position: relative;
  padding: 0 0 clamp(40px, 6vh, 64px) calc(var(--node) + clamp(20px, 3vw, 36px));
}
.v-step:last-child {
  padding-bottom: 0;
}

.v-step-n {
  position: absolute;
  left: 0;
  top: 0;
  display: grid;
  place-items: center;
  width: var(--node);
  height: var(--node);
  border-radius: 50%;
  background: var(--fg);
  color: #fff;
  font: 600 0.8125rem/1 var(--mono);
}

.v-step h3 {
  margin: 4px 0 12px;
  font-size: clamp(1.75rem, 3.4vw, 2.75rem);
  line-height: 1.02;
  letter-spacing: -0.04em;
}
.v-step > p {
  margin: 0;
  max-width: 36em;
  font-size: clamp(1.0625rem, 1.4vw, 1.25rem);
  color: var(--muted);
}

.motion .v-flow::before {
  transform: scaleY(0);
  transition: transform 1.6s var(--ease-out);
}
.motion .v-flow.in::before {
  transform: scaleY(1);
}
.motion .v-step {
  opacity: 0;
  transform: translateY(12px);
  transition:
    opacity 0.7s var(--ease-out),
    transform 0.7s var(--ease-out);
}
.motion .v-flow.in .v-step {
  opacity: 1;
  transform: none;
}
.motion .v-flow.in .v-step:nth-child(2) {
  transition-delay: 0.35s;
}
.motion .v-flow.in .v-step:nth-child(3) {
  transition-delay: 0.7s;
}

/* Stake GLEAM: its own dark section. Each reward is a chapter with room
   around it and a small diagram that moves at the same calm pace as the
   hero, so a reader stops on each one instead of scanning a grid. */

.v-stake {
  padding: clamp(24px, 4vh, 48px) 0 clamp(48px, 8vh, 96px);
  background: var(--ink);
  color: var(--on-ink);
}
.v-stake .v-rewards-kicker {
  color: var(--on-ink-muted);
}
.v-stake-h {
  margin: 0;
  font-size: clamp(2.75rem, 8.5vw, 6.5rem);
  line-height: 0.96;
  letter-spacing: -0.05em;
}

.perk {
  display: grid;
  gap: 28px;
  align-items: center;
  margin-top: clamp(56px, 10vh, 120px);
  padding-top: clamp(40px, 7vh, 80px);
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}
.perk:nth-of-type(1) {
  --c: var(--beam-green);
}
.perk:nth-of-type(2) {
  --c: var(--beam-purple);
}
.perk:nth-of-type(3) {
  --c: var(--beam-sky);
}
.perk:nth-of-type(4) {
  --c: var(--beam-yellow);
}

.perk-k {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0 0 18px;
  font: 600 0.8125rem/1 var(--mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--c);
}
.perk-k::before {
  content: "";
  width: 28px;
  height: 3px;
  border-radius: 3px;
  background: var(--c);
}
.perk h3 {
  margin: 0 0 18px;
  font-size: clamp(2.25rem, 5.5vw, 4.25rem);
  line-height: 1;
  letter-spacing: -0.045em;
}
.perk-copy > p:last-child {
  margin: 0;
  max-width: 28em;
  font-size: clamp(1.0625rem, 1.5vw, 1.3125rem);
  color: var(--on-ink-muted);
}

.perk-art {
  width: 100%;
  max-width: 480px;
  height: auto;
  justify-self: center;
  overflow: visible;
}
.perk-art text {
  font: 500 14px var(--mono);
  fill: var(--on-ink-muted);
}

@media (min-width: 900px) {
  .perk {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 64px;
  }
  .perk:nth-of-type(even) .perk-copy {
    order: 2;
  }
}

/* Early access: you're already through the gate while the queue waits */
.q-post {
  fill: rgba(255, 255, 255, 0.22);
}
.q-dot {
  fill: rgba(255, 255, 255, 0.14);
}
.q-you circle {
  fill: var(--c);
  filter: drop-shadow(0 0 10px var(--c));
}
.q-you text {
  fill: var(--c);
}
.q-you {
  transform: translateX(118px);
}

/* Projects come to you: tokens drift down into your wallet */
.d-tok {
  transform-box: fill-box;
  transform-origin: center;
  transform: rotate(45deg);
}
.d-tok:nth-of-type(1) {
  fill: var(--beam-purple);
}
.d-tok:nth-of-type(2) {
  fill: var(--beam-yellow);
}
.d-tok:nth-of-type(3) {
  fill: var(--beam-sky);
}
.d-wallet {
  fill: var(--ink-2);
  stroke: rgba(255, 255, 255, 0.22);
  stroke-width: 2;
}
.d-slot {
  stroke: var(--c);
  stroke-width: 3;
  stroke-linecap: round;
}

/* Lower fees: the staked bar is shorter */
.f-bar {
  fill: rgba(255, 255, 255, 0.12);
}
.f-staked {
  fill: var(--c);
  transform-box: fill-box;
  transform-origin: left;
  transform: scaleX(0.55);
}

/* Fee share: value goes round the loop from use, to fees, to stakers */
.l-ring {
  fill: none;
  stroke: rgba(255, 255, 255, 0.14);
  stroke-width: 2;
}
.l-node {
  fill: rgba(255, 255, 255, 0.35);
}
.l-orbit circle {
  fill: var(--c);
  filter: drop-shadow(0 0 8px var(--c));
}
.l-orbit {
  transform-origin: 240px 150px;
}
/* A stop lights in the value's colour as it passes */
.l-node {
  transform-box: fill-box;
  transform-origin: center;
}
.l-node.hit {
  animation: l-hit 0.9s ease-out;
}
@keyframes l-hit {
  15% {
    fill: var(--c);
    transform: scale(1.6);
    filter: drop-shadow(0 0 6px var(--c));
  }
}

.motion .q-you {
  transform: none;
  transition: transform 1.8s cubic-bezier(0.3, 0.7, 0.3, 1) 0.3s;
}
.motion .perk.in .q-you {
  transform: translateX(118px);
}

.motion .d-tok {
  opacity: 0;
}
.motion .perk.in .d-tok {
  animation: drop 4.8s ease-in-out infinite;
}
.motion .perk.in .d-tok:nth-of-type(2) {
  animation-delay: 1.6s;
}
.motion .perk.in .d-tok:nth-of-type(3) {
  animation-delay: 3.2s;
}
@keyframes drop {
  0% {
    opacity: 0;
    transform: translateY(0) rotate(45deg);
  }
  15% {
    opacity: 1;
  }
  70% {
    opacity: 1;
  }
  85%,
  100% {
    opacity: 0;
    transform: translateY(185px) rotate(45deg);
  }
}

.motion .f-staked {
  transform: scaleX(1);
  transition: transform 1.8s cubic-bezier(0.3, 0.7, 0.3, 1) 0.3s;
}
.motion .perk.in .f-staked {
  transform: scaleX(0.55);
}

.motion .perk.in .l-orbit {
  animation: orbit 10s linear infinite;
}
@keyframes orbit {
  to {
    transform: rotate(360deg);
  }
}

.motion .perk .perk-copy {
  opacity: 0;
  transform: translateY(14px);
  transition:
    opacity 0.8s var(--ease-out),
    transform 0.8s var(--ease-out);
}
.motion .perk.in .perk-copy {
  opacity: 1;
  transform: none;
}

/* Stake and the CTA are both on ink, so a thin beam marks the seam */
.v-stake-end {
  height: 2px;
  background: linear-gradient(
    90deg,
    transparent,
    var(--beam-red),
    var(--beam-purple),
    var(--beam-sky),
    var(--beam-yellow),
    var(--beam-green),
    transparent
  );
  opacity: 0.6;
}

/* CTA: back on ink. The beam draws in from the left edge, the start, to the heading. */

.v-final {
  margin-top: 0;
  padding: clamp(40px, 8vh, 96px) 0 clamp(56px, 10vh, 112px);
  background: var(--ink);
  color: var(--on-ink);
}

.v-start.beam {
  width: calc(50vw - 50% + 120px);
  max-width: none;
  height: 10px;
  flex-direction: column;
  margin: 0 0 28px calc(50% - 50vw);
  transform-origin: left;
}
.motion .v-start:not(.in) {
  transform: scaleX(0);
}
.motion .v-start {
  transition: transform 1.1s cubic-bezier(0.7, 0, 0.2, 1);
}

.v-final .heading {
  font-size: clamp(3rem, 11vw, 8.5rem);
  line-height: 0.94;
  letter-spacing: -0.055em;
}
.v-final .get-in {
  margin-top: 24px;
}
.v-final .vision-lead {
  color: var(--on-ink-muted);
}

.v-final .cta {
  margin-top: 32px;
}
.v-final .small {
  margin: 16px 0 0;
  color: var(--on-ink-muted);
}
.v-final .small a,
.v-final .vision-lead strong {
  color: var(--on-ink);
}
.v-final .get-in + .small {
  margin-top: 8px;
}

/* The page is long; this is the way down to the CTA for whoever's ready early */

.v-jump {
  margin: clamp(24px, 4vh, 40px) 0 0;
  font-size: 1.0625rem;
  font-weight: 600;
}
.v-jump a {
  color: var(--fg);
  text-underline-offset: 4px;
}
.v-jump a::after {
  content: " \2193";
}

.v-final .button {
  background: var(--on-ink);
  color: var(--ink);
}
.v-final .button:hover {
  background: #e8e8e8;
}
.v-final .vision-note {
  color: var(--on-ink-muted);
}

.paused .v-hero *,
.paused .v-tl * {
  animation-play-state: paused !important;
}

@media (prefers-reduced-motion: reduce) {
  .v .od-s:not(.snap) {
    transition: none;
  }
  .v-gleam.glow .v-gleam-word,
  .v-twinkle,
  .gc.land .od-s,
  .tl-now-count.land,
  .tl-now-count.land b,
  .tick .v-sig i,
  .tick .v-sig-hold::after,
  .tick .v-sig-invite::after {
    animation: none;
  }
  .tl-now.on .tl-now-dot::before,
  .tl-now.on .tl-now-dot::after,
  .tl-now.on + .tl-next::before {
    animation: none;
  }
  .v-big span,
  .v-big span:last-child {
    transition: none;
  }
}

/* The gate: every visit opens on an idle orb holding 0.00. Every cycle a
   pulse rides a beam in from the left edge, the orb takes the charge, five
   colour rings spill off it and the light runs across GLEAM letter by
   letter. Each tap charges a third of the arc round it and says one thing
   GLEAM gets you. The third overcharges it and wakes the hero: the rings
   burst, the orb flies to the counter and becomes it, and the page unlocks. */

.v-gate {
  display: none;
}

html.gate,
html.gate body {
  overflow: hidden;
  overscroll-behavior: none;
}

html.gate .v-sound {
  display: none;
}

html.gate .v-gate {
  --cycle: 3.2s;
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(28px, 5vh, 44px);
  padding: 0 16px 48px;
  border: 0;
  background: none;
  color: var(--on-ink);
  font: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

html.gate .v-gate:focus-visible {
  outline: none;
}
html.gate .v-gate:focus-visible .v-gate-cta {
  outline: 2px solid var(--beam-sky);
  outline-offset: 8px;
  border-radius: 6px;
}

/* Held behind the gate, still laid out so the orb knows where to land */
html.gate .v-hero-in > *,
html.gate .v-beam,
html.gate .v-meter {
  opacity: 0;
}

.v-gate-orb {
  --size: clamp(184px, 48vw, 288px);
  --lx: 0;
  --ly: 0;
  position: relative;
  display: grid;
  place-items: center;
  width: var(--size);
  height: var(--size);
  border-radius: 50%;
  background: radial-gradient(circle at 50% 40%, #161616, var(--ink) 70%);
  translate: calc(var(--lx) * 10px) calc(var(--ly) * 10px);
  transition: translate 0.6s cubic-bezier(0.25, 0.8, 0.3, 1);
  animation: gate-in 1s cubic-bezier(0.2, 0.9, 0.3, 1.2) both;
}

/* The ring is the beam bent closed: five hard-edged arcs, slowly turning */
.v-gate-ring,
.v-gate-ring::after {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: conic-gradient(
    var(--beam-red) 0 20%,
    var(--beam-purple) 0 40%,
    var(--beam-sky) 0 60%,
    var(--beam-yellow) 0 80%,
    var(--beam-green) 0
  );
  -webkit-mask: radial-gradient(circle, transparent calc(70.7% - 4px), #000 calc(70.7% - 3px));
  mask: radial-gradient(circle, transparent calc(70.7% - 4px), #000 calc(70.7% - 3px));
  animation: gate-spin 16s linear infinite;
}
.v-gate-ring::after {
  content: "";
  filter: blur(14px);
  opacity: 0.45;
  animation: gate-charge var(--cycle) ease-out infinite;
}

.v-gate-num {
  display: flex;
  align-items: flex-end;
  font-size: calc(var(--size) * 0.36);
  font-weight: 760;
  line-height: 1;
  letter-spacing: -0.055em;
  font-variant-numeric: tabular-nums;
  animation: gate-num var(--cycle) ease-out infinite;
}
.v-gate-num b {
  font-weight: inherit;
}
.v-gate-num small {
  padding-bottom: 0.1em;
  font-size: 0.3em;
  font-weight: inherit;
  letter-spacing: -0.02em;
  color: var(--on-ink-muted);
}

/* The feed: the hero's beam, cut to run from the screen's left edge into the
   orb, with a white pulse riding it that lands at 40% of each cycle */
.v-gate-beam {
  position: absolute;
  top: 50%;
  right: 100%;
  display: flex;
  flex-direction: column;
  width: 50vw;
  height: 10px;
  margin-top: -5px;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 30%);
  mask-image: linear-gradient(90deg, transparent, #000 30%);
}
.v-gate-beam i {
  flex: 1;
  opacity: 0.55;
}
.v-gate-beam i:nth-child(1) { background: var(--beam-red); }
.v-gate-beam i:nth-child(2) { background: var(--beam-purple); }
.v-gate-beam i:nth-child(3) { background: var(--beam-sky); }
.v-gate-beam i:nth-child(4) { background: var(--beam-yellow); }
.v-gate-beam i:nth-child(5) { background: var(--beam-green); }
.v-gate-beam::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 0;
  width: 160px;
  height: 4px;
  margin: -2px 0 0 -160px;
  border-radius: 2px;
  background: linear-gradient(90deg, transparent, #fff);
  box-shadow: 0 0 14px 2px rgba(255, 255, 255, 0.5);
  animation: gate-pulse var(--cycle) cubic-bezier(0.55, 0, 0.9, 0.6) infinite;
}

/* Five rings, one per beam colour, spill off as the charge lands */
.v-gate-waves {
  position: absolute;
  inset: 0;
}
.v-gate-waves i {
  position: absolute;
  inset: 0;
  border: 2px solid;
  border-radius: 50%;
  opacity: 0;
  animation: gate-wave var(--cycle) cubic-bezier(0.2, 0.7, 0.3, 1) infinite;
}
.v-gate-waves i:nth-child(1) { color: var(--beam-red); animation-delay: 0s; }
.v-gate-waves i:nth-child(2) { color: var(--beam-purple); animation-delay: 0.06s; }
.v-gate-waves i:nth-child(3) { color: var(--beam-sky); animation-delay: 0.12s; }
.v-gate-waves i:nth-child(4) { color: var(--beam-yellow); animation-delay: 0.18s; }
.v-gate-waves i:nth-child(5) { color: var(--beam-green); animation-delay: 0.24s; }

.v-gate-cta {
  display: block;
  width: min(100%, 36em);
  font-size: clamp(1.375rem, 4.2vw, 2.125rem);
  font-weight: 760;
  letter-spacing: -0.03em;
  color: var(--on-ink-muted);
  animation: gate-rise 0.8s 0.35s cubic-bezier(0.2, 0.8, 0.3, 1) both;
}

/* GLEAM takes the light one letter at a time, each in its own beam colour */
.v-gate-word {
  display: inline-flex;
  margin-left: 0.15em;
  color: var(--on-ink);
}
.v-gate-word i {
  font-style: normal;
  animation: gate-letter var(--cycle) ease-out infinite;
}
.v-gate-word i:nth-child(1) { --c: var(--beam-red); animation-delay: 0.1s; }
.v-gate-word i:nth-child(2) { --c: var(--beam-purple); animation-delay: 0.17s; }
.v-gate-word i:nth-child(3) { --c: var(--beam-sky); animation-delay: 0.24s; }
.v-gate-word i:nth-child(4) { --c: var(--beam-yellow); animation-delay: 0.31s; }
.v-gate-word i:nth-child(5) { --c: var(--beam-green); animation-delay: 0.38s; }

.v-gate-line {
  display: block;
  min-height: 2.3em;
  line-height: 1.12;
  text-align: center;
  text-wrap: balance;
}
.v-gate-line b {
  font-weight: inherit;
  color: var(--c);
  text-shadow: 0 0 24px var(--c);
}
/* Once charging starts the copy speaks up: full white, not the idle grey */
.v-gate.charging .v-gate-cta {
  color: var(--on-ink);
}
.v-gate-line.slam {
  animation: gate-slam 0.45s cubic-bezier(0.2, 1.4, 0.4, 1) both;
}

/* The charge: three arcs round the orb, a third each, drawn in a tap at a
   time in their beam colour */
.v-gate-charge {
  position: absolute;
  inset: -20px;
  width: calc(100% + 40px);
  height: calc(100% + 40px);
  overflow: visible;
  fill: none;
  pointer-events: none;
}
.v-gate-charge circle {
  stroke-dasharray: 95.5 400;
  stroke-linecap: round;
}
.v-gate-charge .track {
  stroke: rgba(255, 255, 255, 0.14);
  stroke-width: 2;
}
.v-gate-charge .fill {
  stroke: var(--c);
  stroke-width: 3.5;
  stroke-dashoffset: 95.5;
  filter: drop-shadow(0 0 4px var(--c));
  transition: stroke-dashoffset 0.32s cubic-bezier(0.3, 0.9, 0.3, 1);
}
.v-gate-charge .fill.on {
  stroke-dashoffset: 0;
}

/* The pulse quickens and the glow climbs with each third of charge */
html.gate .v-gate.charging {
  --cycle: calc(3.2s / (1 + var(--level) * 1.2));
}
.v-gate.charging .v-gate-ring::after {
  filter: blur(calc(14px + var(--level) * 6px));
  opacity: calc(0.45 + var(--level) * 0.18);
}
.v-gate.charging .v-gate-beam i {
  opacity: calc(0.55 + var(--level) * 0.15);
}

/* Each tap: the orb takes a knock and a ring of the tap's colour blasts off */
.v-gate-orb.hit {
  animation: gate-hit 0.5s cubic-bezier(0.3, 1.5, 0.5, 1);
}
.v-gate-orb::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: radial-gradient(circle, var(--c, #fff), transparent 70%);
  opacity: 0;
  pointer-events: none;
}
.v-gate-orb.hit::before {
  animation: gate-flash 0.5s ease-out;
}
.v-gate-shock {
  position: absolute;
  inset: 0;
  border: 6px solid var(--c, #fff);
  border-radius: 50%;
  opacity: 0;
  pointer-events: none;
}
.v-gate-shock.go {
  animation: gate-shock 0.7s cubic-bezier(0.1, 0.7, 0.3, 1);
}

/* The blast around each tap: sparks on a canvas over the hero, a flash of
   the tap's colour, and the whole gate kicked, harder each time */
.v-gate-sparks,
.v-gate-flash {
  display: none;
}
html.gate .v-gate-sparks,
html.gate .v-gate-flash {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: block;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
html.gate .v-gate-flash {
  background: radial-gradient(circle at 50% 45%, var(--c, #fff), transparent 75%);
  opacity: 0;
}
.v-gate-flash.go {
  animation: gate-flash-screen 0.35s ease-out;
}
.v-gate-flash.white {
  --c: #fff;
  animation: gate-flash-screen 0.6s ease-out;
}
html.gate .v-gate.shake {
  --kick: calc(4px + var(--level, 1) * 4px);
  animation: gate-shake 0.38s cubic-bezier(0.3, 0, 0.3, 1);
}
html.gate .v-gate.blast {
  --kick: 22px;
  animation: gate-shake 0.55s cubic-bezier(0.3, 0, 0.3, 1);
}

/* Full: the orb strains against the charge until it lets go */
.v-gate.full .v-gate-orb {
  animation: gate-strain 0.09s linear infinite;
}
.v-gate.full .v-gate-orb.hit {
  animation: gate-hit 0.5s cubic-bezier(0.3, 1.5, 0.5, 1), gate-strain 0.09s 0.5s linear infinite;
}

@media (hover: hover) {
  .v-gate:hover .v-gate-ring::after {
    opacity: 0.8;
  }
  .v-gate:hover .v-gate-cta {
    color: var(--on-ink);
  }
}

@keyframes gate-hit {
  15% {
    scale: 0.8;
  }
  45% {
    scale: 1.14;
  }
}

@keyframes gate-flash {
  0% {
    opacity: 0.55;
  }
  100% {
    opacity: 0;
  }
}

@keyframes gate-shock {
  0% {
    opacity: 1;
    transform: scale(1);
  }
  100% {
    opacity: 0;
    transform: scale(2.4);
    border-width: 1px;
  }
}

@keyframes gate-slam {
  0% {
    opacity: 0;
    transform: scale(1.7);
    filter: blur(8px);
  }
  55% {
    transform: scale(0.96);
  }
}

@keyframes gate-flash-screen {
  0% {
    opacity: 0.5;
  }
  100% {
    opacity: 0;
  }
}

@keyframes gate-shake {
  10% {
    translate: calc(var(--kick) * -1) calc(var(--kick) * 0.6);
  }
  25% {
    translate: var(--kick) calc(var(--kick) * -0.8);
  }
  40% {
    translate: calc(var(--kick) * -0.6) calc(var(--kick) * 0.4);
  }
  60% {
    translate: calc(var(--kick) * 0.3) calc(var(--kick) * -0.2);
  }
  80% {
    translate: calc(var(--kick) * -0.1) 0;
  }
}

@keyframes gate-strain {
  25% {
    rotate: 1.2deg;
  }
  75% {
    rotate: -1.2deg;
  }
}

@keyframes gate-in {
  from {
    opacity: 0;
    transform: scale(0.6);
  }
}

@keyframes gate-rise {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
}

@keyframes gate-spin {
  to {
    rotate: 1turn;
  }
}

@keyframes gate-pulse {
  0%,
  8% {
    transform: translateX(0);
    opacity: 0;
  }
  12% {
    opacity: 1;
  }
  40% {
    transform: translateX(50vw);
    opacity: 1;
  }
  41%,
  100% {
    transform: translateX(50vw);
    opacity: 0;
  }
}

@keyframes gate-charge {
  0%,
  38% {
    opacity: 0.45;
  }
  42% {
    opacity: 1;
  }
  100% {
    opacity: 0.45;
  }
}

@keyframes gate-num {
  0%,
  39% {
    transform: scale(1);
  }
  43% {
    transform: scale(1.06);
    text-shadow: 0 0 24px rgba(255, 255, 255, 0.55);
  }
  60%,
  100% {
    transform: scale(1);
  }
}

@keyframes gate-wave {
  0%,
  40% {
    opacity: 0;
    transform: scale(1);
  }
  41% {
    opacity: 0.7;
  }
  75%,
  100% {
    opacity: 0;
    transform: scale(1.7);
  }
}

@keyframes gate-letter {
  0%,
  44% {
    color: inherit;
    transform: none;
  }
  48% {
    color: var(--c);
    transform: translateY(-0.12em);
    text-shadow: 0 0 18px var(--c);
  }
  62%,
  100% {
    color: inherit;
    transform: none;
  }
}

/* ---- Waking: added on the tap, gone with the gate a second and a bit on -- */

html.waking .v-gate {
  cursor: default;
  pointer-events: none;
}
html.waking .v-gate-orb {
  transition:
    translate 0.95s cubic-bezier(0.7, 0, 0.2, 1),
    scale 0.95s cubic-bezier(0.7, 0, 0.2, 1);
}
html.waking .v-gate-beam,
html.waking .v-gate-ring::after,
html.waking .v-gate-num,
html.waking .v-gate-word i {
  animation: none;
}
html.waking .v-gate-beam {
  opacity: 0;
  transition: opacity 0.2s;
}
html.waking .v-gate-ring {
  animation: gate-spin 0.9s cubic-bezier(0.5, 0, 0.3, 1) both, gate-out 0.5s 0.35s both;
}
html.waking .v-gate-waves i {
  animation: gate-burst 1s cubic-bezier(0.15, 0.7, 0.3, 1) both;
}
html.waking .v-gate-waves i:nth-child(n) {
  animation-delay: calc(var(--n, 0) * 0.06s);
}
html.waking .v-gate-waves i:nth-child(2) { --n: 1; }
html.waking .v-gate-waves i:nth-child(3) { --n: 2; }
html.waking .v-gate-waves i:nth-child(4) { --n: 3; }
html.waking .v-gate-waves i:nth-child(5) { --n: 4; }
html.waking .v-gate-num small {
  animation: gate-out 0.4s 0.2s both;
}
html.waking .v-gate-cta {
  animation: none;
}
html.waking .v-gate-word i {
  color: var(--c);
  animation: gate-scatter 0.7s cubic-bezier(0.3, 0, 0.6, 1) both;
  animation-delay: calc(var(--n, 0) * 0.05s);
}
html.waking .v-gate-word i:nth-child(2) { --n: 1; }
html.waking .v-gate-word i:nth-child(3) { --n: 2; }
html.waking .v-gate-word i:nth-child(4) { --n: 3; }
html.waking .v-gate-word i:nth-child(5) { --n: 4; }
html.waking .v-gate-cta {
  transition: color 0.3s, opacity 0.4s 0.2s;
  opacity: 0;
}

/* The hero comes up behind the orb in reading order; the beam lights from
   the left edge as if the orb had just left it */
html.waking .v-hero-in > *,
html.waking .v-meter {
  opacity: 1;
  animation: gate-rise 0.8s cubic-bezier(0.2, 0.8, 0.3, 1) both;
}
html.waking .points-kicker { animation-delay: 0.3s; }
html.waking .v-title { animation-delay: 0.38s; }
html.waking .v-hero .line { animation-delay: 0.46s; }
html.waking .v-track { animation: none; }
html.waking .v-meter {
  animation: gate-land 0.25s 0.95s both;
}
html.waking .v-beam {
  opacity: 1;
  animation: gate-ignite 0.8s 0.4s cubic-bezier(0.6, 0, 0.2, 1) both;
}
html.waking .v-gate-orb,
html.waking .v-gate.full .v-gate-orb {
  animation: gate-out 0.2s 0.95s both;
}

@keyframes gate-out {
  to {
    opacity: 0;
  }
}

@keyframes gate-land {
  from {
    opacity: 0;
  }
}

@keyframes gate-burst {
  0% {
    opacity: 0.9;
    transform: scale(1);
    border-width: 3px;
  }
  100% {
    opacity: 0;
    transform: scale(5);
    border-width: 1px;
  }
}

@keyframes gate-scatter {
  30% {
    transform: translateY(-0.3em);
    text-shadow: 0 0 22px var(--c);
  }
  100% {
    opacity: 0;
    transform: translateY(-1.4em) scale(0.6);
  }
}

@keyframes gate-ignite {
  from {
    clip-path: inset(0 100% 0 0);
  }
  to {
    clip-path: inset(0 0 0 0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .v-gate-orb,
  .v-gate-ring,
  .v-gate-ring::after,
  .v-gate-num,
  .v-gate-beam::after,
  .v-gate-waves i,
  .v-gate-cta,
  .v-gate-word i,
  html.waking .v-gate-ring,
  html.waking .v-gate-waves i,
  html.waking .v-gate-word i,
  html.waking .v-hero-in > *,
  html.waking .v-beam,
  html.waking .v-meter {
    animation: none;
  }
  .v-gate-beam::after,
  .v-gate-waves i {
    display: none;
  }
  html.waking .v-gate-orb {
    transition: none;
    animation: gate-out 0.3s both;
  }
}

/* ---- Welcome back: one moment each time the hero comes round ------------ */

.v-title {
  position: relative;
}

/* Pluck: the stripes shake a little out of step, as a struck string does */
.v-beam.pluck span {
  animation: pluck 1s cubic-bezier(0.3, 0.6, 0.4, 1) both;
}
.v-beam.pluck span:nth-child(2) { animation-delay: 0.025s; }
.v-beam.pluck span:nth-child(3) { animation-delay: 0.05s; }
.v-beam.pluck span:nth-child(4) { animation-delay: 0.075s; }
.v-beam.pluck span:nth-child(5) { animation-delay: 0.1s; }

@keyframes pluck {
  10% {
    transform: translateY(-6px);
    filter: brightness(1.6);
  }
  22% { transform: translateY(5px); }
  34% { transform: translateY(-3.5px); }
  46% { transform: translateY(2.5px); }
  58% { transform: translateY(-1.5px); }
  70% { transform: translateY(0.75px); }
  82%,
  100% {
    transform: none;
    filter: none;
  }
}

/* Five at once: the landing splits the counter into all five colours */
.gc.burst {
  animation: gc-burst 0.9s cubic-bezier(0.2, 0.8, 0.3, 1);
}

@keyframes gc-burst {
  15% {
    transform: scale(1.07);
    text-shadow:
      -0.03em 0 var(--beam-red),
      -0.015em 0 var(--beam-purple),
      0 0.015em var(--beam-sky),
      0.015em 0 var(--beam-yellow),
      0.03em 0 var(--beam-green);
  }
}

/* Spin: each digit rolls on to its own place again, a full turn. The roll
   is on `translate`, so it rides on top of the odometer's own transform. */
.gc.spin .od-s {
  animation: od-spin 0.9s cubic-bezier(0.5, 0, 0.25, 1) both;
  animation-delay: calc(var(--i, 0) * 60ms);
}

@keyframes od-spin {
  0% { translate: 0 0; }
  49.99% { translate: 0 var(--a); }
  50% { translate: 0 var(--b); }
  100% { translate: 0 0; }
}

/* Cascade: a coloured copy of GLEAM laid exactly over the word */
.v-cascade {
  position: absolute;
  top: 0;
  left: 0;
  display: inline-flex;
  white-space: nowrap;
  pointer-events: none;
}
.v-cascade i {
  font-style: normal;
  color: var(--c);
  animation: cascade 1.1s ease-out both;
}

@keyframes cascade {
  0% {
    opacity: 0;
    transform: translateY(0.12em);
  }
  25% {
    opacity: 1;
    transform: translateY(-0.06em);
    text-shadow: 0 0 0.25em var(--c);
  }
  100% {
    opacity: 0;
    transform: none;
  }
}

/* The fifth return's line, once ever */
.v-echo {
  position: absolute;
  bottom: 100%;
  left: 0;
  margin: 0 0 12px;
  font-size: 0.9375rem;
  font-weight: 600;
  white-space: nowrap;
  color: var(--on-ink);
  animation: echo 7s ease both;
}

@media (min-width: 900px) {
  .v-echo {
    left: auto;
    right: 0;
  }
}

@keyframes echo {
  0% {
    opacity: 0;
    transform: translateY(8px);
  }
  8%,
  85% {
    opacity: 1;
    transform: none;
  }
  100% {
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .v-beam.pluck span,
  .gc.burst,
  .gc.spin .od-s,
  .v-cascade i {
    animation: none;
  }
  .v-echo {
    animation: echo 7s step-end both;
  }
}

/* Time moving fast, either way: the counter splits a little into red and
   sky, like light through a prism held at speed */
.gc {
  transition: text-shadow 0.25s;
}
.gc.scrub {
  text-shadow:
    -0.025em 0 color-mix(in srgb, var(--beam-red) 70%, transparent),
    0.025em 0 color-mix(in srgb, var(--beam-sky) 70%, transparent);
}

@media (prefers-reduced-motion: reduce) {
  .gc.scrub {
    text-shadow: none;
  }
}

/* ---- Flavours: how a milestone moves as a pass goes over it ------------- */
/* Forward: the milestone arrives. --c is its beam colour. */

.tl-item.fx-pop::after {
  animation: fx-pop 0.7s cubic-bezier(0.2, 0.9, 0.3, 1.3);
}
.tl-item.fx-ring::after {
  animation: fx-ring 0.9s ease-out;
}
.tl-item.fx-prism::after {
  animation: fx-prism 0.6s steps(1) both;
}
.tl-item.fx-prism .tl-card {
  animation: fx-prism-card 0.9s ease-out;
}
.tl-item.fx-rise .tl-card {
  animation: fx-rise 0.7s cubic-bezier(0.2, 0.8, 0.3, 1);
}

@keyframes fx-pop {
  0% {
    transform: scale(2.6);
    background: var(--c);
    box-shadow: 0 0 22px 6px var(--c);
  }
}
@keyframes fx-ring {
  0% {
    box-shadow: 0 0 0 0 var(--c);
  }
  100% {
    box-shadow: 0 0 0 26px transparent;
  }
}
@keyframes fx-prism {
  0% { background: var(--beam-red); }
  20% { background: var(--beam-purple); }
  40% { background: var(--beam-sky); }
  60% { background: var(--beam-yellow); }
  80% { background: var(--beam-green); }
}
@keyframes fx-prism-card {
  0% {
    border-left-color: var(--c);
    box-shadow: -6px 0 18px -8px var(--c);
  }
}
@keyframes fx-rise {
  0% {
    transform: translateY(12px);
    text-shadow: 0 0 14px var(--c);
  }
}

/* Back: the milestone is undone, the way a tape runs backwards */

.tl-item.fx-glitch .tl-card {
  animation: fx-glitch 0.4s steps(1);
}
.tl-item.fx-implode::after {
  animation: fx-implode 0.55s ease-in-out;
}
.tl-item.fx-implode .tl-card {
  animation: fx-shrink 0.55s ease-in-out;
}
.tl-item.fx-smear .tl-card {
  animation: fx-smear 0.5s ease-out;
}
.tl-item.fx-flicker .tl-card {
  animation: fx-flicker 0.45s steps(1);
}

@keyframes fx-glitch {
  0% {
    transform: translateX(-5px);
    text-shadow: 3px 0 var(--beam-red), -3px 0 var(--beam-sky);
  }
  25% {
    transform: translateX(4px);
    text-shadow: -2px 0 var(--beam-red), 2px 0 var(--beam-sky);
  }
  50% {
    transform: translateX(-2px);
    text-shadow: 1px 0 var(--beam-purple);
  }
  75% {
    transform: none;
  }
}
@keyframes fx-implode {
  30% {
    transform: scale(1.9);
    background: var(--c);
  }
  65% {
    transform: scale(0.2);
  }
}
@keyframes fx-shrink {
  50% {
    transform: scale(0.96);
    filter: blur(1px);
  }
}
@keyframes fx-smear {
  0% {
    transform: skewX(-14deg) translateX(18px);
    filter: blur(3px);
  }
}
@keyframes fx-flicker {
  0% { opacity: 1; }
  15% { opacity: 0.1; }
  30% { opacity: 0.9; }
  45% { opacity: 0.2; }
  60% { opacity: 0.7; }
}

/* The closing beam flares as its chord lands */
.beam.fx-closing {
  animation: fx-closing 1.2s ease-out;
}

@keyframes fx-closing {
  12% {
    filter: brightness(1.7) saturate(1.3);
    transform: scaleY(1.6);
  }
}

@media (prefers-reduced-motion: reduce) {
  .tl-item[class*="fx-"]::after,
  .tl-item[class*="fx-"] .tl-card,
  .beam.fx-closing {
    animation: none;
  }
}

/* ---- Rainbow arcs: a bead of light, and a spark where a string is struck - */

.cut path.arc-glint[stroke] {
  stroke-width: 5;
  stroke-linecap: round;
}
/* A blurred copy underneath glows in the band's own colour, which reads on
   paper and on ink alike. The blur is on the group, so it softens the
   clipped bead's ends rather than being cut square by the clip. */
.arc-glint-glow {
  opacity: 0.55;
  filter: blur(6px);
}
.cut .arc-glint-glow path[stroke] {
  stroke-width: 16;
}

.arc-spark {
  position: absolute;
  width: 18px;
  height: 18px;
  margin: -9px 0 0 -9px;
  border-radius: 50%;
  background: radial-gradient(circle, #fff 15%, var(--c) 45%, transparent 70%);
  pointer-events: none;
  animation: arc-spark 0.7s ease-out both;
}

@keyframes arc-spark {
  0% {
    opacity: 1;
    transform: scale(0.4);
  }
  100% {
    opacity: 0;
    transform: scale(2.6);
  }
}

/* ---- Wallet lines: each pass moves the sentence its own way -------------- */

.v-big span.fx-pop,
.v-sub b.fx-pop,
.v-step h3.fx-pop,
.vision-today strong.fx-pop,
.v-stake-h.fx-pop,
.v-final .heading.fx-pop { animation: line-pop 0.6s cubic-bezier(0.2, 0.9, 0.3, 1.3); }
.v-big span.fx-ring,
.v-sub b.fx-ring,
.v-step h3.fx-ring,
.vision-today strong.fx-ring,
.v-stake-h.fx-ring,
.v-final .heading.fx-ring { animation: line-glow 0.9s ease-out; }
.v-big span.fx-prism,
.v-sub b.fx-prism,
.v-step h3.fx-prism,
.vision-today strong.fx-prism,
.v-stake-h.fx-prism,
.v-final .heading.fx-prism { animation: line-prism 0.6s steps(1); }
.v-big span.fx-rise,
.v-sub b.fx-rise,
.v-step h3.fx-rise,
.vision-today strong.fx-rise,
.v-stake-h.fx-rise,
.v-final .heading.fx-rise { animation: fx-rise 0.7s cubic-bezier(0.2, 0.8, 0.3, 1); }
.v-big span.fx-glitch,
.v-sub b.fx-glitch,
.v-step h3.fx-glitch,
.vision-today strong.fx-glitch,
.v-stake-h.fx-glitch,
.v-final .heading.fx-glitch { animation: fx-glitch 0.4s steps(1); }
.v-big span.fx-implode,
.v-sub b.fx-implode,
.v-step h3.fx-implode,
.vision-today strong.fx-implode,
.v-stake-h.fx-implode,
.v-final .heading.fx-implode { animation: fx-shrink 0.55s ease-in-out; }
.v-big span.fx-smear,
.v-sub b.fx-smear,
.v-step h3.fx-smear,
.vision-today strong.fx-smear,
.v-stake-h.fx-smear,
.v-final .heading.fx-smear { animation: fx-smear 0.5s ease-out; }
.v-big span.fx-flicker,
.v-sub b.fx-flicker,
.v-step h3.fx-flicker,
.vision-today strong.fx-flicker,
.v-stake-h.fx-flicker,
.v-final .heading.fx-flicker { animation: fx-flicker 0.45s steps(1); }

@keyframes line-pop {
  0% { transform: scale(1.06); }
}
@keyframes line-glow {
  0% { text-shadow: 0 0 0.35em var(--c); }
}
@keyframes line-prism {
  0% { color: var(--beam-red); }
  20% { color: var(--beam-purple); }
  40% { color: var(--beam-sky); }
  60% { color: var(--beam-yellow); }
  80% { color: var(--beam-green); }
}

/* ---- Stake cards: coming back into view, forwards or rewound ------------- */

.perk.fx-lift { animation: card-lift 0.7s cubic-bezier(0.2, 0.8, 0.3, 1); }
.perk.fx-tilt { animation: card-tilt 0.8s cubic-bezier(0.2, 0.8, 0.3, 1); }
.perk.fx-bloom { animation: card-bloom 0.9s ease-out; }
.perk.fx-glitch .perk-copy { animation: fx-glitch 0.4s steps(1); }
.perk.fx-smear .perk-copy { animation: fx-smear 0.5s ease-out; }
.perk.fx-flicker .perk-art { animation: fx-flicker 0.45s steps(1); }

@keyframes card-lift {
  0% { transform: translateY(24px); }
}
@keyframes card-tilt {
  0% { transform: perspective(900px) rotateX(8deg) translateY(10px); }
}
@keyframes card-bloom {
  0% { box-shadow: 0 0 0 0 transparent; }
  25% { box-shadow: 0 0 60px -10px var(--c); }
}

/* ---- The angled cuts: struck lines, a different look each pass ----------- */
/* Each line's animation-delay is set from script to match its note. */

.cut-angle[class*="strike-"] line {
  animation-duration: 0.55s;
  animation-timing-function: ease-out;
  animation-fill-mode: both;
}
.cut-angle.strike-flare line { animation-name: strike-flare; }
.cut-angle.strike-slide line { animation-name: strike-slide; }
.cut-angle.strike-flash line { animation-name: strike-flash; animation-timing-function: steps(1); }
.cut-angle.strike-jolt line { animation-name: strike-jolt; }

@keyframes strike-flare {
  20% {
    stroke-width: 6;
    filter: drop-shadow(0 0 4px currentColor);
  }
}
/* Slides along its own length, the way the scroll is going */
@keyframes strike-slide {
  25% {
    transform: translateX(calc(var(--dir, 1) * 28px));
    stroke-width: 4;
  }
}
@keyframes strike-flash {
  0% { opacity: 0.1; }
  25% { opacity: 1; stroke-width: 5; }
  50% { opacity: 0.3; }
  75% { opacity: 1; }
}
/* Knocked off its line and settling back, like a plucked string */
@keyframes strike-jolt {
  15% { transform: translateY(calc(var(--dir, 1) * 5px)); }
  35% { transform: translateY(calc(var(--dir, 1) * -3px)); }
  55% { transform: translateY(calc(var(--dir, 1) * 1.5px)); }
  75% { transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .v-big span[class*="fx-"],
  .perk[class*="fx-"],
  .perk[class*="fx-"] .perk-copy,
  .perk[class*="fx-"] .perk-art,
  .cut-angle line {
    animation: none;
  }
}

/* ---- Chord changes: the section that turned the drone shows it ----------- */

/* A sweep of the chord's colour through the heading. The fill goes
   transparent so the sweep shows, with currentColor either side of the band
   keeping the text its own colour. */
.fx-chord-glint h2 {
  background: linear-gradient(100deg, currentColor 42%, var(--c) 50%, currentColor 58%) 0 0 / 300% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: chord-glint 1.4s ease-in-out;
}
.fx-chord-glint.chord-up h2 {
  animation-direction: reverse;
}
@keyframes chord-glint {
  from { background-position: 100% 0; }
  to { background-position: 0 0; }
}

.fx-chord-breathe h2 {
  animation: chord-breathe 1.6s ease-in-out;
}
@keyframes chord-breathe {
  45% {
    transform: translateY(-3px) scale(1.012);
    text-shadow: 0 0 24px color-mix(in srgb, var(--c) 35%, transparent);
  }
}
.fx-chord-breathe.chord-up h2 {
  animation-name: chord-breathe-up;
}
@keyframes chord-breathe-up {
  45% {
    transform: translateY(3px) scale(1.012);
    text-shadow: 0 0 24px color-mix(in srgb, var(--c) 35%, transparent);
  }
}

.fx-chord-bar h2 {
  position: relative;
}
.fx-chord-bar h2::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -14px;
  width: 120px;
  height: 3px;
  background: var(--beam-run);
  transform-origin: left;
  animation: chord-bar 1.8s cubic-bezier(0.2, 0.8, 0.3, 1) both;
}
.fx-chord-bar.chord-up h2::after {
  transform-origin: right;
}
@keyframes chord-bar {
  0% { transform: scaleX(0); opacity: 1; }
  40% { transform: scaleX(1); opacity: 1; }
  100% { transform: scaleX(1); opacity: 0; }
}

.fx-chord-kicker .points-kicker {
  animation: chord-kicker 1.8s ease-in-out;
}
@keyframes chord-kicker {
  35% {
    color: var(--c);
    letter-spacing: 0.32em;
  }
}

/* ---- Whoosh threads ------------------------------------------------------- */

.v-air {
  position: fixed;
  top: 0;
  z-index: 15;
  width: 2px;
  height: 45vh;
  border-radius: 1px;
  background: linear-gradient(to bottom, transparent, var(--c), transparent);
  opacity: 0;
  pointer-events: none;
  animation: air-down 0.55s cubic-bezier(0.4, 0, 0.6, 1) both;
}
.v-air.up {
  animation-name: air-up;
}
@keyframes air-down {
  0% { transform: translateY(-50vh); opacity: 0; }
  30% { opacity: 0.45; }
  100% { transform: translateY(110vh); opacity: 0; }
}
@keyframes air-up {
  0% { transform: translateY(110vh); opacity: 0; }
  30% { opacity: 0.45; }
  100% { transform: translateY(-50vh); opacity: 0; }
}

/* ---- Tokenomics step numbers counting in light ---------------------------- */

.v-step-n.count {
  animation: step-count 0.7s cubic-bezier(0.2, 0.8, 0.3, 1.2) both;
}
@keyframes step-count {
  30% {
    color: var(--c);
    transform: scale(1.25);
    text-shadow: 0 0 14px color-mix(in srgb, var(--c) 60%, transparent);
  }
}

@media (prefers-reduced-motion: reduce) {
  [class*="fx-chord-"] h2,
  [class*="fx-chord-"] h2::after,
  [class*="fx-chord-"] .points-kicker,
  .v-step-n.count {
    animation: none;
  }
  .v-air {
    display: none;
  }
}

/* ---- "You earn GLEAM by" signals, played forwards or rewound -------------- */

.v-sig.sig-fwd i,
.v-sig.sig-back i {
  animation: sig-hit 0.55s ease-out;
}
.v-sig-hold.sig-fwd::after {
  animation: sig-ring 0.7s ease-out;
}
/* Rewound, the ring falls in rather than spreading out */
.v-sig-hold.sig-back::after {
  animation: sig-ring 0.7s ease-in reverse;
}
.v-sig-invite.sig-fwd::after {
  animation: sig-run 0.55s cubic-bezier(0.5, 0, 0.5, 1);
}
.v-sig-invite.sig-fwd i:last-child {
  animation-delay: 0.4s;
}
/* Rewound, the light runs from the friend back to you */
.v-sig-invite.sig-back::after {
  animation: sig-run 0.55s cubic-bezier(0.5, 0, 0.5, 1) reverse;
}
.v-sig-invite.sig-back i:first-child {
  animation-delay: 0.4s;
}

/* ---- The prism gathering its spectrum back in ------------------------------ */

.v-prism.reset * {
  transition: none !important;
}
/* Reverse order to the split: the colours fold in, the pane goes, then the
   white light withdraws the way it came. */

.motion .v-prism.gather .pr-out {
  transition: stroke-dashoffset 0.45s cubic-bezier(0.5, 0, 0.9, 0.5);
}
.motion .v-prism.gather .pr-pane {
  transition:
    opacity 0.25s 0.4s,
    transform 0.3s ease-in 0.4s;
}
.motion .v-prism.gather .pr-in {
  transition: stroke-dashoffset 0.5s cubic-bezier(0.5, 0, 0.9, 0.5) 0.55s;
}

@media (prefers-reduced-motion: reduce) {
  .v-sig[class*="sig-"] i,
  .v-sig[class*="sig-"]::after {
    animation: none;
  }
}

/* ---- Points converting to GLEAM tokens -------------------------------------- */

.v-convert {
  position: relative;
}
.v-tokens {
  font-weight: 600;
  color: var(--fg);
  white-space: nowrap;
}
.v-tokens-word i {
  display: inline-block;
  font-style: normal;
}
.v-tokens-word i.lit {
  animation: tok-letter 0.9s ease-out both;
  animation-delay: var(--d, 0s);
}
@keyframes tok-letter {
  30% {
    color: var(--c);
    transform: translateY(-0.12em);
    text-shadow: 0 0 0.4em var(--c);
  }
}

/* The light that carries points into tokens. rotate and scale are set
   separately, so the run along the line doesn't fight the angle. */
.v-convert-beam {
  position: absolute;
  height: 2px;
  margin-top: -1px;
  border-radius: 1px;
  background: var(--beam-run);
  transform-origin: left center;
  scale: 0 1;
  opacity: 0;
  pointer-events: none;
}
.v-convert-beam.back {
  transform-origin: right center;
}
.v-convert-beam.run {
  animation: convert-run 0.6s cubic-bezier(0.3, 0, 0.3, 1) both;
}
@keyframes convert-run {
  0% {
    scale: 0 1;
    opacity: 1;
  }
  60% {
    scale: 1 1;
    opacity: 1;
  }
  100% {
    scale: 1 1;
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .v-tokens-word i.lit,
  .v-convert-beam.run {
    animation: none;
  }
}

/* ---- Tokenomics steps: a ring for each step passed, a spark on the rail --- */

/* Above the spark, which glows along the rail between them and tucks in
   behind the node it arrives at */
.v-step-n {
  z-index: 2;
  transition: box-shadow 0.4s var(--ease-out);
}
.v-step.passed .v-step-n {
  box-shadow:
    0 0 0 3px color-mix(in srgb, var(--c) 75%, transparent),
    0 0 18px -2px var(--c);
}

.v-flow-spark {
  position: absolute;
  z-index: 1;
  left: calc(var(--node) / 2);
  top: calc(var(--node) / 2);
  width: 14px;
  height: 14px;
  margin: -7px 0 0 -7px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 14px 5px var(--c, var(--beam-red));
  opacity: 0;
  pointer-events: none;
  transition:
    top 0.7s cubic-bezier(0.3, 0.8, 0.3, 1),
    opacity 0.3s,
    box-shadow 0.5s;
}
.v-flow-spark.on {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .v-flow-spark {
    transition: none;
  }
}
